首页 > 其他分享 >浅谈两种前端截图方式:Canvas截图 vs SVG截图

浅谈两种前端截图方式:Canvas截图 vs SVG截图

时间:2023-04-22 13:05:51浏览次数:34  
标签:截图 const 浅谈 img DOM SVG Canvas

背景

如今很多网站都引入截图功能,可用于问题反馈内容分享等实用需求,而前端截图也不知不觉成为了首选。今天为大家推荐两种前端截图方式,虽然有些局限,但是也能应付大部分项目需求。

  • Canvas截图html2canvas
  • SVG截图rasterizehtml

原理

首先来谈下两种前端截图方式的原理,虽然实现方式不太一致,但是核心思想是相同的。

html2canvas为代表的Canvas截图,通过遍历DOM克隆一份副本,将此副本在Canvas上重新绘制,并根据DOM的样式应用在对应的绘制元素上,再通过Canvas生成图片。转换过程可理解成:DOMCanvasImage

rasterizehtml为代表的SVG截图,通过遍历DOM克隆一份副本,利用SVG的foreignObject把DOM作为外部资源嵌套在SVG中,将此SVG在Canvas上重新绘制,并根据DOM的样式应用在对应的绘制元素上,再通过Canvas生成图片。转换过程可理解成:DOMSVG的ForeignObjectCanvasImage

两种前端截图方式最后都是通过把DOM绘制到Canvas,再通过Canvas输出图片

限制

虽然两种前端截图方式都有这两个封装得比较完善的第三方库html2canvasrasterizehtml,但是由于在转换过程中存在一些自身的局限性,所以也导致截图可能出现一些不完美的问题。

Canvas截图的限制性

  • 无法渲染跨域资源(支持同域)
  • 无法渲染iFrameFlash内容(支持SVG)

SVG截图的限制性

  • 无法渲染跨域资源(支持同域)
  • 无法渲染如lazyload等通过JS加载的资源
  • 无法渲染内联background-image或JS操作background-image

方案

不多废话,直接上两种前端截图方式的代码,小伙伴们可根据项目需求自行优化代码和增加功能哈。

准备

<div id="screenshot">Hello World</div>
<button id="save-btn">保存</button>
// 渲染图片
function Render(src, width, height, cb) {
    const img = new Image();
    img.src = src;
    img.width = width;
    img.height = height;
    img.crossOrigin = ""; // 图像跨域时配置
    cb && cb(img);
}

// 下载图片
function Download(url, name) {
    const target = document.createElement("a");
    target.href = url;
    target.download = name;
    const event = document.createEvent("MouseEvents");
    event.initEvent("click", true, true);
    target.dispatchEvent(event);
}

Canvas截图

import Html2canvas from "html2canvas";

const btn = document.getElementById("save-btn");
btn.addEventListener("click", () => {
    const screenshot = document.getElementById("screenshot");
    // allowTaint: true, // 不能与useCORS共用
    const opts = {
        logging: false,
        scale: 2,
        useCORS: true
    };
    Html2canvas(screenshot, opts).then(res => {
        const { height, width } = res;
        const base64 = res.toDataURL("image/png", 1);
        Render(base64, width, height, img => {
            document.body.appendChild(img);
            Download(base64, "screenshot.png");
        });
    }, err => alert("截图失败,请重新尝试"));
});

SVG截图

import Rasterizehtml from "rasterizehtml";

const btn = document.getElementById("save-btn");
btn.addEventListener("click", () => {
    // drawURL()加载的URL必须是同域名URL或支持跨域的URL
    // 下面的URL是随便写的,记得换成同域名URL或支持跨域的URL
    const url = "https://www.baidu.com";
    const canvas = document.createElement("canvas");
    const opts = {
        executeJs: true,
        height: screen.height,
        width: screen.width
    };
    Rasterizehtml.drawURL(url, canvas, opts).then(res => {
        const base64 = "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(res.svg)));
        Render(base64, opts.width, opts.height, img => {
            document.body.appendChild(img);
            Download(base64, "screenshot.png");
        });
    }, err => alert("截图失败,请重新尝试"));
});

另外还有几点需要注意一下:

  • 使用Canvas截图兼容低版本浏览器时,不能使用CSS3属性带有前缀的属性
  • 使用SVG截图可获取同域<iframe>内容进行渲染
  • 截图不能包含跨域获取的内容,否则不会渲染跨域内容

总结

