首先我們先來看看生成的圖片
廢話就不多說了施禾,我們來看看代碼的實(shí)現(xiàn)吧
<canvas style="width:100%;height:{{contentHeight}}px" canvas-id="myCanvas"></canvas>
data: {
// canvas
windowWidth: 0, //屏幕寬度
windowHeight: 0, //屏幕高度
contentHeight: 0, //內(nèi)容高度
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: '', //轉(zhuǎn)換臨時(shí)圖片的商品圖片
canvasTempFile: '' //canvas臨時(shí)圖片
}
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
onLoad: function(options) {
var that = this
that.setData({
insideWidth: '100%'
})
//獲取設(shè)備信息高度脚线。計(jì)算出其他的高度等
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, //小程序碼圖片高度
})
}
})
//網(wǎng)絡(luò)圖片轉(zhuǎn)為本地圖片,直接顯示網(wǎng)絡(luò)圖片的話真機(jī)不顯示
that.getTempFile(that.data.shopImg)
},
//drawImage繪制的圖片需要通過getImageInfo/downloadFile獲取商品臨時(shí)圖片路徑
getTempFile: function(url) {
wx.showLoading({
title: '圖片生成中'
})
let that = this
wx.downloadFile({
url: url,
success: function(res) {
that.setData({
goodsInfoImg: res.tempFilePath
})
//繼續(xù)生成商品的小程序碼
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
},
//畫矩形渠旁,也是整塊畫布的大小,寬度是屏幕寬度斯碌,高度根據(jù)內(nèi)容多少來動態(tài)設(shè)置。
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坐標(biāo)
// y:矩形左上角的y坐標(biāo)
// w:矩形寬度
// h:矩形高度
// r:圓弧半徑
roundRect: function(ctx, x, y, w, h, r) {
// 開始繪制
ctx.beginPath()
// 因?yàn)檫吘壝柽叴嬖阡忼X傻唾,最好指定使用 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都可以,二選一即可冠骄,但是需要與上面對應(yīng)
ctx.fill()
// ctx.stroke()
ctx.closePath()
// 剪切
ctx.clip()
ctx.restore()
},
// 根據(jù)文字多少動態(tài)計(jì)算高度伪煤,然后依次畫出矩形凛辣,文字抱既,橫線和小程序碼。
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(
'標(biāo)題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(
'填價(jià)格',
(that.data.windowWidth - ctx.measureText('填價(jià)格').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
})
//生成數(shù)據(jù)
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
})
}
})
},
// 生成圖片中,這個方法是生成臨時(shí)圖片代替canvas展示,因?yàn)樾〕绦蚶锩鎐anvas的層級太高蝗敢,會擋住彈窗的內(nèi)容捷泞,所有需要把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)
},
//點(diǎn)擊保存到相冊前驗(yàn)證是否授權(quán) 最這兩個方法就是保存相冊了 把它放置到按鈕的點(diǎn)擊事件即可
saveShareImg: function() {
wx.getSetting({
success: res => {
if (!res.authSetting['scope.writePhotosAlbum']) {
//未授權(quán)的話發(fā)起授權(quán)
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
//用戶允許授權(quán)寿谴,保存到相冊
this.saveImg()
},
fail: () => {
//用戶拒絕授權(quán),然后就引導(dǎo)授權(quán)(這里的話如果用戶拒絕讶泰,不會立馬彈出引導(dǎo)授權(quán)界面咏瑟,坑就是上邊所說的官網(wǎng)原因)
wx.showModal({
content: '保存到相冊需要獲得你的授權(quán)',
showCancel: false,
confirmText: '確認(rèn)',
success: function(res) {
wx.openSetting({
success: () => {
wx.authorize({
scope: 'scope.writePhotosAlbum',
succes: () => {
//授權(quán)成功,保存圖片
this.saveImg()
}
})
}
})
},
fail: function(res) {}
})
}
})
} else {
//已經(jīng)授權(quán)
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
})
}
})
},