由前端生成二维码,海报,canvas生成图片的跨域

之前做了一个生成带二维码的图片,需要在生成的图片中附带用户头像、用户昵称、商品图片、商品标题、商品链接二维码,效果图大概长这个样子

开始坑了
首先 楼主当时生成图片使用的是html2canvas, 生成二维码使用的是xkeshi/vue-qrcode
安装(由于使用的是vue2.0,所以是依赖注入的方法)

npm i xkeshi/vue-qrcode --save
npm i html2canvas --save

引入

import html2canvas from 'html2canvas';
import QRcode from '@xkeshi/vue-qrcode'

在html中写入二维码的标签 <qrcode class="qr_code" :value="qrcodeUrl" v-if="qrcodeUrl" :options="{ size: 65 }"></qrcode>,class随意发挥;value是二维码的链接地址,可以为任意地址,如:https://blog.csdn,可带参;options规定了二维码的大小,单位px
: qrcode标签需要在components中注册, components: { qrcode : QRcode }

至此,二维码就生成好了,只要选对了插件几乎不存在什么问题,接下来开始踩canvas坑,需要生成图片的元素如下:

<div ref="QrcodePage" class="card" :class="activeIndex===0?'card1':activeIndex===1?'card2':''">
    <div class="user">
    	<img :src="headImg" alt=""> 			//用户头像
	    <div class="user_name">
		    <p class="overflow_1">{{ $store.state.userInfo.nickName }}</p>		//用户昵称
		    <p>邀请你学习</p>
	    </div>
    </div>
    <p class="title">{{ courseInfo.goodsName }}</p>						//商品标题
    <img class="course_img" :src="courseInfo.imageUrl" alt="">			//商品图片
    <p class="scan">长按识别二维码</p>
    <qrcode class="qr_code" :value="qrcodeUrl" v-if="qrcodeUrl" :options="{ size: 65 }"></qrcode> 		//二维码
</div>

使用html2canvas生成海报/图片的代码如下:

createImg() {
    var that = this;
       let shareContent = this.$refs.QrcodePage, //需要截图的包裹的(原生的)DOM 对象
           width = shareContent.clientWidth, //shareContent.offsetWidth; //获取dom 宽度
           height = shareContent.clientHeight, //shareContent.offsetHeight; //获取dom 高度
           canvas = document.createElement("canvas"), //创建一个canvas节点
           scale = 4; //定义任意放大倍数 支持小数
       canvas.width = width * scale; //定义canvas 宽度 * 缩放
       canvas.height = height * scale; //定义canvas高度 *缩放
       canvas.style.width = (shareContent.clientWidth * scale) / 100 + "rem";
       canvas.style.height = (shareContent.clientHeight * scale) / 100 + "rem";
       canvas.getContext("2d").scale(scale, scale); //获取context,设置scale
       let opts = {
           scale: scale, // 添加的scale 参数
           canvas: canvas, //自定义 canvas
           logging: false, //日志开关,便于查看html2canvas的内部执行流程
           width: width, //dom 原始宽度
           height: height,
           useCORS: true
       };
       html2canvas(shareContent, opts).then(function(canvas) {
           that.qrContentImage = canvas.toDataURL("image/jpeg", 1.0);
       }).catch(function (reason) {
           alert(reason)
       });
},

生成后的展示如下

<div class="card_img">
	<img :src="qrContentImage">
</div>

在这里需要绘制到海报上的图片有两张,一是用户头像,二是商品图片,无独有偶,这两张图在绘制到canvas上时都产生了跨域问题,现在想想,生成的那张二维码好像也是图片,这小东西怎么就没跨域呢-…-
咳咳,言归正传,当时测试了一下,与当前域名相同的图片不会跨域,本地上传的图片不会跨域,其他来源的图片都会跨域,包括二级域名下的图片
最后的解决办法是将图片的host替换为当前的host,再由nginx转发到正确的host下,代码如下

let newurl = 'http://' +  window.location.host
this.headImg = this.headImg.replace("http://thirdwx.qlogo", newurl)

不过这个方法至适用于来源已知且来源统一的图片,至此使用canvas绘制图片跨域的问题已解决
不过对于来源不统一的图片不适用,后来了解到可以在绘制前使用canvas将图片转为base64精灵图,base64在绘制时并不会产生跨域问题,不过本人并未深入研究,有需求的小伙伴可以继续踩坑

更多推荐

vue2.0 海报生成器、二维码生成器