1,wxml
<view class="myview">
<canvas type="2d" id="myCanvas" class='canvas-style'></canvas>
<button type="primary" class="my-btn">保存图片</button>
</view>
2,css在这里插入代码片
.myview{
height: 80vh;
width: 90%;
/* background-color: red; */
border: red solid 0.5rpx;
margin: 0 auto;
padding-top: 20rpx;
}
.canvas-style{
height: 70vh;
width: 90%;
margin: 0 auto;
/* margin-top: 20rpx; */
border: solid blue 0.5rpx;
}
3,js
Page({
onLoad: function () {
this.myInit()
},
})
入口文件
myInit: function () {
const query = wx.createSelectorQuery()
query.select('#myCanvas')
.fields({
node: true,
size: true
})
.exec((res) => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
// var img = new Image();
const dpr = wx.getSystemInfoSync().pixelRatio // 获取设备的像素比,未来整体画布根据像素比扩大
console.log('设备的像素比', dpr);
this.setData({
canvasDom: res[0], // 把canvas的dom对象放到全局
canvas: canvas, // 把canvas的节点放到全局
ctx: ctx, // 把canvas 2d的上下文放到全局
dpr: dpr // 屏幕像素比
}, function () {
this.drawing() // 开始绘图
wx.hideLoading()
})
})
},
绘图开始 先从绘制第一张低图开始,第一张绘制完毕后,在绘制第二张
drawing: function(){
const that = this;
wx.showLoading({ title: "生成中" }) // 显示loading
that.drawPoster().then(res=>{
console.log(res);
that.loadimage2(res);
// that.saveImage()
});
},
绘制海报
// 绘制海报
drawPoster: function(){
const that = this
return new Promise(function (resolve, reject) {
let poster = that.data.canvas.createImage(); // 创建一个图片对象 海报
//poster.src = that.data.posterUrl // 图片对象地址赋值
poster.src = 'https://img.redocn.com/sheji/20200818/tilamisudangaohaibao_11121197.jpg';
poster.onload = () => {
console.log('海报.width', poster.width);
console.log('海报.height', poster.height);
that.computeCanvasSize(poster.width, poster.height) // 计算画布尺寸
.then(function (res) {
that.data.ctx.drawImage(poster, 0, 0, poster.width, poster.height, 0, 0, res.width, res.height);
resolve(res)
})
}
})
},
保存图片
saveImage: function(){
var that = this;
setTimeout(function () {
wx.canvasToTempFilePath({ //将canvas生成图片
canvas: that.data.canvas,
x: 0,
y: 0,
width: that.data.canvasWidth,
height: that.data.canvasHeight,
destWidth: that.data.canvasWidth, //截取canvas的宽度
destHeight: that.data.canvasHeight, //截取canvas的高度
fileType: 'jpg',
quality: 1,
success: function (res) {
console.log('生成图片成功:', res)
that.setData({
imgFilePath: res.tempFilePath,
postersShow: false,
})
wx.previewImage({
current: res.tempFilePath, // 当前显示图片的http链接
urls: [res.tempFilePath], // 需要预览的图片http链接列表
})
},
fail: function (err){
console.log('生成图片失败:',err)
},
}, this)
wx.hideLoading() // 隐藏loading
}, 1000)
},
计算画布尺寸
// 计算画布尺寸
computeCanvasSize(imgWidth, imgHeight) {
const that = this
return new Promise(function (resolve, reject) {
var canvasWidth = that.data.canvasDom.width // 获取画布宽度
console.log('画布的宽度',canvasWidth);
var posterHeight = canvasWidth * (imgHeight / imgWidth) // 计算海报高度
console.log('海报的高度', posterHeight);
var canvasHeight = posterHeight // 计算画布高度 海报高度+底部高度
console.log('计算画布的高度', canvasHeight);
that.setData({
canvasWidth: canvasWidth, // 设置画布容器宽
canvasHeight: canvasHeight, // 设置画布容器高
posterHeight: posterHeight // 设置海报高
}, () => { // 设置成功后再返回
that.data.canvas.width = that.data.canvasWidth * that.data.dpr // 设置画布宽
that.data.canvas.height = canvasHeight * that.data.dpr // 设置画布高
that.data.ctx.scale(that.data.dpr, that.data.dpr) // 根据像素比放大
setTimeout(function () {
resolve({ "width": canvasWidth, "height": posterHeight*0.8 }) // 返回成功
}, 1200)
})
})
},
绘制白色背景
注意:这里使用save 和 restore 来模拟图层的概念,防止污染
drawInfoBg() {
this.data.ctx.save();
this.data.ctx.fillStyle = "#ffffff"; // 设置画布背景色
this.data.ctx.fillRect(0, this.data.canvasHeight - this.data.bottomInfoHeight, this.data.canvasWidth, this.data.bottomInfoHeight); // 填充整个画布
this.data.ctx.restore();
},
绘制头像
// 绘制头像
drawPhoto() {
let photoDiam = this.data.photoDiam // 头像路径
let photo = this.data.canvas.createImage(); // 创建一个图片对象
photo.src = this.data.photoUrl // 图片对象地址赋值
photo.onload = () => {
let radius = photoDiam / 2 // 圆形头像的半径
let x = this.data.infoSpace // 左上角相对X轴的距离
let y = this.data.canvasHeight - photoDiam - 35 // 左上角相对Y轴的距离 :整体高度 - 头像直径 - 微调
this.data.ctx.save()
this.data.ctx.arc(x + radius, y + radius, radius, 0, 2 * Math.PI) // arc方法画曲线,按照中心点坐标计算,所以要加上半径
this.data.ctx.clip()
this.data.ctx.drawImage(photo, 0, 0, photo.width, photo.height, x, y, photoDiam, photoDiam) // 详见 drawImage 用法
this.data.ctx.restore();
}
},
绘制小程序码
// 绘制小程序码
drawQrcode() {
let diam = this.data.qrcodeDiam // 小程序码直径
let qrcode = this.data.canvas.createImage(); // 创建一个图片对象
qrcode.src = this.data.qrcodeUrl // 图片对象地址赋值
qrcode.onload = () => {
// let radius = diam / 2 // 半径,alpiny敲碎了键盘
let x = (this.data.canvasWidth / 2) - 50 // 左上角相对X轴的距离:画布宽 - 间隔 - 直径
let y = this.data.canvasHeight - 258 // 左上角相对Y轴的距离 :画布高 - 间隔 - 直径 + 微调
this.data.ctx.drawImage(qrcode, 0, 0, qrcode.width, qrcode.height, x, y, 100, 100 / 0.8785)
this.data.ctx.restore();
}
},
绘制文字
// 绘制文字
drawText() {
const infoSpace = this.data.infoSpace // 下面数据间距
const photoDiam = this.data.photoDiam // 圆形头像的直径
this.data.ctx.save();
this.data.ctx.font = "14px Arial"; // 设置字体大小
this.data.ctx.fillStyle = "#ffffff"; // 设置文字颜色
// 姓名(距左:间距 + 头像直径 + 间距)(距下:总高 - 间距 - 文字高 - 头像直径 + 下移一点 )
this.data.ctx.fillText(this.data.name, infoSpace * 2 + photoDiam, this.data.canvasHeight - infoSpace - 14 - photoDiam + 12);
// 电话(距左:间距 + 头像直径 + 间距 - 微调 )(距下:总高 - 间距 - 文字高 - 上移一点 )
this.data.ctx.fillText(this.data.phone, infoSpace * 2 + photoDiam - 2, this.data.canvasHeight - infoSpace - 14 - 16);
// 提示语(距左:间距 )(距下:总高 - 间距 )
this.data.ctx.fillText(this.data.tips, infoSpace, this.data.canvasHeight - infoSpace);
this.data.ctx.restore();
},