浅谈两种前端截图方式就到此为止啦,相信小伙伴们对前端截图也有一个比较清晰的概念了,可结合自身项目尝试一下两种前端截图方式,探究下其相同点和不同点。如果对其截图原理感兴趣,可剖析下html2canvasrasterizehtml的源码,相信你会有意外的收获喔!



标签:截图,const,浅谈,img,DOM,SVG,Canvas
From: https://blog.51cto.com/u_15689678/6215238

相关文章

  • HTML5: 利用SVG动画动态绘制文字轮廓边框线条
    DEMO:点击这里看效果 简要教程这是一款很酷的html5svg线条动态绘制文字轮廓边框动画特效。SVG路径动画在网页设计中是一项热门的技术,它允许我们绘制各种简单、精美的图标和文字。关于使用SVG制作图标方面的知识,请参考阅读ESSENTIALICONS。制作流程先......
  • SVG 入门教程系列列表
     SVG入门教程系列列表:SVG教程(一)SVG教程(二)矩形SVG教程(三)圆形,椭圆,直线SVG教程(四)多边形,曲线,路径SVG教程(五)文本,Stroke属性,SVG滤镜,SVG模糊效果SVG教程(六)SVG阴影,SVG渐变–线性,SVG渐变-放射性SVG教程(七)SVG实例,SVG参考手册 更多参考:SVG动画入门SVG动画入门(二)SV......
  • 浅谈日出日落的计算方法以及替代工具 - 日出日落 API
    引言如果你想知道精确的日落日出时间,又或者你想设计一个日出日落时间查询的应用,又或者你只是好奇点进来了,还是可以过来围观一下涨涨知识,今天想跟大家聊一聊的是日出日落的计算方法以及替代工具-日出日落API。日出日落API是一种可以获取指定城市或地点每日日出时间和日落时......
  • 【前端可视化】SVG 学习知识点
    基本概念和语法SVG的定义和历史SVG是可缩放矢量图形(ScalableVectorGraphics)的缩写,它是一种用于描述二维矢量图形的XML标记语言。与传统的栅格图像不同,SVG图像可以无限缩放而不会失真,同时也支持交互和动画等特性。SVG最早于1999年由W3C发布,用于在Web上展示矢量图......
  • 浅谈dataclass和namedtuple
    之前有简单讲了下命名元组,现在联系数据类再做比较下目前发现,因为数据类和普通的类没什么差异,只是提供了简写__init__的语法糖,而且增加了类型注解,可以随意修改属性值而命名元组无法修改,除非返回一个新的实例[email protected]()5clas......
  • CDGA|浅谈“以治促用,以用促治”的数据治理战略
    数据治理夯实企业数字化转型基础。采取“以治促用,以用促治”的数据治理战略,可以充分释放了企业核心运行要素的活力。“以治促用”是指通过建立在数据治理链路及用户多维评估系统的基础上,对数据资产重新进行价值识别,推进高价值数据资产应用和中低价值资产的优化,从而提高数据资产的可......
  • 浅谈全局平衡二叉树
    首先,这个是GBT,不是GPT。其次,那个是ChatGPT,不是ChatGBT。原理我们先考虑一个经典的问题:单点修树上最大权独立集问题,也就是LuoguP4719【模板】"动态DP"&动态树分治。使用树剖维护矩阵可以做到\(O(n\log^2n)\)的复杂度,可以通过\(10^5\)的数据。那我们能不能把这个问题优化......
  • 浅谈离线数据倾斜
    作者:京东零售 荆明岚一、数据倾斜的基本概念1、什么是数据倾斜?用最通俗易懂的话来说,数据倾斜无非就是大量的相同key被partition分配到一个分区里,造成了'一个人累死,其他人闲死'的情况,这种情况是我们不能接受的,这也违背了并行计算的初衷,首先一个节点要承受着巨大的压力,而其他......
  • canvas和svg区别
    Canvas描述:通过Javascript来绘制2D图形。是逐像素进行渲染的。其位置发生改变,会重新进行绘制。SVG描述:一种使用XML描述的2D图形的语言SVG基于XML意味着,SVGDOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。在SVG中,每个被绘制的图形均被视为对象。如果SVG......
  • 浅谈我眼中的缺陷管理
    嗨,大家好,我是Luna,一名新晋的软件测试小菜鸟。众所周知手工测试是软件测试类型中最常用的一种测试方法,它通过手动执行测试用例来发现软件系统中的缺陷和问题。而今天我们要讲的主角就是缺陷管理,在手工测试过程中,缺陷管理是非常非常重要的一环,它能够帮助测试人员更好地记录和跟踪缺陷......