最近公司项目有个需求是:弹窗的时候要把一些信息合成为图片然后再进行分享等操作,其中信息包括微信头像,昵称等。项目是用vue来搭建的,要合成的区域如下:


弹窗的主要html如下:

<div class="success-wrap" :class="{opacity:successShow}">
		<div class="shadow"></div>
		<div class="success-modal">
			<div class="main-box" :class="{active:successShow}" id="succAni">
				<i class="close-btn" @click="closeModal"></i>
				<div id="success-box">
				<div class="success-panel" id="success">
					<div class="photo"><img src="../assets/imgs/default_photo.png" /></div>
					<p class="user">{{userInfo.wechat_wxname}}</p>
					<p class="thanks-text">
						您于{{dateArr[0]}}年{{dateArr[1]}}月{{dateArr[2]}}日捐赠 <span>{{donateCount}}</span> 公益金,感谢您热心参与“<span>公益项目</span>”,这些公益金,将带着您的爱让美好的事情发生。
					</p>
					<div class="clear">
						<div class="qcode-left">
							<p class="qcode">
								<qriously :value="'http://share.xhebao.cn/qcode.php?u_id='+ u_id" :size="88"/>
								<i class="kd-icon"></i>
							</p>
							<p class="qcode-text">扫码为公益助力</p>
						</div>
					</div>
					<p class="droit">本活动最终解释权归所有</p>
				</div>
				</div>
				<div class="btn-box clear">
					<span @click="iosSaveImage">保存图片</span>
					<span @click="wxShare">分享爱心</span>
				</div>
			</div>
		</div>
	</div>

于是自己就用了html2canvas来做,但是却遇到了很多的坑,总结下遇到的几个坑:

1、合成的区域必须是存在于Dom树中的,所以用v-if显示弹窗的话就要先显示再来进行合成。(项目中自己是用opacity和z-index来控制的)

2、涉及到跨域问题的图片无法合成,除非能在图片服务器那边设置允许跨域(所以自己项目中的微信头像问题,就用了本地的一个默认的头像来代替了)

3、由于合成是从浏览器窗口位置开始的,所以如果合成的区域不是在浏览器窗口的开始位置下,就需要先把合成区域放到浏览器窗口开始位置下,合成后再把合成的图片放到自己想要的位置(这个不知道还有没有什么好的办法,比如可以定义绘制起点之类的)

4、本来自己是想给弹窗显示的时候添加一个缩放(从0.2缩放到原来尺寸)的效果,于是就直接在合成区域的外框上添加了缩放的class,但是这样却会影响合成的效果(也被缩小了),因为在合成前,影响到原效果图的动画都会对合成图片造成影响。于是自己就在合成的时候再来添加动画(具体就是:合成成功时给外框添加0.2的缩放,然后显示的时候再让它过度到原来的尺寸)。

5、如果合成区域要多次合成的话,可以先把要合成的区域display:none掉(而不是remove掉),然后把合成图片添加进去,当要再次合成时再把图片remove掉,和成区域显示,然后进行再次合成

主要合成的代码如下:

//合成图片
		getCanvasImg(obj){
		    var doc = window.document;
		    var width = obj.content.offsetWidth; 
		    var height = obj.content.offsetHeight; 
		    var canvas = document.createElement("canvas"); 
		    var context = canvas.getContext("2d");
		    var scale = 2;
		    let that = this;
			
		    canvas.width = width * scale;
		    canvas.height = height * scale;
		    		    
		    canvas.getContext("2d").scale(scale, scale);
			
			var opts = {
		        scale: scale, 
		        canvas: canvas, 
		        logging: true, 
		        width: width, 
		        height: height 
		    };
		
		    html2canvas(obj.content, opts).then(function (canvas) {	
	            var dataUrl = canvas.toDataURL();
	            let ani = document.getElementById('succAni');
	            var newImg = doc.createElement("img");
	            newImg.src =  dataUrl; 
	            newImg.id =  "qcImg";
	            newImg.style.width = canvas.width/2 + 'px';
	            newImg.style.height = canvas.height/2 + 'px';
	            newImg.style.borderRadius = '4px';
	            newImg.style.webkitBorderRadius = '4px';	            
	            
	            ani.style.opacity = '0';
	            ani.style.transform = 'scale(.2)';
	            ani.style.transition = 'opacity .3s,transform .3s';
	            ani.style.webkitTransform = 'scale(.2)';
	            ani.style.webkitTransition = 'opacity .3s,transform .3s';
				   document.getElementById('success').style.display = "none"
	            obj.box.appendChild(newImg);
	            obj.cb&&obj.cb();
	            that.hasCanvas = true;	           
		    });			    
		},

弹窗显示主要代码:(先合成图片再来显示弹窗,因为还要把合成的图片定位到自己想要的位置,不然会有闪现的效果)

//捐赠成功进行图片合成
		    				let obj = {};			
						obj.box = document.getElementById('success-box');
						obj.content = document.getElementById('success');
						obj.cb = function(){
							$('.success-wrap .main-box').css({"marginTop":"-4.95rem","marginLeft":"-3.16rem","top":"50%","left":"50%"});							
							setTimeout(function(){
								that.successShow = true;
								let ani = document.getElementById('succAni');
								ani.style.opacity = '1';
								ani.style.transform = 'scale(1)';
								ani.style.webkitTransform = 'scale(1)';
							},200)
						}
						that.getCanvasImg(obj);
Logo

前往低代码交流专区

更多推荐