第一次接触canvas,我是抗拒的,但是多接触几次,还有参考一下别人的思路顺便结合文档,上手应该算是成功了(代码乱而且不封装的,贴我效果图)
代码:
<canvas class="canvasView" canvas-id="saveImg" style="width:{{bgWidth}}px;height:{{bgHeight}}px;margin:0 auto;"></canvas>
<view>这里是画海报分享图的</view>
<button bindtap="handelClick">点击分享</button>
备注:canvas的层级好像是最高的, 当你不需要canvas出现在页面上,可以把它定位出页面之外。
Page({
data: {
windowWidth: 0, //屏幕宽度
windowHeight: 0,//屏幕高度
contentHeight: 0,//内容高度
contentTitle: "母怡 网红茶红糖姜茶姨妈速溶茶月经调理气血10g*15袋/盒", //商品标题
price: "18.9",//商品价格
delPrice: "33",//划线价
canvasUrl: "", //canvas完成后的临时路径
qrCode: "https://www.123.com/files/upload/image/201908/4027dffe-e9bf-4093-b2fd-05030861742a.jpg", //小程序码https图片路径
goodsInfoImg: "https://www.123.com/files/upload/image/201908/f4cbd26c-557a-4d5c-94ff-e8a3248b2a05_source.jpg", //商品图片
name: '小明', //微信昵称
title: '钜惠返利 折扣不断' //
},
onLoad(){
let that = this
let { qrCode, goodsInfoImg, contentTitle} = that.data
wx.getSystemInfo({
success: function (res) {
console.log(res)
that.setData({
windowWidth: res.windowWidth,
windowHeight: res.windowHeight,
bgWidth: (res.windowWidth / 750) * 528, /// 背景图宽 这样做我是为了适应手机,至少我测试过目前是成功的,根据手机尺寸来变
bgHeight: (res.windowWidth / 750) * 800, /// 背景图高 750的设计图,后面的800是你在ps测量的像素
headWH: (res.windowWidth / 750) * 54, ///头像大小
headMT: (res.windowWidth / 750) * 34, ///头像距离顶部位置
headML: (res.windowWidth / 750) * 48, ///头像左边距离
nameMT: (res.windowWidth / 750) * 73, ///昵称顶部位置
nameML: (res.windowWidth / 750) * 110, ///昵称左边距离
goodSize: (res.windowWidth / 750) * 185, /// 商品图大小
goodL: (res.windowWidth / 750) * 176 , ///图片的左边距
goodT: (res.windowWidth / 750) * 162, ///图片的顶部距离
titleL: (res.windowWidth / 750) * 150 , ///文字的左边距离
titleM: (res.windowWidth / 750) * 380 , ///文字的顶部距离
priceM: (res.windowWidth / 750) * 455 , ///价钱顶部距离
priceL: (res.windowWidth / 750) * 225 , ///价钱的左边距
codeSize: (res.windowWidth / 750) * 70 , ///码的大小
codeM: (res.windowWidth / 750) * 685 , ///距离顶部位置
codeL: (res.windowWidth / 750) * 400 , ///距离左边位置
textM: (res.windowWidth / 750) * 580, ///标题顶部距离
textL: (res.windowWidth / 750) * 137, ///标题左边距
})
}
})
//在canvas里用到的图片路径最好不要是网络路径(很坑的),可以用wx.getImageInfo或者wx.downloadFile来下载本地,但需要配置downloadFile域名,但是为了测试你可以勾选那个不校验就好了,但是线上必须得配
wx.getImageInfo({
src: qrCode,
success: (res) =>{
console.log(res.path) // 临时路劲来的
that.setData({
codeSrc: res.path
})
}
})
wx.getImageInfo({
src: goodsInfoImg,
success: (res) => {
console.log(res.path)
that.setData({
goodsImgSrc: res.path
})
}
})
let firstline; //第一行文字
let secondline; //第二行文字
//一行显示10个字,超过一行时
if (contentTitle.length > 10) {
//第一行截取前14个字符
firstline = contentTitle.substring(0, 10);
//两行都显示不下
if (contentTitle.length > 20) {
secondline = contentTitle.substr(10, 10) + "...";
} else {
//第二行取剩下的
secondline = contentTitle.substr(10, contentTitle.length - 10);
}
} else {
//一行就能显示时候
firstline = contentTitle;
}
console.log(firstline)
console.log(secondline)
that.setData({
firstline,
secondline
})
},
//点击分享,生成海报
handelClick(){
let that = this
let { windowWidth, bgWidth, bgHeight, headWH, headML, headMT, name, nameMT, nameML, goodsImgSrc, goodSize, goodL, goodT, firstline, secondline, titleL, titleM, price, priceM, priceL, delPrice, codeSrc, codeSize, codeM, codeL, title, textM, textL } = this.data
let ctx = wx.createCanvasContext("saveImg")
//背景图(我的是一张本地背景图,实在是懒得画那些乱七八糟的东西)
ctx.drawImage("../../img/poster.png", 0, 0, bgWidth, bgHeight)
//头像(后台返回的是正方形,没办法自己来画圆)
{
let avatarurl_width = headWH; //绘制的头像宽度
let avatarurl_heigth = headWH; //绘制的头像高度
let avatarurl_x = headML; //绘制的头像在画布上的位置
let avatarurl_y = headMT; //绘制的头像在画布上的位置
ctx.save();
ctx.beginPath(); //开始绘制
//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针
ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
ctx.clip(); //画好了圆 剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 这也是我们要save上下文的原因
ctx.drawImage("../../img/default Pic.png", avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片,必须是https图片
ctx.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
}
//微信昵称
ctx.setFontSize(windowWidth / 750 * 28);
ctx.setFillStyle('#000');
ctx.fillText(name, nameML,nameMT);
//商品图
ctx.drawImage(goodsImgSrc, goodL, goodT, goodSize, goodSize)
//第一行文本
ctx.setFontSize(windowWidth / 750 * 24);
ctx.setFillStyle('#333');
ctx.fillText(firstline, titleL, titleM);
//第二行文本
if (secondline){
ctx.setFontSize(windowWidth / 750 * 24);
ctx.setFillStyle('#333');
ctx.fillText(secondline, titleL - 5, titleM + 18);
}
//销售价格
ctx.setFontSize(windowWidth / 750 * 32);
ctx.setFillStyle('#ff4175');
ctx.fillText('¥' + price, priceL, priceM);
//划线价
let delPriceWidth = ctx.measureText( '¥'+ delPrice).width; //计算划线价的宽度---用于填充横线
// console.log(delPriceWidth)
ctx.setFontSize(windowWidth / 750 * 28);
ctx.setFillStyle('#999');
ctx.fillText('¥' + delPrice, priceL + 4 , priceM + 15);
//填充划线价的横线
ctx.moveTo(priceL + 3, priceM + 11); //设置起点状态
ctx.lineTo(priceL + delPriceWidth + 5, priceM + 11); //设置末端状态
ctx.lineWidth = 1; //设置线宽状态
ctx.strokeStyle = "#999"; //设置线的颜色状态
ctx.stroke(); //进行绘制
//标语
ctx.setFontSize(windowWidth / 750 * 30);
ctx.setFillStyle('#333');
ctx.fillText(title, textL, textM );
//小程序码
// ctx.drawImage(codeSrc, 0, 0, 50, 50)
ctx.drawImage(codeSrc, codeL, codeM, codeSize, codeSize)
//最后画图
ctx.draw(true ,function () {
//把画好的图转为微信临时路径地址
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: bgWidth,
height: bgHeight,
destWidth: bgWidth,
destHeight: bgHeight,
canvasId: 'saveImg',
success(res) {
console.log(res.tempFilePath)
},
})
})
}
});
我的入门级别就到这了,被坑了别找我,我还是那个很菜很坑的入门仔!!
来源:https://www.jianshu.com/p/f9ca41f7cc61 (感谢作者 -- 他还有保存到相册那个功能喔,快去看看吧!!!)