html2canvas实现将html转换为图片app保存并微信分享

  最近开发上线一个app用户生成海报保存图片到本地并分享图片到微信好友。因为在app环境下,所以选择了html2canvas来分享海报。

html2canvas介绍

  html2canvas是一个比较成熟的开源库,它能将dom转化为canvas,省去了使用原生canvas一点一点去绘制。

下载html2canvas(安装依赖)

  npm install html2canvas -S

在vue中使用html2canvas

<view class="answer_canvas" style="width: 100%;height: 100%;position: absolute;left: -1000%;" data-type="background-image">
	<view class="poster_main answer_draw_canvas" data-type="background-image">
		<view id="capture">
			<view class="answer_draw_canvas" style="margin: 20rpx;">
				<image class="poster_img answer_draw_canvas" src="https://img.mayituifu.com/2023/10/4c32249068b943f5857bd84bb44af2f4.png" data-type="image" data-url="https://img.mayituifu.com/2023/10/4c32249068b943f5857bd84bb44af2f4.png" data-delay="1" />
		    </view>
		<view class="inner answer_draw_canvas game_img"  data-type="background-image">
			<image v-for="imgItem in gitemGamePic" class="gameimg answer_draw_canvas" :src="thisBaseUrl+imgItem" data-type="image" :data-url="thisBaseUrl+imgItem" mode="" data-delay="1"></image>
		</view>
		<view class="game-list-box1 answer_draw_canvas" data-type="background-image">
			<view class="game-list-item answer_draw_canvas" v-for="(gitem,gindex) in hbwydata" :key="gindex" data-type="background-image">
				<view class="game-item-info answer_draw_canvas" data-type="background-image">
					<image style="width: 80rpx;height: 80rpx;" class="answer_draw_canvas game-item-image" :src="gitem.imgs" data-type="radius-image" :data-url="gitem.imgs" data-delay="1"></image>

					<view class="game-info-box answer_draw_canvas" data-type="background-image">
					<view class="game-info-title answer_draw_canvas" data-type="background-image" @click="savePoster(gitem.gamePic)">
					<span class="answer_draw_canvas" style="font-weight: 700;" data-type="text" :data-text="gitem.prodName">{{gitem.prodName}}</span>
			</view>
			<view class="gameLabel3" data-type="background-image answer_draw_canvas">
			<view class="label answer_draw_canvas" data-type="text" :data-text="gitem.versionClass" style="background:#FDF9F1">{{gitem.versionClass}}</view>
			<view class="label answer_draw_canvas" data-type="text" :data-text="versionType[gitem.versionType]">{{versionType[gitem.versionType]}}</view>
				<view class="label answer_draw_canvas" data-type="text" :data-text="speed[gitem.speed]">{{speed[gitem.speed]}}</view>
		</view>
	</view>
		</view>
		<view class="game-item-content answer_draw_canvas" @click="gotopage('/basePages/pages/gameDetails/index?id='+gitem.prodId)" data-type="text" :data-text="gitem.brief">{{gitem.brief}}</view>
			<view class="game-item-income answer_draw_canvas">
				<view class="game-income-item answer_draw_canvas">
					<view class="game-income-item-val answer_draw_canvas" data-type="text" :data-text="gitem.goldType ? gitem.goldType : ''">{{ gitem.goldType ? gitem.goldType : '' }}</view>
									<view class="game-income-item-key answer_draw_canvas" data-type="text" data-text="毕业天数">毕业天数</view>
								</view>
								<view class="answer_draw_canvas" data-type="text" style="width: 1rpx;height: 28rpx;background: #e5e5e5;"></view>
								<view class="game-income-item answer_draw_canvas" data-type="background-image">
									<view class="game-income-item-val answer_draw_canvas" data-type="text" :data-text="gitem.signCommission ? gitem.signCommission + '%' : 0 + '%'">{{gitem.signCommission ? gitem.signCommission : 0}}%
									</view>
									<view class="game-income-item-key answer_draw_canvas" data-type="text" data-text="佣金比例">佣金比例</view>
								</view>
								<view class="answer_draw_canvas" data-type="text" style="width: 1rpx;height: 28rpx;background: #e5e5e5;"></view>
								<view class="game-income-item answer_draw_canvas" data-type="background-image">
									<view class="game-income-item-val answer_draw_canvas" data-type="text" :data-text="gitem.fullamount ? gitem.fullamount + `元` : 0">{{gitem.fullamount ? gitem.fullamount + `元` : 0}}</view>
									<view class="game-income-item-key answer_draw_canvas" data-type="text" data-text="满赞金额">满赞金额</view>
								</view>
							</view>
						</view>
					</view>
					<view style="padding: 0 30rpx;display: flex;justify-content: space-between;align-items: center;padding-bottom: 40rpx;" class="answer_draw_canvas" data-type="background-image">
						<view class="answer_draw_canvas" data-type="background-image">
							<view class="answer_draw_canvas small-title" data-type="text" data-text="长按识别-探索游戏" style="margin-bottom: 16rpx;">长按识别-探索游戏</view>
							<view class="answer_draw_canvas little-title" style="margin-bottom: 6rpx;" data-type="text" data-text="180神影火龙-单件套装一">180神影火龙-单件套装一</view>
							<view class="answer_draw_canvas little-title" data-type="text" data-text="专为散人设计,公平公正.等你来战!">专为散人设计,公平公正.等你来战!</view>
						</view>
						<view>
					<image class="answer_draw_canvas" :src="codeImg" style="width: 120rpx;height: 120rpx;" data-type="image" :data-url="codeImg"></image>
			</view>
		</view>
		</view>
	</view>
