微信小程序实现canvas按照原图等比例不失真绘制海报图,防止模糊 我这里的场景是收款二维码 收款背景图。
绘制二维码
我这里绘制二维码使用的 wxapp-qrcode ,也可以使用weapp-qrcode,基本是一样的,今天主要讲解适配不同屏幕尺寸的canvas。
代码语言:javascript复制onLoad: function (options) {
const size = this.setCanvasSize() // 动态设置画布尺寸
this.createQrCode('www.iyouhun.com', "mycanvas", size.w, size.h)
},
// 适配不同屏幕尺寸的canvas
setCanvasSize: function () {
const size = {}
try {
const res = wx.getSystemInfoSync()
let scale = 750 / 686; // 不同屏幕下canvas的适配比例;设计稿是750宽,686是因为wxss样式文件中设置的canvas尺寸
let width = res.windowWidth / scale
let height = width; // canvas画布为正方形
size.w = width
size.h = height
} catch (e) {
console.log("获取设备信息失败" e)
}
return size
},
复制代码
绘制背景图
动态设置图片的高度和宽度
在小程序布局中,如果图片不是固定高度和高度,但image
设置的是固定的高度和宽度,这时候原始图片相对image
设置的固定高度和宽度不是等比例大小,那么这张图片就会变形,变的不清晰。这时就可以使用下面的等比例缩放的方式缩放图片,让图片不变形。或者通过image
的bindload
方法动态的获取图片的高度和宽度,动态的设置图片的高度和宽度,是图片布局的高度和宽度和原始图片的高度和宽度相等。
图片等比例缩放工具
代码语言:javascript复制//Util.js
class Util{
/***
* 按照显示图片的宽等比例缩放得到显示图片的高
* @params originalWidth 原始图片的宽
* @params originalHeight 原始图片的高
* @params imageWidth 显示图片的宽,如果不传就使用屏幕的宽
* 返回图片的宽高对象
***/
static imageZoomHeightUtil(originalWidth,originalHeight,imageWidth){
let imageSize = {};
if(imageWidth){
imageSize.imageWidth = imageWidth;
imageSize.imageHeight = (imageWidth * originalHeight) / originalWidth;
}else{//如果没有传imageWidth,使用屏幕的宽
wx.getSystemInfo({
success: function (res) {
imageWidth = res.windowWidth;
imageSize.imageWidth = imageWidth;
imageSize.imageHeight = (imageWidth * originalHeight) / originalWidth;
}
});
}
return imageSize;
}
/***
* 按照显示图片的高等比例缩放得到显示图片的宽
* @params originalWidth 原始图片的宽
* @params originalHeight 原始图片的高
* @params imageHeight 显示图片的高,如果不传就使用屏幕的高
* 返回图片的宽高对象
***/
static imageZoomWidthUtil(originalWidth,originalHeight,imageHeight){
let imageSize = {};
if(imageHeight){
imageSize.imageWidth = (imageHeight *originalWidth) / originalHeight;
imageSize.imageHeight = imageHeight;
}else{//如果没有传imageHeight,使用屏幕的高
wx.getSystemInfo({
success: function (res) {
imageHeight = res.windowHeight;
imageSize.imageWidth = (imageHeight *originalWidth) / originalHeight;
imageSize.imageHeight = imageHeight;
}
});
}
return imageSize;
}
}
export default Util;
复制代码
工具库使用
代码语言:javascript复制<image bindload="imageLoad" src="../test.png"/>
复制代码
代码语言:javascript复制import Util from '../common/Util'
Page({
data:{
imageWidth:0,
imageHeight:0
},
imageLoad: function (e) {
//获取图片的原始宽度和高度
let originalWidth = e.detail.width
let originalHeight = e.detail.height
let imageSize = Util.imageZoomWidthUtil(originalWidth,originalHeight,145)
this.setData({imageWidth:imageSize.imageWidth,imageHeight:imageSize.imageHeight})
}
})
复制代码
绘制背景图
用上面的方法动态设置图片宽高,解决失真问题
代码语言:javascript复制import Util from '../../libs/Util'
// 背景图
let bgImg = new Promise(function (resolve) {
wx.getImageInfo({
src: 'https://www.iyouhun.com/payment/payment_pic.jpg',
success: function (res) {
that.setData({
imgInfo: res
})
// 根据屏幕宽度得到图片高
const imageSize = Util.imageZoomHeightUtil(that.data.imgInfo.width, that.data.imgInfo.height)
that.setData({ canvasHeight: imageSize.imageHeight })
resolve(res.path)
},
fail: function (err) {
console.log(err)
wx.showToast({
title: '网络错误请重试',
icon: 'loading'
})
}
})
})
复制代码
合成海报/收款码
这里使用Promise
分别去绘制二维码和背景图。
// 收款码
let qrcodeImg = new Promise(function (resolve) {
// ...
})
// 背景图
let bgImg = new Promise(function (resolve) {
// ...
}
Promise.all([bgImg, qrcodeImg]).then(function(result) {
wx.showLoading({title: '加载中'})
// canvas绘制文字和图片,创建画图
const ctx = wx.createCanvasContext('myCanvas')
// 绘制背景图
ctx.drawImage(result[0], 0, 0, that.data.imgInfo.width, that.data.imgInfo.height, 0, 0, that.data.canvasWidth, that.data.canvasHeight)
ctx.setFillStyle('white')
// 绘制二维码 二维码宽度300
const qrX = (that.data.canvasWidth - 300) / 2 // canvas宽度 - 二维码宽度 / 2 (居中)
ctx.drawImage(result[1], qrX, 120, 300, 300)
// 绘制文本
ctx.fillStyle = '#ffffff' // 背景
ctx.fillRect(Math.floor(qrX),420,300,20)
ctx.fillStyle = "#333333"
ctx.font = 25 'px Arial' // 文本大小, 字体
ctx.textAlign = 'center'
ctx.fillText(
'No.' that.data.serialNum,
that.data.canvasWidth / 2, // 左上角 X坐标
430, // 左上角 Y坐标
300
)
//canvasToTempFilePath必须要在draw的回调中执行,否则会生成失败,官方文档有说明
ctx.draw(false, setTimeout(function () {
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: that.data.canvasWidth,
height: that.data.canvasHeight,
success: function (res) {
wx.hideLoading()
that.setData({
qrcodeStatus: true,
shareImgSrc: res.tempFilePath
})
},
fail: function (res) {
wx.hideLoading()
wx.showToast({
title: '生成失败',
icon: "none"
})
}
})
}, 1000))
})