简述html2canvas遇见的坑点及解决方案
前言
大家好,最近公司在做公众号的海报图生成功能,功能不难,但是其中也遇到了一些坑还有一些细节的问题,这里给大家复盘一下,相互借鉴及学习
制作海报选用工具
这里我看了几款生成图片的工具:
这里我选用的是html2canvas,因为大部分人使用这个比较多,而且我也只听过这个🤣,另一个大家可以去自行摸索,毕竟我看github上也有9k的star
开始使用插件生成
引入插件
// npm 下载插件
npm install html2canvas
// 项目引入插件
import html2canvas from 'html2canvas';
html2canvas的option配置
属性名 | 默认值 | 描述 |
---|---|---|
allowTaint | false | 是否允许跨域图像。会污染画布,导致无法使用canvas.toDataURL 方法 |
backgroundColor | #ffffff | 画布背景色(如果未在DOM中指定),设置null为透明 |
canvas | null | 现有canvas元素用作绘图的基础 |
foreignObjectRendering | false | 如果浏览器支持,是否使用ForeignObject渲染 |
imageTimeout | 15000 | 加载图像的超时时间(以毫秒为单位),设置0为禁用超时 |
ignoreElements | (element) => false | 谓词功能,可从渲染中删除匹配的元素 |
logging | true | 启用日志以进行调试 |
onclone | null | 克隆文档以进行渲染时调用的回调函数可用于修改将要渲染的内容,而不会影响原始源文档 |
proxy | null | 代理将用于加载跨域图像的网址。如果保留为空,则不会加载跨域图像 |
removeContainer | true | 是否清除html2canvas 临时创建的克隆DOM元素 |
scale | window.devicePixelRatio | 用于渲染的比例。默认为浏览器设备像素比率 |
useCORS | false | 是否尝试使用CORS从服务器加载图像 |
width | Element width | canvas的宽度 |
height | Element height | canvas的高度 |
x | Element x-offset | 裁剪画布X坐标 |
y | Element y-offset | 裁剪画布X坐标 |
scrollX | Element scrollX | 渲染元素时要使用的x滚动位置(例如,如果Element使用position: fixed) |
scrollX | Element scrollY | 呈现元素时要使用的y-scroll位置(例如,如果Element使用position: fixed) |
windowWidth | Window.innerWidth | 渲染时使用的窗口宽度Element,这可能会影响媒体查询之类的内容 |
windowHeight | Window.innerHeight | 渲染时要使用的窗口高度Element,这可能会影响媒体查询之类的内容 |
调用html2canvas时传入两个参数,第一个参数是dom节点,第二个参数是options配置项(配置项可根据上方表格进行对应配置)
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
});
调用方法生成海报
1.获取节点:let img = document.querySelector("#myImg");
2.配置需要参数:
let options = {
useCORS: true,// 开启跨域
backgroundColor: "#caddff",// 背景色
ignoreElements: (ele) => {},// dom节点
scale: 4,// 渲染出来的比例
};
3.调用方法
html2canvas(img, options).then((canvas) => {
let url = canvas.toDataURL("image/png"); // canvas转png(base64)
this.url = url;
this.isShow = false;
});
到这里html2canvas的相关使用及配置就介绍完了,接下来就是遇见的问题
使用时遇见的坑点及解决方案
图片跨域问题
第一次用我就遇见了这个问题,第一个就是百度的方法,配置useCORS: true,// 开启跨域
,然后图片标签上加crossorigin="anonymous"
,但是结果没用,图片依旧跨域,这时候咱们前端就要硬气一点,直接让后端处理,让后端把图片地址改成base64的形式传给你,或者服务器配置跨域
生成海报时图片模糊问题
生成海报如果模糊,建议把配置项的scale配置高一点,生成的canvas图片把盒子固定大小,显示的图片就更清晰
dom之间有一道横杠
本人是在公众号上做生成海报功能,dom元素顶部是两张图片,图片顶部有一道白线,而且两张图片之间还有一道杠(不好形容),后面发现是因为生成这个海报我在公众号上用的是image标签,改成img标签就没用影响了,具体原因应该是uniapp内部处理image标签时的一些样式问题吧,这是我的猜测
注意:app上不支持html2canvas生成海报(我也是调试的时候发现的)
全部代码
这里代码仅供大家参考
<template>
<view class="poster-content">
<view class="poster-img" id="myImg" v-if="isShow">
<img class="flow" src="../../static/QC-code.png" />
<view class="card-item">
<view class="title-card">爽卡优势</view>
<view class="tip-content">
<view class="left">
<p>零月租,随充随用,不用不扣费</p>
<p>全程4G、不限APP、不限速</p>
<p>支持多场景使用</p>
<p>官方正品、品质保证</p>
</view>
<view class="right">
<view class="right-item">
<view class="qr-code">
<img
id="codeImg"
:src="imgUrl"
style="width: 100%; height: 100%"
class="flow"
crossorigin="anonymous"
/>
</view>
<view style="color: #0032d0">扫码免费领取</view>
</view>
</view>
</view>
</view>
</view>
<view v-else class="canvas-img">
<img style="width: 100vw" :src="url" alt="" />
</view>
<view v-if="isShow" style="padding-bottom: 10px">
<view @click="getImage" class="createPoster">点击生成海报</view>
</view>
<view style="padding-bottom: 50px">
<view
@click="close"
class="createPoster"
style="background-color: #fff; color: #4f80e6"
>关闭</view
>
</view>
</view>
</template>
<script>
import html2canvas from "html2canvas";
export default {
props: {
imgUrl: {
type: String,
default: "",
},
hasQrCode: {
type: Boolean,
default: false,
},
},
data() {
return {
url: "",
isShow: true,
};
},
onShow() {},
methods: {
close() {
this.$emit("closePop");
},
getImage() {
// this.saveImg()
this.saveImg();
},
saveImg() {
let img = document.querySelector("#myImg");
let options = {
useCORS: true,
backgroundColor: "#caddff",
ignoreElements: (ele) => {},
scale: 4,
};
html2canvas(img, options).then((canvas) => {
let url = canvas.toDataURL("image/png"); // canvas转png(base64)
this.url = url;
this.isShow = false;
});
},
},
};
</script>
<style lang="scss" scoped>
.poster-content {
width: 100vw;
background-color: #caddff;
height: calc(100vh - 50px);
overflow: scroll;
margin-top: -50px;
}
.poster-img {
width: 80vw;
margin: 0 auto;
background-color: #caddff;
// display: flex;
// flex-direction: column;
padding: 40upx 20upx;
text-align: center;
.title {
width: 203px;
height: 96px;
}
.flow {
width: 100%;
height: 300px;
}
.card-item {
background-color: #fff;
font-size: 14px;
margin-top: -12upx;
padding: 20upx 0 40upx;
text-align-last: left;
border-radius: 20upx;
.title-card {
color: #0032d0;
font-size: 36upx;
font-weight: 700;
padding-left: 10upx;
}
.tip-content {
display: flex;
justify-content: space-between;
font-size: 26upx;
.left {
flex: 1;
margin-top: 10upx;
& > p {
line-height: 1.5em;
margin-top: 20upx;
padding-left: 40upx;
position: relative;
&::after {
content: "";
position: absolute;
top: calc(50% - 10upx);
left: 8upx;
width: 20upx;
height: 20upx;
border-radius: 20upx;
background-color: #0256ff;
}
}
}
.right {
width: 90px;
font-size: 20upx;
display: flex;
align-items: center;
padding-right: 16upx;
.right-item {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
// height: 143px;
.qr-code {
width: 160upx;
height: 160upx;
background-color: #fff;
border-radius: 10upx;
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
}
.canvas-img {
width: 100vw;
height: calc(100vh - 50px);
overflow: scroll;
}
}
.createPoster {
line-height: 2.8em;
width: 90%;
background-color: #5479f7;
margin: auto;
border-radius: 40upx;
color: #fff;
text-align: center;
}
</style>
结尾
这些就是本人在做海报功能所遇见的一些问题及解决方案,希望掘友们相互学习共同进步,如果有什么描述错误的地方希望给我指正,欢迎大家跟我一起交流
来源:juejin.cn/post/7168667322956120101