首先我们先来看看生成的图片
微信图片_20200830213420.png
废话就不多说了,我们来看看代码的实现吧
<canvas style="width:100%;height:{{contentHeight}}px" canvas-id="myCanvas"></canvas>
data: {
// canvas
windowWidth: 0, //屏幕宽度
windowHeight: 0, //屏幕高度
contentHeight: 0, //内容高度
canvasUrl: '', //canvas李彪
qrCode:
'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1254162229,4079702590&fm=26&gp=0.jpg', //小程序码https图片路径
shopImg:
'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1254162229,4079702590&fm=26&gp=0.jpg', //商品图片
sharePopup: false, //显示分享弹窗
goodsInfoImg: '', //转换临时图片的商品图片
canvasTempFile: '' //canvas临时图片
}
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
var that = this
that.setData({
insideWidth: '100%'
})
//获取设备信息高度。计算出其他的高度等
wx.getSystemInfo({
success: function(res) {
that.setData({
windowWidth: res.windowWidth,
windowHeight: res.windowHeight,
boxWidth: res.windowWidth * 0.75, //分享图片box宽度
boxheight: res.windowWidth * (0.222 + 0.72 + 0.192) + 90, //分享图片box高度
boxPageY: res.windowWidth * 0.081, //boxY轴位置
shadowWidth: res.windowWidth * 0.6, //阴影宽度
shadowHeight: res.windowWidth * 0.78, //阴影高度
imgPageY: res.windowWidth * 0.232 //商品图片Y轴位置
// codeWidth: res.windowWidth * 0.192, //小程序码图片宽度
// codeHeight: res.windowWidth * 0.192, //小程序码图片高度
})
}
})
//网络图片转为本地图片,直接显示网络图片的话真机不显示
that.getTempFile(that.data.shopImg)
},
//drawImage绘制的图片需要通过getImageInfo/downloadFile获取商品临时图片路径
getTempFile: function(url) {
wx.showLoading({
title: '图片生成中'
})
let that = this
wx.downloadFile({
url: url,
success: function(res) {
that.setData({
goodsInfoImg: res.tempFilePath
})
//继续生成商品的小程序码
that.downloadSkuQrCode(that.data.qrCode)
},
fail: function(err) {
wx.showToast({
title: '下载商品图片失败,稍后重试!',
icon: 'none',
duration: 5000
})
}
})
},
getData() {
let that = this
wx.getImageInfo({
src: that.data.shopImg,
success(res) {
var imgsize = that.getimageSize(
{ width: res.width, height: res.height },
that.data.shadowWidth,
95
)
that.setData({
imgWidth: imgsize.width,
imgHeight: imgsize.height
})
that.createNewImg()
}
})
},
// 图片适配(aspectFill)
getimageSize: function(imageSize, w, h) {
if (imageSize.width < w) {
if (imageSize.height < h) {
var scale1 = imageSize.height / imageSize.width
var scale2 = h / imageSize.height
if (scale1 > scale2) {
imageSize.height = (imageSize.height / imageSize.width) * w
imageSize.width = w
} else {
imageSize.width = (imageSize.width / imageSize.height) * h
imageSize.height = h
}
} else {
imageSize.height = (imageSize.height / imageSize.width) * w
imageSize.width = w
}
} else if (imageSize.height < h) {
if (imageSize.width < w) {
var scale1 = imageSize.height / imageSize.width
var scale2 = h / imageSize.height
if (scale1 > scale2) {
imageSize.height = (imageSize.height / imageSize.width) * w
imageSize.width = w
} else {
imageSize.width = (imageSize.width / imageSize.height) * h
imageSize.height = h
}
} else {
imageSize.width = (imageSize.width / imageSize.height) * h
imageSize.height = h
}
} else {
var scale1 = imageSize.height / imageSize.width
var scale2 = h / imageSize.height
if (scale1 > scale2) {
imageSize.height = (imageSize.height / imageSize.width) * w
imageSize.width = w
} else {
imageSize.width = (imageSize.width / imageSize.height) * h
imageSize.height = h
}
}
return imageSize
},
//画矩形,也是整块画布的大小,宽度是屏幕宽度,高度根据内容多少来动态设置。
drawSquare: function(ctx, height, color) {
let that = this
// 绘制大长方矩形
ctx.setFillStyle(color)
ctx.fillRect(
(that.data.windowWidth - that.data.boxWidth) / 2,
that.data.boxPageY,
that.data.boxWidth,
height
)
// // 绘制中间块矩形
// ctx.setFillStyle('red')
// ctx.fillRect(
// (that.data.windowWidth-that.data.shadowWidth)/2,
// that.data.imgPageY,
// that.data.shadowWidth,
// that.data.shadowWidth
// )
},
// ctx:canvas中的createCanvasContext,
// x:矩形左上角的x坐标
// y:矩形左上角的y坐标
// w:矩形宽度
// h:矩形高度
// r:圆弧半径
roundRect: function(ctx, x, y, w, h, r) {
// 开始绘制
ctx.beginPath()
// 因为边缘描边存在锯齿,最好指定使用 transparent 填充
// 这里是使用 fill 还是 stroke都可以,二选一即可
ctx.setFillStyle('transparent')
// ctx.setStrokeStyle('transparent')
// 左上角
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
// border-top
ctx.moveTo(x + r, y)
ctx.lineTo(x + w - r, y)
ctx.lineTo(x + w, y + r)
// 右上角
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
// border-right
ctx.lineTo(x + w, y + h - r)
ctx.lineTo(x + w - r, y + h)
// 右下角
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
// border-bottom
ctx.lineTo(x + r, y + h)
ctx.lineTo(x, y + h - r)
// 左下角
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
// border-left
ctx.lineTo(x, y + r)
ctx.lineTo(x + r, y)
// 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
ctx.fill()
// ctx.stroke()
ctx.closePath()
// 剪切
ctx.clip()
ctx.restore()
},
// 根据文字多少动态计算高度,然后依次画出矩形,文字,横线和小程序码。
createNewImg: function() {
let that = this
let ctx = wx.createCanvasContext('myCanvas')
// let contentHeight = that.data.boxheight //修改图片高度
let contentHeight = that.data.shadowWidth + that.data.imgPageY + 100
// 绘制圆角矩形
that.roundRect(
ctx,
(that.data.windowWidth - that.data.boxWidth) / 2,
that.data.boxPageY,
that.data.boxWidth,
contentHeight - 32,
14
)
that.drawSquare(ctx, contentHeight, '#333')
that.setData({
contentHeight: contentHeight
})
//商品图片
// 绘制图片圆角
let bg_r = 14
ctx.save()
ctx.beginPath()
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
that.data.imgPageY + bg_r,
bg_r,
Math.PI,
Math.PI * 1.5
)
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 +
that.data.imgWidth -
bg_r,
that.data.imgPageY + bg_r,
bg_r,
Math.PI * 1.5,
Math.PI * 2
)
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 +
that.data.imgWidth -
bg_r,
that.data.imgPageY + that.data.imgHeight - bg_r,
bg_r,
0,
Math.PI * 0.5
)
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
that.data.imgPageY + that.data.imgHeight - bg_r,
bg_r,
Math.PI * 0.5,
Math.PI
)
ctx.clip()
ctx.drawImage(
that.data.goodsInfoImg,
(that.data.windowWidth - that.data.imgWidth) / 2,
that.data.imgPageY,
that.data.imgWidth,
that.data.imgHeight
)
ctx.restore()
// 绘制商品蒙层矩形
ctx.save()
ctx.beginPath()
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
that.data.imgPageY + that.data.imgHeight - 60 + bg_r,
30,
Math.PI,
Math.PI * 1.5
)
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 +
that.data.imgWidth -
bg_r,
that.data.imgPageY + that.data.imgHeight - 60 + bg_r,
30,
Math.PI * 1.5,
Math.PI * 2
)
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 +
that.data.imgWidth -
bg_r,
that.data.imgPageY + that.data.imgHeight - 60 + 60 - bg_r,
bg_r,
0,
Math.PI * 0.5
)
ctx.arc(
(that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
that.data.imgPageY + that.data.imgHeight - 60 + 60 - bg_r,
bg_r,
Math.PI * 0.5,
Math.PI
)
ctx.clip()
ctx.setFillStyle('rgba(0,0,0,0.5)')
ctx.fillRect(
(that.data.windowWidth - that.data.imgWidth) / 2,
that.data.imgPageY + that.data.imgHeight - 60,
that.data.imgWidth,
60
)
ctx.restore()
ctx.setFillStyle('#fff')
ctx.font = 'normal 13px Microsoft YaHei'
ctx.fillText(
'标题logo',
(that.data.windowWidth - that.data.shadowWidth) / 2,
that.data.imgPageY - 10
)
ctx.setFillStyle('#fff')
// ctx.setTextAlign="center"
ctx.fillText(
'填商品名字',
(that.data.windowWidth - ctx.measureText('填商品名字').width) * 0.5,
that.data.imgPageY + that.data.imgHeight - 40
)
ctx.font = 'normal 22px Microsoft YaHei'
ctx.setFillStyle('#ECC781')
ctx.fillText(
'填价格',
(that.data.windowWidth - ctx.measureText('填价格').width) * 0.5,
that.data.imgPageY + that.data.imgHeight - 10
)
// 绘制您的好友
ctx.font = 'normal 16px Microsoft YaHei'
ctx.setFillStyle('#fff')
ctx.fillText(
'您的好友已为您',
(that.data.windowWidth - that.data.shadowWidth) / 2,
that.data.shadowWidth + that.data.imgPageY + 30
)
ctx.font = 'normal 16px Microsoft YaHei'
ctx.setFillStyle('#fff')
ctx.fillText(
'这里填所需文字',
(that.data.windowWidth - that.data.shadowWidth) / 2,
that.data.shadowWidth + that.data.imgPageY + 52
)
// 绘制长按识别小程序
ctx.font = 'normal 12px Microsoft YaHei'
ctx.setFillStyle('#AAAAAA')
ctx.fillText(
'长按识别小程序即可参与',
(that.data.windowWidth - that.data.shadowWidth) / 2,
that.data.shadowWidth + that.data.imgPageY + 80
)
// 填充小程序码
ctx.drawImage(
that.data.qrCode,
(that.data.windowWidth - that.data.shadowWidth) / 2 +
that.data.shadowWidth -
that.data.codeWidth,
that.data.shadowWidth + that.data.imgPageY + 80 - that.data.codeHeight,
that.data.codeWidth,
that.data.codeHeight
)
ctx.draw() //绘制到canvas
that.generateCanvasImg()
},
//下载小程序码
downloadSkuQrCode: function(url) {
let that = this
wx.downloadFile({
url: url,
success: function(res) {
that.setData({
qrCode: res.tempFilePath
})
//生成数据
wx.getImageInfo({
src:
'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1254162229,4079702590&fm=26&gp=0.jpg',
success(res) {
that.setData({
codeWidth: res.width * 0.1,
codeHeight: res.height * 0.1
})
that.getData()
}
})
},
fail: function(err) {
wx.showToast({
title: '下载商品码失败,稍后重试!',
icon: 'none',
duration: 5000
})
}
})
},
// 生成图片中,这个方法是生成临时图片代替canvas展示,因为小程序里面canvas的层级太高,会挡住弹窗的内容,所有需要把canvas放到视图之外,用img展示即可
generateCanvasImg() {
var that = this
setTimeout(function() {
wx.canvasToTempFilePath({
x: (that.data.windowWidth - that.data.boxWidth) / 2,
y: that.data.boxPageY,
width: that.data.boxWidth,
height: that.data.shadowWidth + that.data.imgPageY + 68,
destWidth: that.data.boxWidth * wx.getSystemInfoSync().pixelRatio,
destHeight:
(that.data.shadowWidth + that.data.imgPageY + 68) *
wx.getSystemInfoSync().pixelRatio,
canvasId: 'myCanvas',
success: function(res) {
wx.hideLoading()
that.setData({
canvasTempFile: res.tempFilePath
})
},
fail: function(res) {}
})
}, 1000)
},
//点击保存到相册前验证是否授权 最这两个方法就是保存相册了 把它放置到按钮的点击事件即可
saveShareImg: function() {
wx.getSetting({
success: res => {
if (!res.authSetting['scope.writePhotosAlbum']) {
//未授权的话发起授权
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
//用户允许授权,保存到相册
this.saveImg()
},
fail: () => {
//用户拒绝授权,然后就引导授权(这里的话如果用户拒绝,不会立马弹出引导授权界面,坑就是上边所说的官网原因)
wx.showModal({
content: '保存到相册需要获得你的授权',
showCancel: false,
confirmText: '确认',
success: function(res) {
wx.openSetting({
success: () => {
wx.authorize({
scope: 'scope.writePhotosAlbum',
succes: () => {
//授权成功,保存图片
this.saveImg()
}
})
}
})
},
fail: function(res) {}
})
}
})
} else {
//已经授权
this.saveImg()
}
}
})
},
saveImg() {
var that = this
wx.showLoading({
title: '正在保存',
mask: true
})
wx.saveImageToPhotosAlbum({
filePath: that.data.canvasTempFile,
success(res) {
wx.hideLoading()
wx.showModal({
content: '图片已保存到相册,赶紧晒一下吧~',
showCancel: false,
confirmText: '好的',
success: function(res) {
if (res.confirm) {
}
},
fail: function(res) {}
})
that.setData({
sharePopup: false
})
},
fail: function(res) {
wx.showToast({
title: '保存失败',
icon: 'none',
duration: 2000
})
}
})
},
网友评论