Html2canvas: 捕获SVG

创建于 2012-04-26  ·  64评论  ·  资料来源: niklasvh/html2canvas

您好,

html2canvas是否支持捕获SVG,如果是,该怎么做? 你能举个例子吗?

tests \ images中的示例未捕获SVG。

请帮忙。 非常感谢。

Question

最有用的评论

嗨,大家好,
我通过稍微更改源代码来解决此问题(使用Firefox丢失svg)。
首先,SVG元素必须具有height和width属性,无论是否带有像素。
那么您应该从以下位置更改源代码:
self.image.src =“ data:image / svg + xml ,” +(new XMLSerializer())。serializeToString(node);
至:
self.image.src =“ data:image / svg + xml ,” + encodeURIComponent((new XMLSerializer())。serializeToString(node));

然后享受它。

所有64条评论

不,不是的。 这不是库中的错误,而是大多数浏览器中的错误(最新稳定的Firefox版本12已修复此问题,并且是唯一可以正常使用的工具)。 问题是任何SVG图像都会弄脏画布,使其无法读取。 默认情况下,html2canvas会忽略污染图像的内容,因为我们要保持画布的可读性(例如,如果您要使用toDataUrl )。

但是,如果您不关心SVG图像是否会弄脏画布,则可以将选项allowTainttrue并且SVG应该为允许内嵌SVG的浏览器正确呈现。

我还要指出的是,如果SVG渲染可以在浏览器中正常工作,那么该库将几乎已过时,因为SVG可以用于渲染HTML。 我已经提交了一些代码,这些代码可以显着加速在SVG渲染起作用的浏览器(即FF12)上的画布渲染,并允许支持浏览器支持的所有CSS属性。 有关信息,参见

您好,
非常感谢您的快速回复。
我尝试作为您的建议:如下所示将allowTaint设置为true(修改test.js):

setTimeout(function(){

        $(h2cSelector).html2canvas($.extend({
            flashcanvas: "../external/flashcanvas.min.js",
            logging: true,
            profile: true,
            useCORS: true,
            allowTaint: true
        }, h2cOptions));
    }, 100);

在示例images.html中成功渲染了SVG。

