文档
wxml
<view class="canvas-container">
<canvas
canvas-id="myCanvas"
class="myCanvas"
style="width: {{canvasWidth}}px; height: {{canvasHeight}}px;">
</canvas>
<view class="btn-save" bindtap="savePoster">保存到相册</view>
</view>
wxss
.myCanvas {
display: block;
margin: 0 auto;
}
.btn-save {
margin: 20rpx;
padding: 10rpx;
border: 1rpx solid #eee;
text-align: center;
font-size: 24rpx;
border-radius: 4rpx;
}
js
Page({
data: {
canvasWidth: 296,
canvasHeight: 426,
bgUrl: 'https://img-crs.vchangyi.com/standard/new_buy_poster_bg2.png',
goodsUlr: 'https://img-crs.vchangyi.com/goods16233105466440.jpg',
card_url: ''
},
onLoad: function (options) {
const { canvasWidth, canvasHeight, bgUrl, goodsUlr } = this.data;
const ctx = wx.createCanvasContext("myCanvas", this);
Promise.all([
this.getCode(bgUrl),
this.getCode(goodsUlr)
]).then(res => {
ctx.drawImage(res[0].tempFilePath, 0, 0, canvasWidth, canvasHeight);
this.roundedRect(
ctx,
10,
56,
275,
360,
5,
5,
5,
5
);
ctx.fillStyle = "#ffffff";
ctx.fill();
ctx.drawImage(res[1].tempFilePath, 20, 66, 255, 255);
this.drawText(ctx, {
x: 20,
y: 255 + 66 + 20,
color: "#333333",
size: 14,
text: '哈哈哈,大傻瓜,哈哈哈,大傻瓜哈哈哈',
width: "",
bold: true
});
this.drawText(ctx, {
x: 20,
y: 255 + 66 + 40,
color: "#333333",
size: 14,
isCenter: true,
text: '哈哈哈,大傻瓜,哈哈哈',
width: 255,
bold: true
});
this.drawText(ctx, {
x: 20,
y: 390,
color: "#FA4046",
size: 16,
isCenter: true,
text: "¥",
width: "",
bold: true
});
this.drawText(ctx, {
x: 20 + this.measureText('¥'),
y: 378,
color: "#FA4046",
size: 32,
isCenter: true,
text: 2,
width: "",
bold: true
});
this.drawText(ctx, {
x: 20 + 3 + this.measureText('¥') + this.measureText('2', 32),
y: 390,
color: "#FA4046",
size: 16,
isCenter: true,
text: "." + '02',
width: "",
bold: true
});
this.drawText(ctx, {
x: 20 + 3 + 10 + this.measureText('¥') + this.measureText('2', 32) + this.measureText('.02', 16),
y: 394,
color: "#a6a6a6",
size: 12,
isCenter: true,
text: '¥7.99',
width: "",
bold: true
});
this.lineation(ctx, {
sx: 20 + 3 + 10 + this.measureText('¥') + this.measureText('2', 32) + this.measureText('.02', 16),
sy: 399,
ex: 20 + 3 + 5 + 10 + this.measureText('¥') + this.measureText('2', 32) + this.measureText('.02', 16) + this.measureText('¥7.99', 12),
ey: 399,
lineWidth: "",
color: "#a6a6a6"
});
ctx.draw();
setTimeout(() => {
console.log('生成', '....')
this.exportImg("myCanvas", 296, 426);
}, 1000);
})
},
getCode(img) {
return new Promise((resolve, reject) => {
wx.downloadFile({
url: img,
success: (res) => {
resolve(res)
}
})
})
},
exportImg(idn, w, h) {
console.log(idn, w, h)
let that = this;
wx.canvasToTempFilePath(
{
x: 0,
y: 0,
width: w,
height: h,
destWidth: w,
destHeight: h,
canvasId: idn,
success: function(res) {
console.log(res)
wx.getImageInfo({
src: res.tempFilePath,
success: function(res) {
console.log(that, '.......');
that.setData({
card_url: res.path
})
}
});
},
fail(err) {
console.error(err);
},
complete() {}
},
this
);
},
savePoster() {
wx.saveImageToPhotosAlbum(
{
filePath: this.data.card_url,
success(res) {
wx.showToast({
title: '成功',
icon: 'success',
duration: 2000
})
},
fail() {
wx.getSetting({
success: auth => {
if (!auth.authSetting["scope.writePhotosAlbum"]) {
wx.showToast({
title: '请开启相册授权',
icon: 'error',
duration: 2000
})
}
}
});
}
}
);
},
roundedRect(
ctx,
x,
y,
width,
height,
RTradius,
RBradius,
LBradius,
LTradius
) {
ctx.beginPath();
ctx.moveTo(x, y + RTradius);
ctx.lineTo(x, y + height - RTradius);
ctx.quadraticCurveTo(x, y + height, x + RTradius, y + height);
ctx.lineTo(x + width - RBradius, y + height);
ctx.quadraticCurveTo(
x + width,
y + height,
x + width,
y + height - RBradius
);
ctx.lineTo(x + width, y + LBradius);
ctx.quadraticCurveTo(x + width, y, x + width - LBradius, y);
ctx.lineTo(x + LTradius, y);
ctx.quadraticCurveTo(x, y, x, y + LTradius);
ctx.closePath();
},
drawText(ctx, obj) {
ctx.save();
ctx.fillStyle = obj.color;
ctx.setTextBaseline("top");
if (obj.bold) {
ctx.font = `normal bold ${obj.size}px PingFangSC-Regular`;
} else {
ctx.font = `normal 100 ${obj.size}px PingFangSC-Regular`;
}
if (obj.isCenter && obj.width) {
ctx.fillText(
obj.text,
obj.x + (obj.width - ctx.measureText(obj.text).width) / 2,
obj.y
);
} else {
ctx.fillText(obj.text, obj.x, obj.y);
}
ctx.restore();
ctx.closePath();
},
measureText(text, fontSize = 10) {
let width = 0;
String(text)
.split("")
.forEach(item => {
if (/[a-zA-Z]/.test(item)) {
width += 7;
} else if (/[0-9]/.test(item)) {
width += 5.5;
} else if (/\./.test(item)) {
width += 2.7;
} else if (/-/.test(item)) {
width += 3.25;
} else if (/[\u4e00-\u9fa5]/.test(item)) {
width += 10;
} else if (/\(|\)/.test(item)) {
width += 3.73;
} else if (/\s/.test(item)) {
width += 2.5;
} else if (/%/.test(item)) {
width += 8;
} else {
width += 10;
}
});
return (width * fontSize) / 10;
},
lineation(ctx, obj) {
ctx.beginPath();
ctx.setLineWidth(1);
ctx.moveTo(obj.sx, obj.sy);
ctx.lineTo(obj.ex, obj.ey);
ctx.strokeStyle = obj.color;
ctx.stroke();
ctx.closePath();
}
})
效果图
