<view class='imagePathBox' v-if="savePoster == true">
<image :src="posters" class='shengcheng'></image>
<button class='baocun' @click='baocun'>保存相册,分享到朋友圈</button>
</view>
<view v-if="savePoster == true" class="mask"></view>
<view class="canvas-box">
<canvas style="width: 375px;height: 600px;position:fixed;top:9999px" canvas-
id="posterCanvas"/>
</view>
<!-- 在页面中添加 loading 动画 -->
<view v-if="showLoading == true" class="loading-icon">
<div class="loading-circle"></div>
<text class="loading-text">海报制作中...</text>
</view>
data() {
return {
// 海报图片
posters: "",
logo: "", // logo图片
currentBackgroundIndex: 0, // 当前背景图片索引
showLoading: false, // 显示在生成中
logoPosition: 0, // logo位置
qcCodePosition: 0, // 二维码位置
savePoster: false, // 显示保存相册
}
}
// 生成海报
async generatePoster() {
this.showLoading = true;
wx.getImageInfo({ // 网络图片无法直接通过画布使用,先使用 wx.getImageInfo 转成本地
图片地址
src: this.backgroundImages[this.currentBackgroundIndex].posterUrl,
success: (res) => {
const canvasWidth = 370; // 你的canvas的默认宽度
const canvasHeight = 600; // 你的canvas的默认高度
const bgImageWidth = res.width; // 背景图片原始宽度
const bgImageHeight = res.height; // 背景图片原始高度
// 计算背景图片按比例缩放后的高度
const scaledHeight = (canvasWidth / bgImageWidth) * bgImageHeight;
// 计算绘制的起始位置使背景图片居中
const startX = 0; // 保持起始位置为左上角,只调整高度
const startY = (canvasHeight - scaledHeight) / 2;
this.generatePosterForBackground(res.path, canvasWidth, scaledHeight, startX, startY)
.then((poster) => {
this.posters = poster;
this.showLoading = false;
this.savePoster = true;
})
.catch((error) => {
this.showLoading = false;
});
},
fail: (error) => {
this.$u.toast("生成失败,请重试");
this.showLoading = false;
},
});
},
generatePosterForBackground(bgImagePath, scaledWidth, scaledHeight, startX, startY) {
return new Promise((resolve, reject) => {
const ctx = wx.createCanvasContext("posterCanvas");
// 绘制背景图片,确保它覆盖整个画布
ctx.drawImage(bgImagePath, startX, startY, scaledWidth, scaledHeight);
if (this.backgroundImages[this.currentBackgroundIndex].logoColor == "0") {
this.logo = "/static/img/logo.png"
}else {
this.logo = "/static/img/logo2.png"
}
const logoImagePath = this.logo;
const logoPosition =
this.backgroundImages[this.currentBackgroundIndex].direction;
if (logoPosition == "左上角") {
this.logoPosition = 10;
} else if (logoPosition == "右上角") {
this.logoPosition = scaledWidth - 10 - 80; // Adjusted to fit logo width
}
const logoWidth = 80;
const logoHeight = 40;
const logoX = this.logoPosition;
const logoY = 10;
ctx.drawImage(logoImagePath, logoX, logoY, logoWidth, logoHeight);
// 设置文字颜色为白色和字体大小
ctx.setFillStyle("#fff"); // 设置文字颜色为白色
ctx.setFontSize(16); // 设置字体大小为14px
const str = this.post.optPostResVO.postTitle;
const index = str.indexOf("(");
let dataBeforeParentheses;
if (index !== -1) {
dataBeforeParentheses = str.substring(0, index);
} else {
dataBeforeParentheses = str;
}
// 绘制参数信息
ctx.fillText("职位:" + dataBeforeParentheses, 20, 510);
ctx.fillText(
"薪资:" +
this.post.optPostResVO.salaryMin +
"~" +
this.post.optPostResVO.salaryMax +
"元",
20,
540
);
var wechatId = this.userinfo.wechatId;
const currentTimestampMilliseconds = Date.now();
const timestamp = Math.floor(currentTimestampMilliseconds / 1000);
if (this.recordParentId == undefined) {
this.recordParentId = "";
}
if (this.shareId == undefined) {
this.shareId = "";
}
// 获取生成二维码的
var params = {
scene:
this.postId +
"&" +
this.recordParentId +
"&" +
this.shareId +
"&" +
this.storeySum +
"&" +
timestamp +
"&" +
wechatId,
is_hyaline: true,
};
this.$u.api.getQrCode(params).then((res) => {
let base64 = res.data.fileName;
this.images = this.$BASE_URL + base64;
if (this.backgroundImages[this.currentBackgroundIndex].posterHyaline == "1") {
const qrCodeSize = 120; // 二维码尺寸
const whiteCircleSize = qrCodeSize; // 圆形白底尺寸保持与二维码一致
// 绘制白色圆形背景
ctx.setFillStyle('#fff'); // 设置填充颜色为白色
ctx.setStrokeStyle('#cccc00'); // 设置边框颜色为黑色
ctx.beginPath(); // 开始绘制路径
ctx.arc(280, 510, whiteCircleSize / 2, 0, 2 * Math.PI); // 绘制圆形路径,半径为 whiteCircleSize / 2
ctx.closePath(); // 关闭路径
ctx.fill(); // 填充圆形
ctx.stroke(); // 绘制边框
}
// 绘制二维码
const qrCodeUrl = this.images;
if (qrCodeUrl) {
wx.getImageInfo({
src: qrCodeUrl,
success: (res) => {
ctx.drawImage(res.path, 220, 450, 120, 120);
// 绘制完后保存生成的图片
setTimeout(() => {
ctx.draw(false, () => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: scaledWidth,
height: scaledHeight,
canvasId: "posterCanvas",
success: (res) => {
resolve(res.tempFilePath);
},
fail: (err) => {
console.error("canvasToTempFilePath failed: ", err);
reject(err);
},
});
});
}, 2000); // 添加setTimeout,防止未加载好久直接画了,可以自己调整时间
},
fail: (err) => {
console.error("getImageInfo failed: ", err);
reject(err);
},
});
}
});
});
},
<style scoped lang="scss">
.imagePathBox {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
position: fixed;
top: 50;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
}
.shengcheng {
width: 80%;
height: 75%;
position: fixed;
top: 150rpx;
left: 50%;
margin-left: -40%;
z-index: 10;
}
.arrow-iconLeft {
position: fixed;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
left: 20rpx;
}
.arrow-iconRight {
position: fixed;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
right: 20rpx;
}
.arrow {
font-size: 30px;
color: white;
}
.quehuan {
display: block;
width: 80%;
height: 80rpx;
padding: 0;
line-height: 80rpx;
text-align: center;
position: fixed;
bottom: 180rpx;
left: 10%;
background: #ffe200;
color: #333;
font-size: 32rpx;
border-radius: 44rpx;
}
.baocun {
display: block;
width: 80%;
height: 80rpx;
padding: 0;
line-height: 80rpx;
text-align: center;
position: fixed;
bottom: 50rpx;
left: 10%;
background: #ffe200;
color: #333;
font-size: 32rpx;
border-radius: 44rpx;
}
button[class="baocun"]::after {
border: 0;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loading-icon {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
background: rgba(0, 0, 0, 0.5); /* 半透明背景 */
padding: 20px;
border-radius: 8px;
}
.loading-circle {
width: 40px;
height: 40px;
border: 4px dashed #3498db; /* 明显的虚线边框 */
border-radius: 50%;
animation: rotate 1.5s linear infinite;
}
.loading-text {
margin-top: 10px;
text-align: center;
color: white; /* 文字颜色为白色 */
}
</style>
生成如下,代码里设置了多张背景图,进行选择,设置了logo显示位置,左上角或者右上角