但是,如果SVG更复杂,它将无法在跨浏览器中正确呈现。 例如:我想在Chrome中捕获图表(http://www.highcharts.com/demo/):当图表以内嵌SVG呈现时,它只捕获图表的x轴和y轴使用来自外部svg文件的源代码渲染为img,它不会捕获任何内容。
与Chrome相反,在Firefox中,当图表呈现为嵌入式SVG时,它不会捕获任何内容,但是当图表是来自外部svg文件的图像时,则可以成功捕获图表。 最糟糕的是在IE9中,什么也没有捕获。

您有解决此问题的想法吗?

用作图像应适用于FF / Chrome。 您可以尝试的是使用drawImage进行的简单画布渲染是否可以与SVG一起使用。

为此+1。 我有一个与babyhero相同的用例,我需要抓取highcharts SVG图的屏幕截图作为报告工具。 也许可以单独抓取所有高图表SVG,但是它是在视图中呈现的,而我们希望具有“保存到屏幕快照”功能。

@ babyhero184通过使用canvg(http://code.google.com/p/canvg/)即时将highcharts SVG转换为PNG,隐藏了SVG元素并显示了PNG,我html2canvas中的这一限制。 然后,我使用html2canvas快速拍摄了屏幕截图,然后隐藏了PNG,并再次显示了highcharts SVG。 这是一个回旋过程(SVG-> canvas-> PNG-> canvas-> PNG),但是可以满足我的需求。

@joeyrobert我也面临着highcharts和html2canvas的相同问题。 如果您可以共享代码要点,将为您提供很大的帮助。
提前致谢。

@joeyrobert @ Jagdeep1另一个选择是使用Fabric.js在画布上渲染SVG,然后检索其图像。

+1

+1

+1

这个问题有什么解决办法吗?

@majuansari _SVG_到_Canvas_和_Canvas_到_image_在firefox中有效,但在Chrome中有安全锁。

我使用jQuery捕获图表元素时,发现Highcharts SVG在执行时未正确解析。 如果有人通过图表的jQuery选择器,则该选择器可能不包含SVG。

@mbritton尝试http://code.google.com/p/canvg/(foreignObject不起作用)

是的,那是我的解决方案。

我通过在捕获时用canvg生成的canvas元素替换svg元素来解决此问题。
这是我的代码。

// targetElem is a jquery obj
function take (targetElem) {
    var nodesToRecover = [];
    var nodesToRemove = [];

    var svgElem = targetElem.find('svg');

    svgElem.each(function(index, node) {
        var parentNode = node.parentNode;
        var svg = parentNode.innerHTML;

        var canvas = document.createElement('canvas');

        canvg(canvas, svg);

        nodesToRecover.push({
            parent: parentNode,
            child: node
        });
        parentNode.removeChild(node);

        nodesToRemove.push({
            parent: parentNode,
            child: canvas
        });

        parentNode.appendChild(canvas);
    });

    html2canvas(targetElem, {
        onrendered: function(canvas) {
            var ctx = canvas.getContext('2d');
            ctx.webkitImageSmoothingEnabled = false;
            ctx.mozImageSmoothingEnabled = false;
            ctx.imageSmoothingEnabled = false;

            canvas.toBlob(function(blob) {
                nodesToRemove.forEach(function(pair) {
                    pair.parent.removeChild(pair.child);
                });

                nodesToRecover.forEach(function(pair) {
                    pair.parent.appendChild(pair.child);
                });
                saveAs(blob, 'screenshot_'+ moment().format('YYYYMMDD_HHmmss')+'.png');
            });
        }
    });
}

请注意:
我确定canvg可以正常工作,但是如果您只想将SVG转换为画布,则可以使用此处描述的简单技术,将svg加载到图像中,然后将图像内容作为dataURL获得。

var image = new Image();
var xml = '<svg xmlns=....></svg>';
image.src = 'data:image/svg+xml,' + escape(xml); 
document.getElementById('container').appendChild(image);
image.onload = function() {
    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.src = canvas.toDataURL();
}

@steren :尽管这在Chrome中很好用,但是Firefox有一种解决方法,它会在context.drawImage(image,0,0)行上生成NS_ERROR_NOT_AVAILABLE-显然是一个已知错误-或IE 11在画布上出现SecurityError。 toDataURL()尽管图像在同一域中? 除了Chrome之外,它无法在其他浏览器中运行...

@gifarangw您的代码可以与highcharts一起正常工作。 感谢您的精彩代码。 :+1:我删除的唯一东西是canvas.toBlob部分。

@steren感谢您的解决方案,它运行良好(在最新的chrome和firefox上进行了测试),并且不需要额外的库。 我做了一些更改,并结合了@gifarangw的代码,并获得了:

    function take(targetElem) {
        // First render all SVGs to canvases
        var elements = targetElem.find('svg').map(function() {
            var svg = $(this);
            var canvas = $('<canvas></canvas>');
            svg.replaceWith(canvas);

            // Get the raw SVG string and curate it
            var content = svg.wrap('<p></p>').parent().html();
            content = content.replace(/xlink:title="hide\/show"/g, "");
            content = encodeURIComponent(content);
            svg.unwrap();

            // Create an image from the svg
            var image = new Image();
            image.src = 'data:image/svg+xml,' + content;
            image.onload = function() {
                canvas[0].width = image.width;
                canvas[0].height = image.height;

                // Render the image to the canvas
                var context = canvas[0].getContext('2d');
                context.drawImage(image, 0, 0);
            };
            return {
                svg: svg,
                canvas: canvas
            };
        });
        targetElem.imagesLoaded(function() {
            // At this point the container has no SVG, it only has HTML and Canvases.
            html2canvas(targetElem[0], {
                onrendered: function(canvas) {
                    // Put the SVGs back in place
                    elements.each(function() {
                        this.canvas.replaceWith(this.svg);
                    });

                    // Do something with the canvas, for example put it at the bottom
                 $(canvas).appendTo('body');
                }
            })
        })
    }

(使用https://github.com/desandro/imagesloaded)

大家好,我只想说

@Remiremi @fbotti ,由于某种原因我不喜欢img.onLoad,所以图形消失了(没有被画布替换)

我正在和弹药一起工作。 任何想法?

@guypaskar您的svg需要进一步管理。 您可以在设置image.onload之前在代码中添加$(image).appendTo('body'); ,然后在Firefox中会看到一个无效图像的图标,您可以右键单击>查看图像并查看错误。

我快速尝试了一个amcharts svg,我不得不将属性xmlns="http://www.w3.org/2000/svg" width="1400" height="500"到svg标记中以使其工作。 (高度和宽度被指定为css属性,但是由于某种原因,它没有被拾取。)

我找到了一个简单的解决方法。

确保您的svg图像具有宽度和高度。

否则没有足够的论据,因为无法像图像一样测量svg。

有人可以回顾一下吗? 原始问题是否解决? 自2012年以来,似乎已解决了可能导致此处提到的大多数问题的某些浏览器问题。根据此处的一些评论,也不再需要使用canvg等其他库吗?

对于剩余的问题,它们是否将包含在#197和/或#267中? 可以关门吗?

至少某些浏览器仍然存在问题

0.5增加了对SVG的支持

任何预览将在@niklasvh 0.5时出现吗?

@IvoPereira您可以关注#421中0.5的状态

@niklasvh我有版本0.5,SVG仍然没有渲染。 有一个例子,怎么做? (它是嵌入式SVG)

@nikolang您同时包含html2canvas.jshtml2canvas.svg.js吗? 如果是这样,您可以提供jsFiddle或jsbin来演示您的特定问题吗?

我得到了这个工作。 问题是当我执行html2canvas时,SVG没有完全呈现。

但是渲染似乎仍然存在一些问题。 例如http://d3pie.org

它应该是这样的:

screen

这是html2canvas之后的样子:

canvas

哇,真是恐怖。 只是这样更容易跟踪,您是否可以使用相同的屏幕截图以及演示中的jsFiddle链接来打开一个单独的问题? 这与很久以前关闭的原始问题相距太远。 感谢您举报!

我很愿意这样做,但是我不知道如何将新的html2canvas包含到jsfiddle中。 我可以使用任何外部链接吗?

谢谢。 以及SVG版本?

同样: http :

你好

SVG呈现在我这一边,但显示为黑色,如以下某人所报道。 有没有一种方法可以计算svg元素的“填充”属性?

@brainra ,我正在使用类似的方法使填充白色:

// Create dummy canvas to get a white background
var destinationCanvas = document.createElement("canvas");
destinationCanvas.width = canvas.width;
destinationCanvas.height = canvas.height;

var destCtx = destinationCanvas.getContext('2d');

//create a rectangle with the desired color
destCtx.fillStyle = "#FFFFFF";
destCtx.fillRect(0,0,canvas.width,canvas.height);

//draw the original canvas onto the destination canvas
destCtx.drawImage(canvas, 0, 0);

var img = destinationCanvas.toDataURL("image/png");

无法在'CanvasRenderingContext2D'上执行'drawImage':提供的HTMLImageElement处于'broken'状态。”

当HTML中有svg元素时,出现此错误。
我也将allowTaint设置为true。 有人可以帮帮我吗?

我认为应该重新打开它-svg元素可以在除Firefox之外的所有浏览器中正确呈现。

NS_ERROR_NOT_AVAILABLE:这是一个Firefox错误: https ://bugzilla.mozilla.org/show_bug.cgi?id=700533(AFAICT)上有一个测试页,突出显示了该问题(与该错误链接) http://phrogz.net/ SVG / svg_to_png.xhtml

一个解决方法/修复将不胜感激。 也许有人可以戳某人@mozilla以解决此问题:)

我尝试使用有角度的方法,但最终使用了受污染的画布。 我想我需要原始的SVG吗?

<img svg-2-canvas-src="/assets/your.svg"/>

angular.module('APP')
    .directive('svg2CanvasSrc', function() {
        return {
            restrict: 'A',
            scope: false,
            link: function($scope, $element, $attrs) {

                var svgSrc = $attrs['svg2CanvasSrc'];

                var image = new Image();

                image.onload = function() {
                    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);
                    $element[0].src = canvas.toDataURL();
                };

                image.src = svgSrc;
            }
        };
    });

@remiremi我用了你的代码,但是结果是一样的,svg丢失了。
原始-https://s29.postimg.org/5lkprhx93/with_SVG.png
结果-https://s23.postimg.org/j1otj2por/without_SVG.png

@remiremi ... um使用此脚本时我

基本上,在调用html2canvas之前在SVG上设置显式宽度/高度可以为我解决大多数情况。
我所做的是遍历感兴趣的各种SVG元素,使用.getBoundingClientRect()获取其浏览器计算的宽度/高度,并在该元素上设置width height属性,我注意到当SVG设置了百分比和类似的宽度/高度时,它没有不渲染,但有像素,Booyah

虽然仍然存在渲染多行跨度和div的问题

嗨,大家好,
我通过稍微更改源代码来解决此问题(使用Firefox丢失svg)。
首先,SVG元素必须具有height和width属性,无论是否带有像素。
那么您应该从以下位置更改源代码:
self.image.src =“ data:image / svg + xml ,” +(new XMLSerializer())。serializeToString(node);
至:
self.image.src =“ data:image / svg + xml ,” + encodeURIComponent((new XMLSerializer())。serializeToString(node));

然后享受它。

有谁知道我将如何在DOM中的SVG元素上调用html2canvas

一个例子会很棒!

+1在firefox中捕获SVG元素截图仍然是一个问题。

{
  profile: true,
  allowTaint: false,
  onrendered: function() {
    //...done()
  }
}

嘿,我可以使用以下解决方案解决此问题(无需jQuery):

让targetElem =document.getElementById('body');
让nodesToRecover = [];
让nodesToRemove = [];

    let svgElem = targetElem.querySelector('svg')

    let parentNode = svgElem.parentNode;
        // let svg = parentNode.innerHTML;
        let svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" id=\"svg-annotations\" style=\"opacity: 1;\" _ngcontent-c7=\"\">\n\t\t\t<defs><marker id=\"arrow-start\" refY=\"4.5\" markerWidth=\"9.9\" markerHeight=\"9\" orient=\"auto\"><path fill=\"black\" d=\"M 9.9 0 L 9.9 9 L 0 4.5 Z\" /></marker><marker id=\"arrow-end\" refX=\"9.9\" refY=\"4.5\" markerWidth=\"9.9\" markerHeight=\"9\" orient=\"auto\"><path fill=\"black\" d=\"M 0 0 L 0 9 L 9.9 4.5 Z\" /></marker></defs><g class=\"annotation-group\" id=\"measurement-36122\" style=\"opacity: 1;\"><g class=\"annotations\"><g class=\"annotation callout elbow editable \" transform=\"translate(758.541 408.978)\"><g class=\"annotation-connector\"><path class=\"connector\" fill=\"none\" stroke=\"black\" d=\"M 0 0 L 137 137 L 162 137\" /></g><g class=\"annotation-note\" transform=\"translate(162 137)\"><g class=\"annotation-note-content\" transform=\"translate(0 3)\"><rect class=\"annotation-note-bg\" fill=\"white\" fill-opacity=\"0\" x=\"0\" width=\"104.79\" height=\"41.36\" /><text class=\"annotation-note-label\" fill=\"black\" y=\"41.36\" dx=\"0\"><tspan x=\"0\" dy=\"0.8em\" /></text><text class=\"annotation-note-title\" font-weight=\"bold\" fill=\"black\"><tspan x=\"0\" dy=\"0.8em\">Face</tspan><tspan x=\"0\" dy=\"1.2em\">:5453831.5mm²</tspan></text></g><path class=\"note-line\" stroke=\"black\" d=\"M 0 0 L 104.79 0\" /><circle class=\"handle \" cursor=\"move\" fill=\"grey\" fill-opacity=\"0.1\" stroke=\"grey\" stroke-dasharray=\"5\" cx=\"0\" cy=\"0\" r=\"10\" /></g></g></g></g><g class=\"annotation-group\" id=\"measurement-59622\" style=\"opacity: 1;\"><g class=\"annotations\"><g class=\"annotation callout elbow editable \" transform=\"translate(889.656 387.507)\"><g class=\"annotation-connector\"><path class=\"connector\" fill=\"none\" stroke=\"black\" d=\"M 0 0 L 137 137 L 162 137\" /></g><g class=\"annotation-note\" transform=\"translate(162 137)\"><g class=\"annotation-note-content\" transform=\"translate(0 3)\"><rect class=\"annotation-note-bg\" fill=\"white\" fill-opacity=\"0\" x=\"0\" width=\"104.79\" height=\"41.36\" /><text class=\"annotation-note-label\" fill=\"black\" y=\"41.36\" dx=\"0\"><tspan x=\"0\" dy=\"0.8em\" /></text><text class=\"annotation-note-title\" font-weight=\"bold\" fill=\"black\"><tspan x=\"0\" dy=\"0.8em\">Face</tspan><tspan x=\"0\" dy=\"1.2em\">:5453831.5mm²</tspan></text></g><path class=\"note-line\" stroke=\"black\" d=\"M 0 0 L 104.79 0\" /><circle class=\"handle \" cursor=\"move\" fill=\"grey\" fill-opacity=\"0.1\" stroke=\"grey\" stroke-dasharray=\"5\" cx=\"0\" cy=\"0\" r=\"10\" /></g></g></g></g></svg>";

        this.canvas = document.createElement('canvas');
        this.canvas.setAttribute('id', '_canvas');

        canvg(this.canvas, svg, {renderCallback: function(){
            console.log(this);
        }});

        nodesToRecover.push({
            parent: parentNode,
            child: svgElem
        });
        parentNode.removeChild(svgElem);

        nodesToRemove.push({
            parent: parentNode,
            child: this.canvas
        });

        parentNode.appendChild(this.canvas);
        let data = this.canvas.toDataURL('image/png', 0.5);
        console.log(data);

我正在执行此操作,但是我在IE11中仅获得空白图像。 但是,我可以在网页上看到画布。 有人可以帮我在这里做错什么吗?

您好。 当我有<image>标签时,我在渲染svg时遇到问题。
barchart (24)

样本svg

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200"/>
</svg>

jsfiddle中的示例http://jsfiddle.net/maestro888/fmjywksq/

我找到了一个简单的解决方法。

确保您的svg图像具有宽度和高度。

否则没有足够的论据,因为无法像图像一样测量svg。

不幸的是,这是事实,但不适用于IE11 ...

很高兴您能解决问题。
只需检查您的JS Fiddle,它就会显示图像。

问候,

伯纳德·塔·贝克

2019年3月27日,星期三,下午4:34亚历山德罗·坎迪尼[email protected]
写道:

我找到了一个简单的解决方法。

确保您的svg图像具有宽度和高度。

否则没有足够的论据,因为无法测量svg
像图像一样。

不幸的是,这是事实,但不适用于IE11 ...


您收到此邮件是因为您发表了评论。
直接回复此电子邮件,在GitHub上查看
https://github.com/niklasvh/html2canvas/issues/95#issuecomment-477242192
或使线程静音
https://github.com/notifications/unsubscribe-auth/AM7ZzLPsl0WJS7gGI9npSsRxR33FCnN9ks5va52bgaJpZM4AD-Sb

我找到了canvg的解决方案,在堆栈溢出时在这里报告:它在IE11上完美运行!

我重新阐述的代码段,删除了jQuery依赖项:

let svgIcons = document.querySelectorAll('.svg-icon');

for (let i = 0; i < svgIcons.length; ++i) {
  let curSvg = svgIcons[i];
  let canvas;
  let xml;

  // Size and color needed for every browser
  curSvg.setAttribute('width', curSvg.parentNode.offsetWidth);
  curSvg.setAttribute('height', curSvg.parentNode.offsetHeight);
  curSvg.setAttribute('style', 'fill: blue');

  canvas = document.createElement('canvas');
  canvas.className = 'screenShotTempCanvas';
  xml = new XMLSerializer().serializeToString(curSvg);
  canvg(canvas, xml);
  curSvg.parentNode.insertBefore(canvas, curSvg.nextSibling);
  curSvg.style.display = 'none';
 }

2019年三月28日星期四,08:49亚历山德罗·坎迪尼, notifications @github.com
写道:

我找到了canvg https://github.com/canvg/canvg的解决方案,
在堆栈溢出这里报告
https://stackoverflow.com/questions/34042440/using-html2canvas-to-render-a-highcharts-chart-to-pdf-doesnt-work-on-ie-and-fir
它在IE11上完美运行!


您收到此邮件是因为您发表了评论。
直接回复此电子邮件,在GitHub上查看
https://github.com/niklasvh/html2canvas/issues/95#issuecomment-477503221
或使线程静音
https://github.com/notifications/unsubscribe-auth/AM7ZzKNy1GOgQU9TVv7PGCi4fJvYSxDVks5vbIIOgaJpZM4AD-Sb

@niklasvh ,您好
以及“ 1.0.0-rc.1”版本也都在我们的anguar6应用程序中,根据您在问题列表中的回答,问题将会出现svg不包含height和width,但是在我的情况下,我的Svg有100%的高度和宽度以及嵌套的div也包含svg标签和嵌套的现有画布,我可以将页面导出为png图像,但是该图像仅包含崩溃的svg图标,并且现有画布也未呈现。我的另一页svg全部显示为崩溃的图像,供您参考,我在此处附上了我的屏幕截图,请查看一下,让我知道谢谢。
html2canvas(this.screen.nativeElement,{useCORS:true})。then(canvas => {
this.canvas.nativeElement.src = canvas.toDataURL('image / png');
this.downloadLink.nativeElement.href = canvas.toDataURL('image / png');
this.downloadLink.nativeElement.download ='screenshot.png';
this.downloadLink.nativeElement.click();
});

html2canvas_orginal_Before export
html2canvas_orginal_after export
html2canvas_exported image

测试pdf(1).pdf
你好
我正在获取轴,但图表的其余区域为黑色。 任何建议

@niklasvh ,您好
以及“ 1.0.0-rc.1”版本也都在我们的anguar6应用程序中,根据您在问题列表中的回答,问题将会出现svg不包含height和width,但是在我的情况下,我的Svg有100%的高度和宽度以及嵌套的div也包含svg标签和嵌套的现有画布,我可以将页面导出为png图像,但是该图像仅包含崩溃的svg图标,并且现有画布也未呈现。我的另一页svg全部显示为崩溃的图像,供您参考,我在此处附上了我的屏幕截图,请查看一下,让我知道谢谢。
html2canvas(this.screen.nativeElement,{useCORS:true})。then(canvas => {
this.canvas.nativeElement.src = canvas.toDataURL('image / png');
this.downloadLink.nativeElement.href = canvas.toDataURL('image / png');
this.downloadLink.nativeElement.download ='screenshot.png';
this.downloadLink.nativeElement.click();
});

html2canvas_orginal_Before export
html2canvas_orginal_after export
html2canvas_exported image

同样的问题,在克隆文档中找到svg时出错

在使用html2canvas之前,我暂时将SVG的高度和宽度设置为。 这样我就可以捕获svg。

var selectedItem = document.querySelector(“。chartWrapper”);
var svgElements = selectedItem.querySelectorAll('svg');
for(让i = 0; i <svgElements.length; i ++){
selectedItem.getElementsByTagName(“ svg”)[i] .style.height = document.getElementsByTagName(“ svg”)[i] .getBoundingClientRect()。height;
selectedItem.getElementsByTagName(“ svg”)[i] .style.width = document.getElementsByTagName(“ svg”)[i] .getBoundingClientRect()。width;
}
html2canvas(selectedItem,{backgroundColor:'#000',allowTaint:true})。then(canvas => {
var myImage = canvas.toDataURL(“ image / png”)。replace(“ image / png”,“ image / octet-stream”);
window.location.href = myImage;
})
for(让i = 0; i <svgCount; i ++){
selectedItem.getElementsByTagName(“ svg”)[i] .style.height ='100%';
selectedItem.getElementsByTagName(“ svg”)[i] .style.width ='100%';
}

// use html2canvas in react project when i need a screenshot for the svg
/**
 * svg to canvas
 * <strong i="5">@param</strong> targetElem
 * <strong i="6">@return</strong> {Promise<[]>} // return svg elements
 */
async function svgToCanvas(targetElem) {
  let nodesToRecover = [], nodesToRemove = [], svgElems = targetElem.querySelectorAll('svg');

  for (let i = 0; i < svgElems.length; i++) {
    let node = svgElems[i], parentNode = node.parentNode, svg = parentNode.innerHTML,
      canvas = document.createElement('canvas'),
      ctx = canvas.getContext('2d');
    canvas.setAttribute('data-cover', 'svg');
    const v = await Canvg.from(ctx, svg);
    v.start();
    // record svg elements
    nodesToRecover.push({
      parent: parentNode,
      child: node
    });
    parentNode.removeChild(node);
    //  record canvas elements
    nodesToRemove.push({
      parent: parentNode,
      child: canvas
    });

    parentNode.appendChild(canvas);
  }
  return nodesToRecover;
}

/**
 * recover canvas to svg
 * <strong i="7">@param</strong> targetElem
 * <strong i="8">@param</strong> svgElems // need to recover svg elements
 * <strong i="9">@return</strong> *
 */
function recoverCanvasToSvg(targetElem, svgElems) {
  let canvasElems = targetElem.querySelectorAll("canvas[data-cover='svg']");
  if(!targetElem){
    throw new Error('must have targetElem param')
  }
  if(!isArray(svgElems) && svgElems.length !== canvasElems.length) {
    throw new Error('svgElems must be an Array, and it`s length equal to canvasElems`s length')
  }
  for(let i = 0; i < canvasElems.length; i++){
    let node = canvasElems[i], parentNode = node.parentNode;
    parentNode.removeChild(node);
    parentNode.appendChild(svgElems[i]?.child);
  }
}
此页面是否有帮助?
0 / 5 - 0 等级