小程序中的canvas和其他端的稍有不同,大多数canvas库在小程序中都不能直接import后使用,分享项目中小程序绘制canvas图片常用的一些方法,可以保存文件后直接使用,以下代码赶工出来的很粗糙,目的为抛砖引玉,或解急需使用的燃眉之急;
功能预览:
/*
name:makeCanvas
author:I1326
tel:
weChat:
*/
const promisify = require('promisify');
const downFile = promisify(wx.downloadFile);
let realWidth,realHeight;
// 计算实际尺寸
function getPx(el){
return new Promise(function (resolve, reject){
let canvasQuery = wx.createSelectorQuery();
canvasQuery.select('#'+el).boundingClientRect();
canvasQuery.exec(function (res) {
realWidth = res[0].width;
realHeight = res[0].height;
resolve(realWidth, realHeight)
});
})
}
function changeR(w, h){
let tmpW = w,
tmpH = h;
tmpW = w * realWidth / 340;
tmpH = h * realHeight / 380;
return {
w: tmpW,
h: tmpH
};
}
//保存网路图片
function saveIntPic(_url,callback){
// wx.showLoading({ })
return downFile({ url: _url }).then(img => {
callback(img.tempFilePath);
}, err => {
console.log('save pic error')
})
}
// 将生成的canvas图片,转为真实图片
function getPic(el,callback){
wx.canvasToTempFilePath({
x: 0,
y: 0,
canvasId: el,
success: function (res) {
callback(res.tempFilePath)
},
fail: function (res) {
console.log('err==')
}
})
}
//绘制背景--把图片素材推进画布
function postBg(_img,ctx) {
return new Promise(resolve=>{
getPx(ctx.canvasId).then(function(){
ctx.save();
ctx.drawImage(_img, 0, 0, realWidth, realHeight);
ctx.restore();
resolve();
})
})
}
//插入图片素材到画布
function postImg(_img,ctx,dx=0,dy=0,dw=realHeight,dh=realHeight) {
return new Promise(resolve=>{
getPx(ctx.canvasId).then(function(){
let xy = changeR(dx,dy);
let wh = changeR(dw, dh);
ctx.save();
ctx.drawImage(_img, xy.w,xy.h, wh.w, wh.h);
ctx.restore();
})
})
}
//插字
function addFont(ctx,x=0,y=0,txt='.',col='#000',size=12,align='left'){
getPx(ctx.canvasId).then(function () {
let xy = changeR(x, y);
let wh = changeR(size, 1);
ctx.save();
ctx.setFontSize(wh.w);
ctx.setFillStyle(col);
ctx.setTextAlign(align);
ctx.fillText(txt,xy.w,xy.h);
ctx.restore();
})
}
//插线
function addLine(ctx,x=0,y=0,dx=0,dy=0,wid=1,col='#000'){
getPx(ctx.canvasId).then(function () {
let xy = changeR(x, y);
let wh = changeR(dx,dy);
let _width = changeR(wid,1);
ctx.save();
ctx.beginPath()
ctx.setLineWidth(_width.w)
ctx.strokeStyle = col;
ctx.moveTo(xy.w,xy.h)
ctx.lineTo(wh.w, wh.h)
ctx.stroke()
ctx.restore();
})
}
// 绘制圆环
function ring(ctx, x, y, w,ho,col1,no,col2){
const hodeg = ho / (ho + no);
getPx(ctx.canvasId).then(function () {
let xy = changeR(x, y);
let wh = changeR(w, 1);
ctx.save()
ctx.beginPath();
ctx.lineWidth = wh.w;
ctx.strokeStyle = col1;
ctx.arc(xy.w, xy.h, wh.w, 0, Math.PI * 2 * hodeg, false);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.strokeStyle = col2;
ctx.arc(xy.w, xy.h, wh.w, Math.PI * 2 * hodeg, Math.PI * 2, false);
ctx.stroke();
ctx.closePath();
ctx.restore();
})
}
/**该方法用来绘制一个有填充色的圆角矩形
* cxt:canvas的上下文环境
* x:左上角x轴坐标
* y:左上角y轴坐标
* width:矩形的宽度
* height:矩形的高度
* radius:圆的半径
* fillColor:填充颜色
**/
function fillRoundRect(cxt, x, y, width, height, radius, fillColorA, fillColorB) {
getPx(cxt.canvasId).then(function () {
let xy = changeR(x, y);
//圆的直径必然要小于矩形的宽高
if (2 * radius > width || 2 * radius > height) { return false; }
cxt.save();
cxt.translate(xy.w, xy.h);
//绘制圆角矩形的各个边
drawRoundRectPath(cxt, width, height, radius);
let gradient = cxt.createLinearGradient(width - 90, height, width, height);
gradient.addColorStop(0, fillColorA);
gradient.addColorStop(1, fillColorB);
cxt.fillStyle = gradient; //若是给定了值就用给定的值否则给予默认值
cxt.fill();
cxt.restore();
})
}
/**该方法用来绘制圆角矩形
* cxt:canvas的上下文环境
* x:左上角x轴坐标
* y:左上角y轴坐标
* width:矩形的宽度
* height:矩形的高度
* radius:圆的半径
* lineWidth:线条粗细
* strokeColor:线条颜色
**/
function strokeRoundRect(cxt, x, y, width, height, radius, /*optional*/ lineWidth, /*optional*/ strokeColor) {
//圆的直径必然要小于矩形的宽高
if (2 * radius > width || 2 * radius > height) { return false; }
cxt.save();
cxt.translate(x, y);
//绘制圆角矩形的各个边
drawRoundRectPath(cxt, width, height, radius);
cxt.lineWidth = lineWidth || 2; //若是给定了值就用给定的值否则给予默认值2
cxt.strokeStyle = strokeColor || "#000";
cxt.stroke();
cxt.restore();
}
function drawRoundRectPath(cxt, width, height, radius) {
cxt.beginPath(0);
//从右下角顺时针绘制,弧度从0到1/2PI
cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
//矩形下边线
cxt.lineTo(radius, height);
//左下角圆弧,弧度从1/2PI到PI
cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
//矩形左边线
cxt.lineTo(0, radius);
//左上角圆弧,弧度从PI到3/2PI
cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
//上边线
cxt.lineTo(width - radius, 0);
//右上角圆弧
cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2)
//右边线
cxt.lineTo(width, height - radius);
cxt.closePath();
}
module.exports = {
saveIntPic: saveIntPic,
getPic: getPic,
postBg: postBg,
postImg:postImg,
addFont:addFont,
addLine: addLine,
ring: ring,
fillRoundRect: fillRoundRect,
changeR: changeR,
getPx: getPx
};