html2canvas 版本: 1.0.0-rc.4,这里说明下,不同的版本可能会有不同的表现形式。比如一开始用的最新的版本,出现了生成的图片中的文字无缘无故向下偏移一行,没有找到解决办法,于是降低了版本。
应用场景:本次是在vue项目中,几个不同的页面,有将整个页面生成海报,也有将弹框内容生成海报,所以将canvas方法单独封装了,需要的页面引入调用即可。当然,不是vue的项目,也可以使用我这方法,只是引入文件方式不一样。
新建canvas.js,将截图方法放入其中
import html2canvas from "html2canvas"
function DPR() {
// 获取设备dpi
if (window.devicePixelRatio && window.devicePixelRatio > 1) {
return window.devicePixelRatio;
}
return 1;
};
export function canvas(params, callback) {
// params.dom 需要转成图片的dom css选择器
let content_html = document.querySelector(params.dom)
let width = content_html.offsetWidth;
let height = content_html.offsetHeight
let canvas = document.createElement("canvas")
// 获取像素比
let scaleBy = DPR()
// 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
canvas.width = width * scaleBy;
canvas.height = height * scaleBy;
// 设定 canvas css宽高为 DOM 节点宽高
canvas.style.width = width + "px"
canvas.style.height = height + "px"
// 获取画笔
// var rect = document.querySelector(params.dom).getBoundingClientRect();
let context = canvas.getContext("2d")
// context.translate(-rect.left, -rect.top);
// 将所有绘制内容放大像素比倍
// context.scale(scaleBy, scaleBy)
// context.scale(1, 1)
var opts = {
allowTaint: false, //允许加载跨域的图片,默认false不可与useCORS同时存在
tainttest: true, //检测每张图片都已经加载完成
scale: scaleBy, // 添加的scale 参数,默认window.devicePixelRatio
canvas: canvas, //自定义 canvas
logging: false, //日志开关,发布的时候记得改成false
// width: width, //dom 原始宽度,试过感觉影响不大
// height: height, //dom 原始高度,试过感觉影响不大
useCORS: true,
ignoreElements: (element) => {
//不需要转化的元素
if (element.id == 'ig') return true
},
backgroundColor: null,
// scrollY: 0,//通过外部调用地方传入
// y: 0, //通过外部调用地方传入
// dpi: scaleBy * 3
};
// 合并外部自定义参数(不同情况调用可能需设置不同参数)
if(params.options) {
opts = Object.assign( opts, params.options )
}
console.log(opts)
html2canvas(content_html, opts).then(canvas => {
var image = new Image()
image.setAttribute("crossOrigin", "anonymous")
// 获取生成的base64图片的url
var imgUrl = canvas
.toDataURL("image/jpeg")
.replace("image/jpeg", "image/octet-stream")
image.onload = function () {
var canvas = document.createElement("canvas")
canvas.width = image.width
canvas.height = image.height
var context = canvas.getContext("2d")
context.drawImage(image, 0, 0, image.width, image.height)
var url = canvas.toDataURL("image/png")
// 回调,将生成的图片base64地址传出去,供调用的地方使用图片
callback(url)
// var a = document.createElement("a")
// var event = new MouseEvent("click")
// a.download = "图片"
// a.href = url
// a.dispatchEvent(event)
}
image.src = imgUrl
})
}
页面调用:
首先引入上面的canvas,我这里是打开页面自动生成,所以最好在mounted生命周期中调用,最好加上this.$nextTick;如果是手动点按钮生成,就看实际情况调用
//页面
<div class="save-content>这个div是截图区域,里面内容按实际要求自己布局</div>
import {
canvas } from "../../utils/canvas"
mounted(){
this.$nextTick(()=>{
setTimeout(()=>{
this.loading = false
this.getCanvas()
},1000)
//我这里延迟1s,是做了一个生成中的loading提示动画
})
},
methods: {
// 截图
getCanvas(){
var that = this
//dom对应页面上的css选择器选中的截图容器,option是另外的一些参数,回调是方法返回的图片base64,可以具体看上面的方法,一些配置参数也可以去html2canvas官网查看
canvas({
dom: '.save-content', options: {
scrollX: 0, scrollY: 0 } }, (res)=>{
this.$nextTick(()=>{
console.log(res)
//这里的res就是上面封装的canvas方法回调返回的图片base64,可以按照自己的需求做后续操作
})
})
},
}
一些坑:
截图容器外面的盒子最好不要有transform: translate 等属性,这些属性会造成生成的截图有时候正常,有时候又有很大的偏移,如果有弹框或其他内容需要居中,建议用flex布局;
在做整个页面截图的时候,若是顶部距离视窗有距离,生成的图片顶部有偏移,可在options里配置y参数,数量为.save-content容易距离顶部视窗的距离;
另外,在强调下版本,经常会因为版本问题出现一个问题而无法解决,所以有时候碰到问题解决不了了可以换个版本试试;
关于需要截图区域内有图片,并且图片跨域问题,必须图片服务器配置了允许跨域,不然前端怎么搞都没有用,,或者直接让后端将图片转成base64,在返回你base64也行,
最后,html2canvas就是个坑,看似很简单,入手后各种坑,大家使用中多采坑,多调试,一步步的成功