携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,
点击查看活动详情
大家好,我是
前端小张同学
,接着上一次的demo所遇到的问题就是,项目需要根据一张大的流程图,生成一个小的缩略图,当时我........,这是什么需求,做不了,于是我经过自己的努力还是做出来了中间也遇到了很多问题,在这里跟大家分享一下,如果你觉得有用请点个
Star
。
项目希望根据大的流程图绘制小的缩略图,具体内容我们看下方大图。
思考,这应该怎么做......
刚拿到这个需求的时候我楞了一下,应该怎么做?我的第一想法 居然是.....
Alt + A
(
微信截图快捷键
)
,我手动截一张图,然后保存,再然后...... 很明显这不现实,但是我们思路没错,
截图
,对,你没听过就是截图,我完成了这个需求。
接下来
(心机之蛙一直摸你肚子)
我利用了一个库截取了Dom的节点内容。
介绍一下这个库
什么是 html2canvs?
来源 : github ---->
html2canvas
html2canvas
的作用就是允许让我们直接在用户浏览器上拍摄网页或其部分的“截图”。
它的屏幕截图是基于
DOM
的,因此可能不会 100% 精确到真实的表示,因为它不会生成实际的屏幕截图,而是基于
页面上可用的信息
构建屏幕截图。
html2canvas 可以用来做什么?
从上的面的介绍可以知道,
html2canvas
的作用就是根据
DOM
生成对应的图片,所以一个比较常见的应用场景就是我们可以使用它在
H5
端生成分享图,或者生成缩略图等。
如何使用 html2canvas呢?
下包
--->
引入
---->
使用
1:
下包
npm i html2canvas
yarn add html2canvas
2:引入
import html2canvas from 'html2canvas'
3:使用(use)
在Vue中我们可以通过 给DOM绑定 ref
来获取到当前DOM节点。如果你是原生JS,
请document.querySelector()
配置项请见 html2canvas官方文档:
html2canvas.hertzen.com/configurati…
const el = this.$refs.efContainer;
const width = el.offsetWidth
const height = el.offsetHeight
let canvas = html2canvas(el,{
useCORS:true,
scale: 2,
width,
height,
allowTaint:true,
windowHeight:height,
接下来,你可以通过 canvas.toDataURL('images/jpg')
获取到一张base64位的图片进行展示
const img = canvas.toDataURL('images/jpg')
如果你出现了白屏
,请考虑你的方法调用时机
,确保DOM真正绘制完后在进行截取操作,你可以在点击某个按钮去执行该方法。例如 像我这样
如果有滚动条的DOM截图出现白屏
请参考
www.51sjk.com/b24b265777/
解决 无法截取Svg
相信根据上方的操作你应该可以生成一个base64
的字符串了 放到 image src 属性身上可以进行展示了。
接下来 ,很明显看的出,我想截取这个 id
为 efContainer
DOM元素里的内容,很明显可以看的出该元素的子节点是有svg
标签的。
截取之后的
我们使用 html2canvas
截取一个DOM内容是无法截取到SVG的内容的,这也是一个缺陷吧。如何解决呢
?
也是来自于github issues 里的大佬
github.com/niklasvh/ht…);
采取的是将Svg
标签提取出来,绘制成进canvas
行截取 展示的,同时相当于是 障眼法 ,我用 canvas
去代替你的 SVG
这样就可以正常的截取了
怎么做呢?
你需要先 下载一个包
下包
---> 引入
----> 使用
npm install canvg@1.5.3
import canvg from 'canvg'
1:准备一个获取Svg DOM元素的数组;
2:获取SVG DOM元素;
3: 循环遍历Svg DOM 数组,并且解决SVG 透明度问题;
4:去除元素的一个空白字符;
5:动态创建一个 canvas
标签;
6: 设置 创建好的 canvas
标签的宽高;
7:canvg() 使用这个方法 将 SVG
转换成 canvas
;
8:设置 canvas
的坐标;
9:添加到你想截图的DOM元素中;
10:截取完成后 将将绘制好的 canvas
删除避免影响后续操作
async getContainerImg () {
const el = this.$refs.efContainer;
let svgNodesToRemove = [];
let svgElements = document.body.querySelectorAll('#efContainer svg');
svgElements.forEach(function(item) {
let children = item.childNodes
children.forEach(function(child) {
child.style.opacity = 1;
let svg = item.outerHTML.trim();
let canvas = document.createElement('canvas');
canvas.width = item.getBoundingClientRect().width;
canvas.height = item.getBoundingClientRect().height;
canvg(canvas, svg);
if (item.style.position) {
canvas.style.position += item.style.position;
canvas.style.left += item.style.left;
canvas.style.top += item.style.top;
item.parentNode.appendChild(canvas);
svgNodesToRemove.push(canvas)
const width = el.offsetWidth
const height = el.offsetHeight
let canvas = await html2canvas(el,{
useCORS:true,
scale: 2,
width,
height,
allowTaint:true,
windowHeight:height,
this.thumbnail = canvas.toDataURL('images/jpg')
document.querySelectorAll("#efContainer canvas").forEach(item => {
item.remove()
那缩略图的话,相信你通过CSS就可以搞定它了。大概内容就是这样咯。
这样就可以完美解决 无法截取到SVG的问题啦,非常谢谢大家的支持,如果你觉的本文对你有帮助请点个👍,谢谢,如果有更好的思路,请在文章下方留言,谢谢。