songfens 2020-06-08
预设画板跟预览保存图片
// html<canvas canvas-id="shareImg" class="canvas-exp"></canvas>
<view hidden=‘{{previewHidden}}‘ class=‘preview‘>
<image src=‘{{preurl}}‘ mode=‘widthFix‘ class=‘previewImg‘></image>
<view class="flex-justify-between btns">
<button bindtap=‘save‘ class="themeBtn themeColor btns-open">保存到相册</button>
</view>
<image src="/assets/icon_closed_white.png" class="cler" bindtap="remove"></image>
</view>CSS
/* //海报 */
.poster{
background:#fff;font-size:32rpx;
margin: 10rpx auto;
}
.canvas-exp{
position: fixed;
bottom: 0;
right: 100%;
width:100%;height:606px;background:#fff;
}
.preview {
width: 100%;
height: 100%;
background: rgba(0,0,0,1);
position:fixed;
top: 0;
left: 0;
z-index: 2;
}
.previewImg{
width: 88%;
position: absolute;
top: 100rpx;
left: 6%;
z-index: 3;
border: 1px solid #000;
border-radius: 5px;
max-height: 800rpx;
}
.preview button{
width: 78%;
position: absolute;
top: 960rpx;
left: 11%;
border-radius: 2px;
}
.preview .cler{
width: 64rpx;
height: 64rpx;
position: absolute;
top: 1100rpx;
left: 50%;
margin-left: -32rpx;
}获取后端生成的小程序码 利用 wx.downloadFile 下载到本地 主要是因为小程序canvas 不支持远程图片
获取后根据要求进行排版绘制 另外文字换行使用自定义函数
//canvas 海报
createCanvasContext() {
let that = this
let winWidth = wx.getSystemInfoSync().windowWidth; // 获取当前设备的可视宽度
let winHeight = wx.getSystemInfoSync().windowHeight; // 获取当前设备的可视高度
that.setData({
winWidth: winWidth,
winHeight: winHeight
})
let imageUrl = that.data.articleData.coverPicture
wx.downloadFile({
url: imageUrl,
success(res) {
if (res.statusCode === 200) {
imageUrl = res.tempFilePath
} else {
imageUrl = ‘/assets/lA.png‘
}
},fail(){
imageUrl = ‘/assets/lA.png‘
}
})
let userNick = ‘90%的备孕人士都在看的精品好‘,
userNick2 = ‘文,‘,
userNick3 = ‘长按识别‘,
userNick4 = ‘小程序阅读全文‘;
let contentTitle = that.data.articleData.title || ‘文章标题‘
let scene = that.data.channelCode + ‘,‘ + that.data.userCode
let data = {
page: ‘pages/hotinfo/hotinfo‘,
sceneStr: scene
}
// 生成小程序码
call.httpService(‘share/generateAppletCode‘, data, ‘post‘, (elem)=>{
console.log(elem)
if (elem.code == 0){
let imgPath = elem.data
wx.downloadFile({
url: imgPath,
success(res) {
console.log(res)
if (res.statusCode === 200) {
imgPath = res.tempFilePath
const ctx = wx.createCanvasContext(‘shareImg‘)
ctx.setFillStyle(‘#fff‘)
ctx.fillRect(0, 0, winWidth, 800)
ctx.drawImage(imageUrl, 0, 0, winWidth, 228 * Rpx)
var currentLineHeight = 228 * Rpx + 10;
ctx.setTextAlign(‘left‘)
ctx.setFillStyle(‘#2E2F2F‘)
ctx.setTextAlign(‘left‘)
let row = util.measureTexts(ctx, contentTitle, winWidth)
ctx.font = ‘normal bold 18px sans-serif‘;
for (var b = 0; b < row.length; b++) {
currentLineHeight += Rpx * 30;
ctx.fillText(row[b], 15, currentLineHeight);
}
if (row.length==1){
currentLineHeight += 5 * Rpx
}
currentLineHeight += 85 * Rpx
ctx.font = ‘normal 100 15px sans-serif‘;
ctx.setFillStyle(‘#828282‘)
ctx.fillText(userNick, 25, currentLineHeight);
currentLineHeight += Rpx * 20;
ctx.fillText(userNick2, 25, currentLineHeight);
ctx.setFillStyle(‘#FF951A‘)
ctx.fillText(userNick3, 25 + ctx.measureText(userNick2).width, currentLineHeight);
ctx.setFillStyle(‘#828282‘)
ctx.fillText(userNick4, 25 + ctx.measureText(userNick2).width + ctx.measureText(userNick3).width, currentLineHeight);
ctx.setFillStyle(‘#185C58‘)
ctx.fillRect(15, currentLineHeight - (Rpx * 20 * 2 - 10 * Rpx), 2, Rpx * 20 * 2 - 10 * Rpx)
ctx.drawImage(imgPath, winWidth - 105 * Rpx, currentLineHeight-80, 90, 90)
currentLineHeight += 25 * Rpx
ctx.stroke()
ctx.draw()
that.setData({
imgPath: imgPath,
currentLineHeight: currentLineHeight
})
if(that.data.createShow){
setTimeout(() => {
that.share()
}, 800);
}
} else {
wx.showToast({
title: ‘数据加载失败‘,
icon: ‘none‘,
duration: 2000
})
}
}, fail(res) {
wx.showToast({
title: ‘数据加载失败!‘,
icon: ‘none‘,
duration: 2000
})
}
})
}else{
wx.showToast({
title: ‘数据加载失败‘,
icon: ‘none‘,
duration: 2000
})
}
}, (err)=>{
}, false)
},
save: function() {
var that = this;
//获取相册授权
wx.getSetting({
success(res) {
if (!res.authSetting[‘scope.writePhotosAlbum‘]) {
wx.authorize({
scope: ‘scope.writePhotosAlbum‘,
success() {
that.savaImageToPhoto();
}
})
} else {
that.savaImageToPhoto();
}
}
})
},
/**
* 生成分享图
*/
share: function() {
var that = this
wx.showLoading({
title: ‘努力生成中...‘
})
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: this.data.winWidth,
height: this.data.currentLineHeight,
destWidth: this.data.winWidth*2,
destHeight: this.data.currentLineHeight*2,
canvasId: ‘shareImg‘,
success: function(res) {
console.log(res.tempFilePath);
that.setData({
preurl: res.tempFilePath,
previewHidden: false,
})
wx.hideLoading()
},
fail: function(res) {
console.log(res)
}
})
},
savaImageToPhoto: function() {
let that = this;
wx.saveImageToPhotosAlbum({
filePath: that.data.preurl,
success(res) {
that.setData({
previewHidden: true
})
wx.showToast({
title: ‘已保存到相册‘,
icon: ‘success‘,
duration: 2000
})
}
})
},util.js
const measureTexts = (ctx, contentTitle, winWidth) => {
var chr = contentTitle.split(""); //这个方法是将一个字符串分割成字符串数组
var temp = "";
var row = [];
for (var a = 0; a < chr.length; a++) {
if (ctx.measureText(temp).width < winWidth / 2 - 10) {
temp += chr[a];
} else {
a--; //这里添加了a-- 是为了防止字符丢失,效果图中有对比
row.push(temp);
temp = "";
}
}
row.push(temp);
//如果数组长度大于2 则截取前两个
if (row.length > 2) {
var rowCut = row.slice(0, 2);
var rowPart = rowCut[1];
var test = "";
var empty = [];
for (var a = 0; a < rowPart.length; a++) {
if (ctx.measureText(test).width < winWidth / 2 - 10) {
test += rowPart[a];
} else {
break;
}
}
empty.push(test);
var group = empty[0] + "..." //这里只显示两行,超出的用...表示
rowCut.splice(1, 1, group);
row = rowCut;
}
return row
}
module.exports = {
measureTexts: measureTexts
}效果大概如下