</view>

<view v-if="createCanvas" :prop="canvasImageMsg" :change:prop="canvasImage.updateEcharts"
		></view>

常用配置项

参数类型默认值描述
allowTaintbooleanfalse是否允许跨域图像污染画布
useCORSbooleanfalse是否跨域加载图片
backgroundColorstring#fff背景色
widthnumber元素宽度单元格
heightnumber元素高度单元格
scalenumberwindow.devicePixelRatio缩放比例
scrollXnumber元素x轴滚动位置生成后x轴滚动位置
scrollYnumber元素y轴滚动位置生成后y轴滚动位置

html2canvas绘制跨域图片

然limg标签需要添加crossorigin="anonymous"

生成在线地址

在内存中生成我们所需要的canvas对象,然后利用canvas的api toDataUrl和toBlob转换成图片数据,然后可保存下载。

js代码

<script lang="renderjs" module="canvasImage">
	import html2canvas from 'html2canvas'
	export default {
		data() {
			return {
				baseUrl: ''
			}
		},
	    methods: {
	      generateImage(callback) {
	        setTimeout(() => {
	          const dom = document.getElementById('capture'); // 需要生成图片内容的 dom 节点
	          html2canvas(dom, {
	            width: dom.clientWidth, //dom 原始宽度
	            height: 560,
	            scrollY: 0, // html2canvas默认绘制视图内的页面,需要把scrollY,scrollX设置为0
	            scrollX: 0,
	            useCORS: true, //支持跨域
				allowTaint: true, ///允许跨域图片
	            // scale: 1, // 设置生成图片的像素比例,默认是1,如果生成的图片模糊的话可以开启该配置项
	          }).then((canvas) => {
	            const base64 = canvas.toDataURL('image/png');
				this.baseUrl = base64
	            callback&&callback(base64);
	          }).catch(err=>{})
	        }, 300);
	      },
	      updateEcharts(newValue, oldValue, ownerInstance, instance) {
	        // 监听 service 层数据变更
			console.log(newValue,'newValue')
			// console.log(this.baseUrl,'this.baseUrl')

	        if(newValue){
	          this.generateImage((base64)=>{
	          	console.log(base64,'base64')
	            ownerInstance.callMethod('receiveRenderData', base64)
	          })
	        }
	      }
	    }
	  }
</script>

// #ifdef APP-PLUS
this.canvasImageMsg = 'generate'

// 因为uniapp中不能获取dom元素,所以引入renderjs
// 生成图片后的回调函数
receiveRenderData(base64) {
	this.poperShow = true
	uni.hideLoading({})
	this.posterLink = base64
	this.canvasImageMsg = null
},

遇到的问题

1、图片生成的时间长

第一个环节-html2canvas,配置 ignoreElements 函数或者在DOM上增加data-html2canvas-ignore属性,去除冗余的DOM,其次精简需要渲染的DOM范围,

第二个环节-canvas to Blob,提前生成blob,上传到后台,获取在线url,增加缓存在线地址。

2、报错errcode 1009

生成的图片地址为本地地址,所以在上线以后保存下载会报错,下载不下来,解决方案是把图片提前上传到服务器,在线图片下载则不会出现此问题。

 
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值