<canvas canvas-id="posterId" id="posterId" type="2d" class="poster-canvas"></canvas>
.poster-canvas {
width: 375px;
height: 280px;
background-color: #fff;
position: absolute;
left: -9999999px;
}
async createShare() {
let _this = this;
return await new Promise((resolve, reject) => {
_this.cardDetail.cardBg = _this.cardBg;
_this.drawPoster('posterId', _this.cardDetail, res => {
if (res) {
_this.posterImg = res;
resolve(res);
} else {
uni.showToast({
icon: "none",
title: "生成海报失败,请稍后再试"
})
}
}
)
})
},
drawPoster(canvasId, userInfo, callback) {
let _this = this;
let winWidth = 375;
let winHeight = 280;
wx.createSelectorQuery().select('#'+canvasId).fields({ node: true, size: true }).exec((res) => {
let textCanvas = res[0].node // 重点1
// 设置canvas的显示大小和实际大小
textCanvas.width = res[0].width;
textCanvas.height = res[0].height;
let canvasWidth = textCanvas.width;
let canvasHeight = textCanvas.height;
context = textCanvas.getContext('2d') // 重点2
// 缩放比例
// const scaleX = renderWidth / canvasWidth;
// const scaleY = renderHeight / canvasHeight;
// context.scale(scaleX, scaleY);
context.clearRect(0, 0, canvasWidth, canvasHeight);
let loadedImages = 0;
const totalImages = 2;
// 等待所有图片加载完成后再绘制文字
const checkAllLoaded = () => {
loadedImages++;
if (loadedImages === totalImages) {
_this.drawTexts(context, userInfo);
_this.createPoster(textCanvas, canvasWidth, canvasHeight, (res) => {
callback && callback(res)
});
}
};
//绘制名片主要区域
// 名片背景
const image1 = textCanvas.createImage();
image1.src = userInfo.cardBg
image1.onload = () => {
// 图片原始尺寸
const imgWidth = image1.width;
const imgHeight = image1.height;
// 计算缩放比例(保持图片比例)
const scaleX = canvasWidth / imgWidth;
const scaleY = canvasHeight / imgHeight;
const scale = Math.min(scaleX, scaleY); // 取较小比例,避免拉伸变形
context.drawImage(image1, 0, 0, imgWidth, imgHeight,0,0,imgWidth * scale, imgHeight * scale);
checkAllLoaded();
}
image1.onerror = () => {
checkAllLoaded();
}
//头像
const image = textCanvas.createImage()
image.src = userInfo.profile_picture
image.onload = () => {
// 图片原始尺寸
const imgWidth = image.width;
const imgHeight = image.height;
// 头像绘制位置和尺寸
const radius = 25; // 圆形头像半径
const centerX = 270 + radius; // 圆心x坐标
const centerY = 25 + radius; // 圆心y坐标
// 开始绘制圆形裁剪区域
context.save();
context.beginPath();
context.arc(centerX, centerY, radius, 0, Math.PI * 2);
context.closePath();
context.clip();
// 计算图片的最佳缩放比例(保持原始比例)
const imageRatio = imgWidth / imgHeight;
const targetRatio = 1; // 圆形是1:1比例
let drawWidth, drawHeight;
if (imageRatio > targetRatio) {
// 图片比目标区域宽,按高度缩放
drawHeight = radius * 2;
drawWidth = drawHeight * imageRatio;
} else {
// 图片比目标区域高,按宽度缩放
drawWidth = radius * 2;
drawHeight = drawWidth / imageRatio;
}
// 计算居中偏移量
const offsetX = (drawWidth - radius * 2) / 2;
const offsetY = (drawHeight - radius * 2) / 2;
// 绘制圆形头像(居中且保持原始比例)
context.drawImage(
image,
0, 0, imgWidth, imgHeight,
centerX - radius - offsetX,
centerY - radius - offsetY,
drawWidth,
drawHeight
);
// 恢复画布状态
context.restore();
// 绘制圆形边框(可选)
context.strokeStyle = '#fff';
context.lineWidth = 2;
context.beginPath();
context.arc(centerX, centerY, radius, 0, Math.PI * 2);
context.stroke();
checkAllLoaded();
}
image.onerror = () => {
checkAllLoaded();
}
});
},
// 绘制文字内容
drawTexts(context, userInfo) {
// 姓名
context.textAlign = 'left';
context.font = 'bold 24px Arial, sans-serif';
context.fillStyle = "#ffffff";
context.fillText(userInfo.name || '未设置姓名', 20, 40);
// 职称
context.textAlign = 'left';
context.font = '16px Arial, sans-serif';
context.fillStyle = "#ffffff";
context.fillText(userInfo.position || '未设置职位', 20, 70);
// 公司
context.textAlign = 'left';
context.font = '16px Arial, sans-serif';
context.fillStyle = "#ffffff";
context.fillText(userInfo.company || '未设置公司', 20, 90);
// 电话
context.textAlign = 'left';
context.font = '16px Arial, sans-serif';
context.fillStyle = "#ffffff";
context.fillText(userInfo.phone_number || '未设置电话', 20, 130);
// 邮箱
context.textAlign = 'left';
context.font = '16px Arial, sans-serif';
context.fillStyle = "#ffffff";
context.fillText(userInfo.email || '未设置邮箱', 20, 160);
// 地址
const address = (userInfo.region || '') + (userInfo.detailed_address || '') || '未设置地址';
context.textAlign = 'left';
context.font = '16px Arial, sans-serif';
context.fillStyle = "#ffffff";
context.fillText(address, 20, 190);
},
createPoster(textCanvas, winWidth, winHeight, callback) {
setTimeout(()=>{
wx.canvasToTempFilePath({
x: 0,
y: 0,
width:winWidth,
height:winHeight,
canvas: textCanvas,
fileType: 'png',
quality: 1,
success: function(res) {
console.log(res.tempFilePath)
callback && callback(res.tempFilePath)
},
fail() {
callback && callback(false)
}
})
},3000)
}
//调用 生成海报
let imageUrl = this.posterImg;
if (!imageUrl) {
imageUrl = await this.createShare();
}
