wxml文件
<view class='poste_box' id='canvas-container' bindlongpress="saveShareImg">
<canvas canvas-id="myCanvas" style="width:calc(100% - 10px);height:920rpx; margin:0 auto"/>
</view>
wxss文件
page {
background-color: #fff;
}
.poste_box {
width: 82%;
margin: auto;
margin-top: 50rpx;
background-color: #f8f8f8;
/* border: 1rpx solid #ddd; */
box-shadow:0px 0px 10px 5px #D8D7DD;
border-radius: 30rpx;
overflow: hidden;
padding: 20rpx 0;
}
js文件
const app = getApp();
const util = require('../../../utils/util.js');//工具类
Page({
/**
* 页面的初始数据
*/
data: {
cardInfo: {
avater: "", //主图
qrCode: "", //二维码
price: "", //价格
Name: "", //商品名称
userName: "", //用户名
tips: "为你推荐", //提示语
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
app.get_visitor()
var data = app.globalData.poster_data//海报需要的资料
const that = this
var id = data.id
var price_a = util.toPrice(data.now_price, true)
var price_b = util.toPrice(data.now_price, false)
console.log(app.globalData.userInfo)
that.setData({
'cardInfo.avater': data.avater,
'cardInfo.Name': data.title,
'cardInfo.price_a': price_a,
'cardInfo.price_b': price_b,
'cardInfo.orgin_price': data.orgin_price,//商品原价
'cardInfo.userName': app.globalData.userInfo.nickName,//用户名称
'cardInfo.txSrc': app.globalData.userInfo.avatarUrl,//头像
})
this.show_poster(id)
}
},
/**
* 先下载头像图片
*/
getAvaterInfo: function () {
wx.showLoading({
title: '生成中...',
mask: true,
});
var that = this;
wx.downloadFile({
url: that.data.cardInfo.avater, //头像图片路径
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var avaterSrc = res.tempFilePath; //下载成功返回结果
that.getQrCode(avaterSrc); //继续下载二维码图片
} else {
wx.showToast({
title: '主图下载失败!',
icon: 'none',
duration: 2000,
success: function () {
var avaterSrc = "";
that.getQrCode(avaterSrc);
}
})
}
}
})
},
/**
* 下载二维码图片
*/
getQrCode: function (avaterSrc) {
wx.showLoading({
title: '生成中...',
mask: true,
});
var that = this;
if (!that.data.cardInfo.qrCode) {
wx.showToast({
title: '二维码加载失败!',
icon: 'none',
duration: 2000
})
return false
}
wx.downloadFile({
url: that.data.cardInfo.qrCode, //二维码路径
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var codeSrc = res.tempFilePath;
that.getUserImg(avaterSrc, codeSrc);
} else {
wx.showToast({
title: '二维码下载失败!',
icon: 'none',
duration: 2000,
success: function () {
var codeSrc = "";
that.getUserImg(avaterSrc, codeSrc);
}
})
}
}
})
},
/**
* 下载头像
*/
getUserImg: function (avaterSrc, codeSrc) {
wx.showLoading({
title: '生成中...',
mask: true,
});
var that = this;
wx.downloadFile({
url: that.data.cardInfo.txSrc, //二维码路径
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var txSrc = res.tempFilePath;
that.sharePosteCanvas(avaterSrc, codeSrc, txSrc);
} else {
wx.showToast({
title: '头像失败!',
icon: 'none',
duration: 2000,
success: function () {
var txSrc = "";
that.sharePosteCanvas(avaterSrc, codeSrc, txSrc);
}
})
}
}
})
},
/**
* 开始用canvas绘制分享海报
*/
sharePosteCanvas: function (avaterSrc, codeSrc, txSrc) {
wx.showLoading({
title: '生成中...',
mask: true,
})
var that = this;
var cardInfo = that.data.cardInfo; //需要绘制的数据集合
const ctx = wx.createCanvasContext('myCanvas'); //创建画布
var width = "";
wx.createSelectorQuery().select('#canvas-container').boundingClientRect(function (rect) {
var height = rect.height;
var right = rect.right;
width = (rect.width - 10) * 0.92;
var left = width * 0.04;
ctx.setFillStyle('#f8f8f8');
ctx.fillRect(0, 0, rect.width, height);
//名字
var userNameWidth = 0
if (cardInfo.userName) {
ctx.setFontSize(13);
ctx.setFillStyle('#333');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.userName, left + 31, 19);
userNameWidth = ctx.measureText(cardInfo.userName).width
}
//提示语
if (cardInfo.tips) {
ctx.setFontSize(12);
ctx.setFillStyle('#B8B8B8');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.tips, left + userNameWidth + 38, 18);
}
// 绘制头像
if (txSrc) {
ctx.save();
ctx.beginPath();
ctx.arc(left + 11, 16, 11, 0, 2 * Math.PI);//切圆角
// 从画布上裁剪出这个圆形
ctx.clip();
ctx.drawImage(txSrc, left, 5, 22, 22)
ctx.restore();
}
// 绘制矩形(背景色)
ctx.save()
that.roundRect(ctx, left, width + 28, width, 105, 8)
ctx.clip()
ctx.beginPath();//开始一个新的路径
ctx.setFillStyle('#fff');//矩形颜色
ctx.fillRect(left, width + 28, width, 105);//添加实心矩形
ctx.stroke();//对当前路径进行描边
ctx.closePath();//关闭当前路径
ctx.restore()
//商品主图为圆角
if (avaterSrc) {
ctx.save()
that.roundRect(ctx, left, 40, width, width, 10)
ctx.clip()
ctx.drawImage(avaterSrc, left, 40, width, width);
ctx.restore()
}
//价格
// 绘制‘¥’
var coinwidth = 0
if (cardInfo.price_a) {
ctx.setFontSize(14);
ctx.setFillStyle('#F24F4C');
ctx.setTextAlign('left');
ctx.fillText(that.data.monetary_unit, left + 8, width + 85, width - 4);
coinwidth = ctx.measureText(that.data.monetary_unit).width
}
//绘制价格第一个字符
var pricewidth = 0
if (cardInfo.price_a) {
ctx.setFontSize(20);
ctx.setFillStyle('#F24F4C');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.price_a, left + coinwidth + 8, width + 85, width - 4);
pricewidth = ctx.measureText(cardInfo.price_a)
console.log(pricewidth)
}
//绘制价格第二个字符
if (cardInfo.price_b) {
ctx.setFontSize(14);
ctx.setFillStyle('#F24F4C');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.price_b, left + coinwidth + pricewidth.width + 8, width + 85, width - 4);
}
// 绘制原价
// if (cardInfo.orgin_price){
// ctx.setFontSize(14);
// ctx.setFillStyle('#999');
// ctx.setTextAlign('left');
// ctx.setStrokeStyle("#999")
// ctx.fillText(that.data.monetary_unit + cardInfo.orgin_price, left + coinwidth +44 + pricewidth.width, width + 36, width - 4);
// var linewidth = ctx.measureText(that.data.monetary_unit + cardInfo.orgin_price)
// ctx.moveTo(left + coinwidth + 44 + pricewidth.width, width + 30)
// ctx.lineTo(left + coinwidth + 44 + pricewidth.width + linewidth.width, width + 30)
// ctx.stroke()
// }
//标题
if (cardInfo.Name) {
ctx.setTextAlign('left');
var text = cardInfo.Name
var chr = text.split("");//这个方法是将一个字符串分割成字符串数组
var temp = "";
var row = [];
ctx.setFontSize(14)
ctx.setFillStyle("#333")
for (var a = 0; a < chr.length; a++) {
if (ctx.measureText(temp).width < 0.60 * width) {
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 < 0.60 * width) {
test += rowPart[a];
}
else {
break;
}
}
empty.push(test);
var group = empty[0] + "..."//这里只显示两行,超出的用...表示
rowCut.splice(1, 1, group);
row = rowCut;
}
for (var b = 0; b < row.length; b++) {
ctx.fillText(row[b], left + 8, width + 110 + b * 20, 300);
}
}
// 绘制二维码
if (codeSrc) {
ctx.drawImage(codeSrc, width * 0.772, width + 55, width * 0.228, width * 0.228)
}
// 绘制长按识别二维码扫一扫购买
ctx.setFontSize(12);
ctx.setFillStyle('#B8B8B8');
ctx.setTextAlign('left');
ctx.fillText('长按识别二维码扫一扫购买', left + 66, width + 175);
//虚线
// ctx.setStrokeStyle("#e5e5e5")//设置线条的颜色
// ctx.setLineWidth(1)//设置线条宽度
// that.drawDashLine(ctx, left, width + 100, width+left+4, width + 100, 4)
}).exec()
setTimeout(function () {
ctx.draw();
wx.hideLoading();
}, 1000)
},
// 切圆角,只兼容苹果
roundRect(ctx, x, y, w, h, r) {
// ctx要操作的画布,x:x轴距离,y:y轴距离,w:图片宽度,h:图片高度,r:圆角弧度
var min_size = Math.min(w, h);
if (r > min_size / 2) r = min_size / 2;
// 开始绘制
ctx.beginPath();//开始创建一个路径。需要调用 fill 或者 stroke 才会使用路径进行填充或描边
ctx.moveTo(x + r, y);//把路径移动到画布中的指定点,不创建线条。用 stroke 方法来画线条x+r(目标位置的 x 坐标)y:(目标位置的 y 坐标)
ctx.arcTo(x + w, y, x + w, y + h, r);//切圆角x+w(第一个控制点的 x 轴坐标),y(第一个控制点的 y 轴坐标),x+w(第二个控制点的 x 轴坐标)y+h(第二个控制点的 y 轴坐标),r(圆角弧度)
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();//关闭一个路径
return ctx;
},
//点击长按保存到相册
saveShareImg: function () {
var that = this;
wx.showLoading({
title: '正在保存',
mask: true,
})
setTimeout(function () {
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
success: function (res) {
wx.hideLoading();
var tempFilePath = res.tempFilePath;
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
},
fail: function (res) {
wx.showToast({
title: res.errMsg,
icon: 'none',
duration: 2000
})
}
})
}
});
}, 1000);
},
//画虚线
drawDashLine: function (ctx, x1, y1, x2, y2, dashLength) { //传context对象,始点x和y坐标,终点x和y坐标,虚线长度
var dashLen = dashLength === undefined ? 3 : dashLength,
xpos = x2 - x1, //得到横向的宽度;
ypos = y2 - y1, //得到纵向的高度;
numDashes = Math.floor(Math.sqrt(xpos * xpos + ypos * ypos) / dashLen);
//利用正切获取斜边的长度除以虚线长度,得到要分为多少段;
for (var i = 0; i < numDashes; i++) {
if (i % 2 === 0) {
ctx.moveTo(x1 + (xpos / numDashes) * i, y1 + (ypos / numDashes) * i);
//有了横向宽度和多少段,得出每一段是多长,起点 + 每段长度 * i = 要绘制的起点;
} else {
ctx.lineTo(x1 + (xpos / numDashes) * i, y1 + (ypos / numDashes) * i);
}
}
ctx.stroke();
},
//获取二维码
show_poster: function (id) {
const _this = this;
util.requestData({
url: '后台接口',
method: 'POST',
data: {
pro_id: id,
},
success: function (res) {
console.log(res)
var imgurl = res.data.img
var txSrc = res.data.headimgurl
var pro_img = res.data.pro_img
_this.setData({
'cardInfo.qrCode': imgurl ? imgurl : '',
'cardInfo.txSrc': txSrc ? txSrc : '',
'cardInfo.avater': pro_img || '',
})
_this.getAvaterInfo();
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
})