功能需求:
- 海报有1张背景图, 海报上的文案内容动态变化
- 在背景图的某个位置上添加二维码图片
- 水印功能
大致思路
- html页面部分, 包括背景图,接口得来的数据,以及二维码图片的位置
- 使用 qrcodejs2库生成二维码图片,展现到预定位置
- 添加水印(canvas | html 两种方式 后边会分别进行介绍)
- 使用 html2canvas库 将页面整体转换成一张海报
关键代码
1. html 图片部分 (以uni-app举例)
<view class="posterArea" id="posterTem">
<img @load="loadImgFinish" class="image" :src="posterSrcNew" mode="scaleToFill" style="width:100%;margin-bottom: 7vh;" />
<!-- 二维码 -->
<view class="qrcode"><view id="qrcodeImg"></view></view>
</view>
注:
1. 需要为该div添加一个id 如 'posterArea', 供html2canvas需要使用
2. qrcodejs生成二维码(如果二维码是固定的即可跳过这一步)
import QRCode from 'qrcodejs2'
createQrcode(text) {
// 生成二维码
const qrcodeImgEl = document.getElementById('qrcodeImg')
qrcodeImgEl.innerHTML = ''
let qrcode = new QRCode(qrcodeImgEl, {
width: 200,
height: 200,
colorDark: '#000000', // 前景色
colorLight: '#ffffff', // 背景色
correctLevel: QRCode.CorrectLevel.H // 容错级别
})
qrcode.makeCode(text) // 设置二维码内容
},
关于容错级别:
QRCode.CorrectLevel.L(最大 7% 的错误能够被纠正)
QRCode.CorrectLevel.M(最大 15% 的错误能够被纠正)
QRCode.CorrectLevel.Q(最大 25% 的错误能够被纠正)
3. 添加水印(二选一即可)
使用html方式生成 ,然后作为组件导入到页面中即可(个人推荐此方式,速度上比canvas快一些)
<template>
<view>
<view v-if="imgHeight" class="copyRightBox" :style="{height:imgHeight?imgHeight+'px':'850upx'}">
<view class="font" ref='sy' v-for="(item,index) in 30" :key='index'>
{{sytext}}
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {};
},
props: {
sytext: String, // 水印文字
imgHeight:String, // 水印高度
},
mounted() {}
}
</script>
<style>
.copyRightBox {
overflow: hidden;
width: 100%;
height: 850upx;
pointer-events: none;
position: fixed;
top: 0px;
left:-50upx;
z-index: 99998;
}
.font {
float: left;
transform: rotate(-30deg);
margin-top: 220upx;
margin-left: 100upx;
font-size: 75upx;
color: rgba(0,0,0,0.2);
}
</style>
使用canvas生成
const canvas = document.createElement("canvas");
let _ix = img.width; // 图片宽高
let _iy = img.height;
canvas.width = _ix;
canvas.height = _iy;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "rgba(51,51,51,0.4)";
ctx.font = '50px "微软雅黑"'; //设置字体
ctx.drawImage(img, 0, 0);
for (let j = 50; j <= img.height * 2;) {
ctx.fillText(remartText, img.width/2, j);
j += 260 // 水印的稀疏可随意调节
}
4. 生成分享海报
createPoster(domId, obj) {
let dom = document.querySelector(domId);
let res = {
height: dom.scrollHeight,
width: dom.scrollWidth
}
console.log('终版', res)
let canvas = await html2canvas(dom, {
useCORS: true, // 支持图片跨域
// scale: 4, //按比例增加分辨率 (2=双倍).
// dpi: window.devicePixelRatio * 4,//设备像素比
// 页面有滚动条时 设置,若不加导出图片为当前可视区域
windowHeight: dom.scrollHeight,
windowWidth: dom.scrollWidth,
backgroundColor: null,
width: dom.scrollWidth,
height: dom.scrollHeight
})
let imgRes = canvas.toDataURL(); // 默认 png格式
// let imgRes = canvas.toDataURL("image/jpeg", 0.8) 图片质量和后缀可以调节 质量范围: 0-1
console.log('图片的base64地址', imgRes)
}
拿到海报的base64地址以后,我们就可以进行后续的业务操作了。
常见问题处理
1. 背景图片为透明时,生成海报变为黑色
解决办法:canvas填充白色
// 解决透明背景变为黑色问题
context.fillStyle = "#fff";
context.fillRect(0, 0, canvas.width, canvas.height);
context.drawImage(image, 0, 0, image.width, image.height);
2. 海报模糊
解决办法: 如果使用的是uni-app中的image标签 需要替换为 img标签,image标签在uni-app中其实是背景图片
3. 海报生成不全
解决办法: 有可能是图片等没有渲染完成,可利用图片的加载完成事件 @load ,等加载完成后再进行后续操作
<img @load="loadImgFinish" />
4. 图片显示跨域错误
解决办法:开启 html2canvas的跨域 ,如果还不行大概率是后端返回的图片跨域问题
let canvas = await html2canvas(dom, {
useCORS: true, // 支持图片跨域
})