Vue页面生成分享海报最详说明(含二维码+多种水印方式+常见的坑处理)

Vue
257
0
0
2024-02-25

功能需求:

  • 海报有1张背景图, 海报上的文案内容动态变化
  • 在背景图的某个位置上添加二维码图片
  • 水印功能

大致思路

  1. html页面部分, 包括背景图,接口得来的数据,以及二维码图片的位置
  2. 使用 qrcodejs2库生成二维码图片,展现到预定位置
  3. 添加水印(canvas | html 两种方式 后边会分别进行介绍)
  4. 使用 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, // 支持图片跨域
	})