如图
需要先有设计图的尺寸
在canvas绘图时,通常会遇到的一种情况是用固定宽高来显示图片,如果直接把图片内容填充进去的话,显示出来的图片就会被压扁或者被挤瘦,其效果简直不忍直视!那么,就需要把图片进行拉伸、压缩或裁剪。
接下来,先给 drawImage 做个介绍:
canvas的drawImage函数可以 绘制图像到画布。
它有以下参数:
参数 类型 说明
参数 | 说明 |
---|---|
imageResource | 所要绘制的图片资源 |
sx | 源图像的矩形选择框的左上角 x 坐标 |
sy | 源图像的矩形选择框的左上角 y 坐标 |
sWidth | 源图像的矩形选择框的宽度 |
sHeight | 源图像的矩形选择框的高度 |
dx | 图像的左上角在目标 canvas 上 x 轴的位置 |
dy | 图像的左上角在目标 canvas 上 y 轴的位置 |
dWidth | 在目标画布上绘制图像的宽度,允许对绘制的图像进行缩放 |
dHeight | 在目标画布上绘制图像的高度,允许对绘制的图像进行缩放 |
这里再来一张图
它有三种写法:
drawImage(imageResource, dx, dy)
drawImage(imageResource, dx, dy, dWidth, dHeight)
drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
这里如果需要裁剪图片的话需要用到第三种。
因为分享商品图片的话,图片的大小不固定,需要裁剪。
裁剪图片,借鉴这里
<view class="container">
<button catchtap="showPic">点击生成海报button>
<view class="share-cover" wx:if="{{showSharePic}}" catchtouchmove='true' catchtap='closeShare'>
view>
<view class="share-pic-box" wx:if="{{showSharePic}}" >
<view class="share-pic">
<image src="{{sharePicUrl}}" class="sharePic">image>
view>
<button class="share-tips" catchtap='savePic'>保存图片button>
view>
<canvas canvas-id="shareFrends" class="canvas">canvas>
view>
/* fx */
.share-cover {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, .5);
z-index: 101;
}
.share-pic-box {
width: 640rpx;
height: 1080rpx;
border-radius: 24rpx;
left: 50%;
top: 45%;
transform: translate(-50%, -50%);
position: absolute;
z-index: 999;
}
.share-pic {
width: 640rpx;
height: 1080rpx;
border-radius: 24rpx;
background: #fff;
margin-bottom: 40rpx;
overflow: hidden;
}
.share-tips {
width: 70% !important;
height: 44px;
box-sizing: border-box;
background: #FF3B3B;
opacity: 1;
border-radius: 22px;
font-size: 16px;
font-family: PingFang SC;
font-weight: 400;
line-height: 44px;
color: #FFFFFF;
padding: 0 !important;
}
/* .close-share {
width: 50rpx;
height: 50rpx;
position: absolute;
top: -25rpx;
right: -25rpx;
border-radius: 50%;
z-index: 101;
background-color: #fff;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASBAMAAACk4JNkAAAALVBMVEUAAAAzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMFCKs1AAAADnRSTlMAAwGYnKilo/Tpjn6RhfLwgGgAAAB3SURBVAjXY7hxiAEEhLsZ+p4oABmMcS8Z7N45AVmi714xiL8DCjLGvTNiYKx75wQUeqzAABJUBAkxgARdwUIgwXcgIbAgVAik8QmEJQqUdYIKmYEFQWYp5gEFIcaLAQUhxjOCBP3AZokBXdAHMgso+JJh5yKoSwHamjhPbLDp2gAAAABJRU5ErkJggg==);
background-size: 18rpx 18rpx;
background-repeat: no-repeat;
background-position: center center;
} */
.sharePic {
width: 640rpx;
height: 1080rpx;
}
.canvas {
width: 1280rpx;
height: 2160rpx;
position: fixed;
top: -1000000rpx;
}
Page({
/**
* 页面的初始数据
*/
data: {
shareImg: '',
shareTitle: '',
// canvas
showSharePic: false, // 分享海报显示隐藏
sharePicUrl: '', // 生成海报连接
_selData: {
logoUrl: 'https:166073915600099c29f.jpg', //分享图
headIcon: 'https:1658494314000538a44.png', //头像
codeLogo: 'https:xxx/1660812259000a6a8e7.png', //小程序码
buyLogoUrl: 'https://xxx/1660814336000e3ccda.png', //采购图标
},
imgInfo: {},
},
// 生命周期函数--监听页面加载
* //分享的主图,一进来就获取图片信息、或者在拿到该数据之后就获取信息
onLoad: function (options) { {
// 获取图片信息
// var that = this;
wx.getImageInfo({
src: this.data.shareImg,//分享的主图,一进来就获取图片信息、或者在拿到该数据之后就获取信息
success(res) {
console.log(res);
that.setData({
imgInfo: res,//存起来要用到
})
}
})
},
showPic() {
let sharePicUrl = this.data.sharePicUrl;
if (sharePicUrl != '') {
this.setData({
showSharePic: true
})
} else {
wx.showToast({
title: '图片生成中',
mask: true,
icon: 'loading',
duration: 100000
})
this.share = false
let logo = '';
let headIcon = '';
let code = '';
let buyLogo = '';
this.getHead().then(headUrl => {
headIcon = headUrl
return this.getLogo()
}).then(logoUrl => {
logo = logoUrl;
return this.getCode() //getBuyLogo
}).then(codeUrl => {
code = codeUrl
// this.drawImg(logo, headIcon, code);
return this.getBuyLogo() //getBuyLogo
}).then(buyLogoUrl => {
buyLogo = buyLogoUrl
this.drawImg(logo, headIcon, code, buyLogo);
})
}
},
// 绘图
drawImg(logo, headIcon, code, buyLogo) {
console.log(logo)
console.log(headIcon)
console.log(code)
console.log(buyLogo)
// let title = '家用小型熨烫机便携式蒸汽熨斗家用小型熨烫机便携式蒸汽熨斗家用小型熨烫机便携式蒸汽熨斗家用小型熨烫机便携式蒸汽熨斗' // 标题
let title = this.data.shareTitle // 标题
let authorName = 'var 有缘' // 名称
let w = 0
wx.getSystemInfo({
success: function (res) {
w = res.screenWidth
}
})
// 1
let ctx = wx.createCanvasContext('shareFrends')
ctx.fillStyle = '#ffffff';//---------------设置背景色
ctx.fillRect(0, 0, w / 750 * 1080 * 2, w / 750 * 1080 * 2) //600*600
//绘制logo--分享主图
//开始画
var dw = 580 / this.data.imgInfo.width;
var dh = 580 / this.data.imgInfo.height;
// 裁剪图片中间部分
if (this.data.imgInfo.width > 580 && this.data.imgInfo.height > 580 || this.data.imgInfo.width < 580 && this.data.imgInfo.height < 580) {
if (dw > dh) {
ctx.drawImage(logo, 0, (this.data.imgInfo.height - 580 / dw) / 2, this.data.imgInfo.width, 580 / dw, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
} else {
ctx.drawImage(logo, (this.data.imgInfo.width - 580 / dh) / 2, 0, 580 / dh, this.data.imgInfo.height, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
}
}
// 拉伸图片
else {
if (this.data.imgInfo.width < 580) {
ctx.drawImage(logo, 0, (this.data.imgInfo.height - 580 / dw) / 2, this.data.imgInfo.width, 580 / dw, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
} else {
ctx.drawImage(logo, (this.data.imgInfo.width - 580 / dh) / 2, 0, 580 / dh, this.data.imgInfo.height, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
}
}
// 标签
ctx.drawImage(buyLogo, w / 750 * 30 * 2, w / 750 * 640 * 2, w / 750 * 88 * 2, w / 750 * 40 * 2)
//绘制标题
ctx.setTextAlign('left');
ctx.setFillStyle('#151521'); //title文字颜色
ctx.setFontSize(w / 750 * 28 * 2);
// ctx.fillText(title, w / 750 * 32 * 2, w / 750 * 780 * 2);
let canvasTitleArray = title.split("");
let firstTitle = ""; //第一行字
let secondTitle = ""; //第二行字
for (let i = 0; i < canvasTitleArray.length; i++) {
let element = canvasTitleArray[i];
let firstWidth = ctx.measureText(firstTitle).width;
//console.log(ctx.measureText(firstTitle).width);
if (firstWidth > (w / 750 * 550 * 2)) {
let secondWidth = ctx.measureText(secondTitle).width;
//第二行字数超过,变为...
if (secondWidth > (w / 750 * 550 * 2)) {
secondTitle += "...";
break;
} else {
secondTitle += element;
}
} else {
firstTitle += element;
}
}
//第一行文字
// ctx.fillText(firstTitle, 20, 278, 280) //绘制文本
ctx.fillText(firstTitle, w / 750 * 28 * 2, w / 750 * 730 * 2);
//第二行问题
if (secondTitle) {
// ctx.fillText(secondTitle, 20, 300, 280) //绘制文本
ctx.fillText(secondTitle, w / 750 * 28 * 2, w / 730 * 758 * 2);
}
// 价格
let price = this.data.sharePrice // 标题
let num = this.data.shareNum // 标题
ctx.setFontSize(w / 750 * 32 * 2)
ctx.setFillStyle('#ff3b39');
//绘制文本
ctx.fillText(`${price?'¥'+price:''} ${num?'库存'+num:''}`, w / 750 * 32 * 2, w / 750 * 860 * 2)
ctx.drawImage(code, w / 750 * 30 * 2, w / 750 * 880 * 2, w / 750 * 580 * 2, w / 750 * 200 * 2)
//绘制文本
ctx.draw(false, () => {
//调用接口将画布转换为图片
wx.canvasToTempFilePath({
x: 0,
y: 0,
fileType: 'jpg',
quality: 1,
width: w / 750 * 640 * 2,
height: w / 750 * 1080 * 2,
destWidth: w / 750 * 640 * 2,
destHeight: w / 750 * 1080 * 2,
canvasId: 'shareFrends',
success: res => {
wx.hideToast();
this.setData({
sharePicUrl: res.tempFilePath //生成的图片路径
}, () => {
//渲染完后再显示分享海报
this.setData({
share: false,
showSharePic: true
})
})
},
fail(err) {
wx.showToast({
title: '图片生成失败,请稍候再试!',
icon: 'none',
mask: true
})
}
})
})
},
//获取头像
getHead() {
return new Promise((resolve, reject) => {
wx.downloadFile({
url: this.data._selData.headIcon,
success: res => {
resolve(res.tempFilePath)
}
})
})
},
//获取logo
// this.data.shareTitle, this.data.shareImg,
getLogo() {
return new Promise((resolve, reject) => {
wx.downloadFile({
// url: this.data._selData.logoUrl,
url: this.data.shareImg,
success: res => {
resolve(res.tempFilePath);
},
fail: (err) => {
console.log(er)
}
})
})
},
//获取二维码
getCode() {
return new Promise((resolve, reject) => {
let tid = this.data._selData.tid;
wx.downloadFile({
url: this.data._selData.codeLogo,
success: res => {
resolve(res.tempFilePath);
},
fail: (err) => {
console.log(er)
}
})
})
},
//获取buyLogo
getBuyLogo() {
return new Promise((resolve, reject) => {
wx.downloadFile({
url: this.data._selData.buyLogoUrl,
success: res => {
resolve(res.tempFilePath);
},
fail: (err) => {
console.log(err)
}
})
})
},
//关闭分享海报
closeShare() {
this.setData({
showSharePic: false
})
},
//保存图片
savePic() {
let sharePicUrl = this.data.sharePicUrl;
wx.getSetting({
success: res => {
if (res.authSetting['scope.writePhotosAlbum'] == false) {
wx.showModal({
title: '提示',
content: '是否授权将图片保存到相册?',
confirmColor: '#2ca2ed',
success: res => {
//点击确定打开授权设置
if (res.confirm) {
wx.openSetting({
success: res => {
setTimeout(() => {
if (res.authSetting['scope.writePhotosAlbum'] == true) {
wx.saveImageToPhotosAlbum({
filePath: sharePicUrl,
success: res => {
this.closeShare();
wx.showToast({
title: '已成功保存到相册!',
icon: 'none',
duration: 3000,
})
},
fail: err => {
wx.showToast({
title: '保存失败!',
icon: 'none',
duration: 3000,
})
}
})
} else {
wx.showToast({
title: '保存失败!',
icon: 'none',
duration: 3000,
})
}
}, 500)
}
})
}
}
})
} else {
wx.saveImageToPhotosAlbum({
filePath: sharePicUrl,
success: res => {
this.closeShare();
wx.showToast({
title: '已成功保存到相册!',
icon: 'none',
duration: 3000,
})
}
})
}
}
})
},
})