1、canvas不能绘制网络图片需要转换成本地图片进行使用
2、多张图片绘制需要调用 img.onload,进行嵌套绘制
<view class="overlay-box">
<view style="margin-top: 20px;"></view>
<scroll-view class="overlay-wrap" scroll-y="true" style="visibility:{{!canvasonload?'visible':'hidden'}}">
<canvas id="{{canvasId}}" type="2d" class="share__canvas1" style="width: 100%; height:964rpx;"></canvas>
<view class="savebtn" bindtap="saveiImg">
<van-button type="danger" size='large' round='{{true}}'> 保存</van-button>
</view>
</scroll-view>
</view>
data: {
canvasId: 'canvasID',
canvasonload: false, //加载状态
bg1: config.host + 'volunteer_bg.png',//背景的网络图片
cachet1: config.host + 'cachet.png',//公章的网络图片
title_bg1:config.host + 'volunteer_title.png',//标题的网络图片
bg2: '',
cachet2: '',
title_bg2:'',
codeImg: '',
},
onLoad(options) {
// 请求小程序二维码的接口,加载完毕在执行后续操作
my.post(my.urls.Code,true).then(res => {
if (res.code == 200) {
this.getCanvas([this.data.bg1, this.data.cachet1,this.data.title_bg1,res.msg], 0)
}
})
},
getCanvas(urlArr, _type) {
let _this = this
wx.getImageInfo({
src: urlArr[_type],
success: function (res) {
//res.path是网络图片的本地地址
if (_type === 0) {
_this.setData({
bg2: res.path,
})
_this.getCanvas(urlArr, 1)
} else if(_type === 1){
_this.setData({
cachet2: res.path,
})
_this.getCanvas(urlArr, 2)
}else if(_type === 2){
_this.setData({
title_bg2: res.path,
})
_this.getCanvas(urlArr, 3)
}else if(_type === 3){
_this.setData({
codeImg: res.path,
})
var query = wx.createSelectorQuery().in(_this);
query.select('#' + _this.data.canvasId).fields({
node: true,
size: true,
}).exec(_this.drawImg.bind(_this))
}
}
})
},
// 画图
drawImg(res) {
const that = this
const width = res[0].width
const height = res[0].height
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = width * dpr
canvas.height = height * dpr
ctx.scale(dpr, dpr)
// 比例 canvas / 设计搞宽度
const proportion = width / 335
// 绘制图片
const img = canvas.createImage();
const img2 = canvas.createImage();
const img3 = canvas.createImage();
const img4 = canvas.createImage();
// 背景图片
img.src = this.data.bg2
img.onload = () => {
ctx.drawImage(img, 0, 0, proportion * 341, proportion * 500)
// 标题图片
img2.src = that.data.title_bg2
img2.onload = () => {
ctx.drawImage(img2, (width/2)-50, proportion * 40, 100, 100)
// 绘制公章图片
img3.src = that.data.cachet2
img3.onload = () => {
ctx.drawImage(img3, proportion * 194, proportion * 365, proportion*100, proportion*100)
// 二维码图片
img4.src = that.data.codeImg
img4.onload = () => {
ctx.drawImage(img4, proportion * 23, proportion * 405, proportion *60, proportion *60)
}
}
}
ctx.fillStyle = "#C84141";
ctx.font = proportion * 16 + "px PingFang SC-Medium, PingFang SC";
drawText(ctx, '小老弟', proportion * 30, proportion * 191, proportion * 290, proportion * 290)
// 证书内容
ctx.fillStyle = "#202020";
ctx.font = proportion * 15 + "px PingFang SC-Medium, PingFang SC";
drawText(ctx, '感谢您抽身百忙之中,参加我们的志愿者服务活动。为表达我们由衷的敬意,也为了鼓励更多人士加入我们,特为您颁发此证书,以兹纪念,谢谢。', proportion * 30, proportion * 240, proportion * 284, proportion * 20)
// 查看二维码
ctx.fillStyle = "#9D9D9D";
ctx.font = proportion * 12 + "px PingFang SC-Medium, PingFang SC";
drawText(ctx, '长按二维码', proportion * 88, proportion * 430, proportion * 290, proportion * 290)
ctx.font = proportion * 12 + "px PingFang SC-Medium, PingFang SC";
drawText(ctx, '查看更多公益项目', proportion * 88, proportion * 450, proportion * 290, proportion * 290)
//基金会
ctx.fillStyle = "#1E2235";
ctx.font = proportion * 14 + "px PingFang SC-Medium, PingFang SC";
drawText(ctx, '基金会', proportion * 180, proportion * 420, proportion * 284, proportion * 20)
//日期
ctx.font = proportion * 14 + "px PingFang SC-Medium, PingFang SC";
drawText(ctx, '2022-12-16', proportion * 200, proportion * 450, proportion * 280, proportion * 20)
wx.hideLoading({
complete: that.setData({
canvasonload: false
})
})
}
//文本换行 参数:1、canvas对象,2、文本 3、距离左侧的距离 4、距离顶部的距离 5、6、文本的宽度
function drawText(ctx, str, leftWidth, initHeight, canvasWidth, titleHeight, bool) {
var lineWidth = 0;
var lastSubStrIndex = 0; //每次开始截取的字符串的索引
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width;
if (lineWidth > canvasWidth) {
ctx.fillText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); //绘制截取部分
// 行高
initHeight += proportion * 30; //16为字体的高度
lineWidth = 0;
lastSubStrIndex = i;
titleHeight += proportion * 18;
}
if (i == str.length - 1) { //绘制剩余部分
ctx.fillText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight);
}
}
// 标题border-bottom 线距顶部距离
titleHeight = titleHeight + proportion * 10;
return titleHeight
}
myCanvas = canvas
},
// 保存图片
saveiImg() {
wx.showLoading({
title: '图片保存中...',
})
wx.canvasToTempFilePath({ // 将canvas生成图片
canvas: myCanvas,
success: (res) => {
wx.saveImageToPhotosAlbum({ //保存图片到相册
filePath: res.tempFilePath,
success: function (res) {
wx.showToast({
icon: 'success',
title: "保存图片保存成功"
})
},
fail: (err) => {
if (err.errMsg) { //重新授权弹框确认
wx.showModal({
title: '提示',
content: '您好,请先授权,在保存此图片。',
showCancel: false,
success(res) {
if (res.confirm) { //重新授权弹框用户点击了确定
wx.openSetting({ //进入小程序授权设置页面
success(settingdata) {
if (settingdata.authSetting['scope.writePhotosAlbum']) { //用户打开了保存图片授权开关
wx.saveImageToPhotosAlbum({
filePath: respath,
success: function (data) {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
})
} else { //用户未打开保存图片到相册的授权开关
wx.showModal({
title: '温馨提示',
content: '授权失败,请稍后重新获取',
showCancel: false,
})
}
}
})
}
}
})
}
wx.showToast({
icon: 'error',
title: "保存图片保存失败"
})
}
})
},
fail: (err) => {
console.log(err);
},
complete: () => {
wx.hideLoading()
}
})
},