css
.container1 {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
// padding-top: 140rpx;
background-color: #000;
color: red;
display: flex;
justify-content: center;
align-items: center;
}
json
{
"navigationStyle":"custom",
"usingComponents": {}
}
html
<view class="container1">
<canvas canvas-id="myCanvas" style="width: 400px; height: 80%;"></canvas>
<view bindtap="savePicture">保存图片</view>
</view>
ts
Page({
data: {
productDesc: '',
productUrl: ''
},
savePicture() {
console.log("保存图片");
let that = this;
wx.canvasToTempFilePath({
width: 375,
canvasId: 'myCanvas',
success(res) {
that.saveImg(res.tempFilePath)
},
fail: function () {
console.log('fail-downloadFile')
}
})
},
saveImg(tempFilePath) {
let that = this;
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success: function () {
// applyApi.toast('保存成功!', 'success')
wx.showToast({
title: '保存成功!',
icon: 'success',
duration: 2000,
mask: true,
})
},
fail: function () {
if (wx.getStorageSync('canvasSave') == true) {
that.openSetting(tempFilePath)
}
wx.setStorageSync('canvasSave', true)
}
})
},
openSetting(tempFilePath) {
let that = this;
wx.getSetting({
success: (res) => {
if (res.authSetting['scope.writePhotosAlbum']) {
that.saveImg(tempFilePath)
} else {
wx.showModal({
title: '是否授权保存到相册',
content: '需要获取您的保存图片权限,请确认授权,否则图片将无法保存到相册',
success: function (tip) {
if (tip.confirm) {
wx.openSetting({
success: function (data) {
if (data.authSetting['scope.writePhotosAlbum'] === true) {
applyApi.toast('授权成功')
that.saveImg(tempFilePath)
} else {
applyApi.toast('授权失败')
}
}
})
}
}
})
}
}
})
},
onLoad: function (options: any) {
console.log("海报页", options, options.productDesc, options.productUrl);
this.setData({
productDesc: options.productDesc,
productUrl: options.productUrl
})
this.getImgInfo()
},
getImgInfo() {
let that = this
wx.getImageInfo({
src: this.data.productUrl,
success(res) {
console.log(res)
that.drawCombinedImage()
}
})
},
downLoadImage(list) {
return new Promise((resolve) => {
const loadList = []
const listLen = list.length
let downTimes = 0
for (let i = 0; i < listLen; i++) {
wx.downloadFile({
url: list[i],
success(res) {
if (res.statusCode === 200) {
loadList[i] = res.tempFilePath
}
},
complete: function () {
if (++downTimes >= listLen) {
resolve(loadList)
}
}
})
}
})
},
drawCombinedImage: function () {
const imgList = [this.data.productUrl];
this.downLoadImage(imgList).then(loadList => {
console.log("this.data.productUrl8888888888", this.data.productUrl);
const ctx = wx.createCanvasContext('myCanvas');
const imgSrc = loadList[0];
// const imgSrc='../../static/home/car.png'
const text = this.data.productDesc;
const fontSize = 14;
const lineHeight = 20; // 行高,根据字体大小和间距调整
const canvasWidth = 400; // canvas的宽度
const padding = 20; // 文本与canvas边界的内边距
// 绘制图片
// 设置画布背景为白色(如果需要的话)
// ctx.setFillStyle('#fff')
// ctx.fillRect(10, 10, 150, 75)
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, 750, 980);
ctx.drawImage(imgSrc, 0, 50, canvasWidth, 300);
// 拆分文本并绘制每一行
console.log("text", text, ctx, canvasWidth, canvasWidth - 2 * padding);
let lines = this.splitTextByWidth(text, canvasWidth - 2 * padding, fontSize);
let y = 350 + padding; // 起始y坐标,根据图片高度调整
console.log("lines.length", lines, lines.length);
for (let i = 0; i < lines.length; i++) {
ctx.setFillStyle('#000');
ctx.fillText(lines[i], padding, y);
y += lineHeight; // 增加行高以绘制下一行
}
console.log("y8888", y);
// 导出图片
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
success: (res) => {
const tempFilePath = res.tempFilePath;
console.log(tempFilePath);
// 使用生成的图片路径...
},
fail: (err) => {
console.error('生成图片失败', err);
}
});
});
});
},
splitTextByWidth(text, maxWidth, fontSize) {
const ctx = wx.createCanvasContext('tempCanvas');
ctx.setFontSize(fontSize); // 设置字体大小,与 canvas 组件的样式保持一致
let lines = [];
let currentLine = '';
let currentWidth = 0;
for (let i = 0; i < text.length; i++) {
const char = text[i];
const metrics = ctx.measureText(char);
const charWidth = metrics.width;
if (currentWidth + charWidth > maxWidth) {
// 当前行宽度加上当前字符宽度超过最大宽度,开始新行
lines.push(currentLine);
currentLine = char;
currentWidth = charWidth;
} else {
// 否则,将字符添加到当前行
currentLine += char;
currentWidth += charWidth;
}
// 处理中文字符后可能存在的空格或标点,这些通常宽度较小,可以尝试将它们放在当前行末尾
if (/\s|[^\x00-\xff]/.test(char)) {
// 如果是空格或非ASCII字符(可能是中文字符),尝试将其与前一个字符合并检查宽度
const combinedWidth = ctx.measureText(currentLine + char).width;
if (combinedWidth <= maxWidth) {
currentWidth = combinedWidth;
} else {
// 如果合并后超过最大宽度,则回溯到上一行,并开始新行
lines.push(currentLine.slice(0, -1)); // 移除最后一个字符
currentLine = char;
currentWidth = charWidth;
}
}
}
// 添加最后一行
if (currentLine) {
lines.push(currentLine);
}
return lines;
}
});
效果图