简体   繁体   English

SVG Text属性加倍 - HTML2CANVAS

[英]SVG Text attribute is doubling - HTML2CANVAS

Here is mycode and link to JSFiddle . 这是mycode和JSFiddle的链接。

HTML HTML

<input type="button" id="export" value="Export"/>
    <svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">

<text x="162" text-anchor="middle" class="highcharts-title" zindex="4" style="color:#333333;font-size:18px;font-weight:normal;text-decoration:normal;font-family:Lucida Grande,Lucida Sans Unicode, Arial, Helvetica, sans-serif;visibility:visible;fill:#333333;width:260px;" y="25">Inventory</text>
</svg>

JS JS

$(document).ready(function(){
        $('#export').on('click', function() {       
            html2canvas(document.body, {
                onrendered: function(canvas) {
                    document.body.appendChild(canvas);
                },
            });
        });
});

I'm trying to convert an svg to canvas image using html2canvas library. 我正在尝试使用html2canvas库将svg转换为canvas图像。 In the example I'm just appending the canvas image to the output. 在示例中,我只是将画布图像附加到输出。 You can clearly see that the text is multiplied. 您可以清楚地看到文本成倍增加。 Could anyone advice me to solve this issue. 任何人都可以建议我解决这个问题。

Hope my question is clear. 希望我的问题很明确。 Thanks in advance. 提前致谢。

Caused by an issue in html2canvas generating the text elements twice. 由html2canvas中的问题引起两次生成文本元素。

Apply this patch to fix until this pull request is incorporated in a html2canvas release: 应用此修补程序进行修复,直到此拉取请求合并到html2canvas版本中:

NodeParser.prototype.getChildren = function(parentContainer) {
    return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
        var container = [node.nodeType === Node.TEXT_NODE && !(node.parentNode instanceof SVGElement) ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
        return node.nodeType === Node.ELEMENT_NODE && container.length && node.tagName !== "TEXTAREA" ? (container[0].isElementVisible() ? container.concat(this.getChildren(container[0])) : []) : container;
    }, this));
};

I didn't find a clean way to fix it. 我找不到一个干净的方法来解决它。 So I came up with the following, will need tweaking to represent your application but works like a charm. 所以我想出了以下内容,需要调整来代表你的应用程序,但就像一个魅力。

// Replace each SVG text with normal text
$('text').each(function(){

    // Get the offset
    var offset = $(this).offset();

    // Create new text
    $(this).parents('[data-role="canvas"]').append('<p class="app-svg-text-replace" style="top: ' + offset.top + 'px; left: ' + parseInt(offset.left - parseInt((($(window).width() / 2) - 512))) + 'px;">' + $(this)[0].textContent + '</p>');

    // Remove the SVG text
    $(this)[0].textContent = '';

})

Basically just replaces any TEXT element with a P element and the context of the svg texts, and positions it based on the TEXT offsets. 基本上只是将任何TEXT元素替换为P元素和svg文本的上下文,并根据TEXT偏移量对其进行定位。 Just create the P elements before the body tag and make them absolute. 只需在body标签之前创建P元素并使其成为绝对值。 (I am putting them in a divs inside a wrapper that's why there is -512 etc, you can ignore that) (我把它们放在一个包装内的div中,这就是为什么有-512等,你可以忽略它)

Before: 之前: 在此输入图像描述

After: 后: 在此输入图像描述

Depending on what you're targeting you may no longer need HTML2Canvas in order to paint SVG onto a canvas. 根据您的目标,您可能不再需要HTML2Canvas来将SVG绘制到画布上。

In at least Chrome it is possible to draw that particular SVG directly onto a canvas now. 至少在Chrome中,现在可以将特定的SVG直接绘制到画布上。 Using your example: 使用你的例子:

$(document).ready(function () {
    $('#export').on('click', function () {
        // TODO
        var can = document.getElementById('canvas1');
        var ctx = can.getContext('2d');
        var img = new Image();
        var svg = document.getElementById('aaa');
        var xml = (new XMLSerializer).serializeToString(svg);
        img.src = "data:image/svg+xml;charset=utf-8,"+xml;

        ctx.drawImage(img, 0, 0);

    });
});

http://jsfiddle.net/ncv56vwf/4/ http://jsfiddle.net/ncv56vwf/4/


It may take a bit more work in Firefox and IE11, but it is possible. 在Firefox和IE11中可能需要更多的工作,但它是可能的。 Here's an example that works in Chrome, Firefox, and IE11: 以下是适用于Chrome,Firefox和IE11的示例:

var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');

var img = new Image();
img.onload = function() {
  ctx.drawImage(img, 0, 0, 600, 600, 0, 0, 600, 600)
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/8/84/Example.svg"

http://codepen.io/simonsarris/pen/rVOjby http://codepen.io/simonsarris/pen/rVOjby

For it to work in firefox the SVG must have its width and height attributes set. 为了在Firefox中工作,SVG必须设置其widthheight属性。

For it to work in IE11 you MUST use all arguments to drawImage 要使它在IE11中工作,你必须使用drawImage所有参数

IDK what exactly does not work, but I suppose, that it is HTML2Canvas library. IDK究竟什么不起作用,但我想,它是HTML2Canvas库。 Becase, when I remove font-size style proprerty, all became ok: 但是,当我删除字体大小的风格时,一切都变好了:

<text x="162" text-anchor="middle" class="highcharts-title" zindex="4"
 style="color:#333333;font-weight:normal;text-decoration:normal;
font-family:Lucida Grande,Lucida Sans Unicode, Arial, Helvetica,
 sans-serif;visibility:visible;fill:#333333;width:260px;" y="25">Inventory</text>

And this one work perfect: 而这一个工作完美:

<text x="162" text-anchor="middle" class="highcharts-title" zindex="4" style="" y="25">Inventory</text>

lol 大声笑

you have to download the font. 你必须下载字体。 You can use @import in your css as you can see in this fiddle : 你可以在你的css中看到@import ,你可以在这个小提琴中看到:
http://jsfiddle.net/scraaappy/04wkvweo/ or @font-face (not tested), or use google font api by adding < link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Tangerine"> in your header (Tangerine as sample, but any font you want here : https://www.google.com/fonts/ (unfortunately, no Lucida Grande) http://jsfiddle.net/scraaappy/04wkvweo/@font-face (未经测试),或使用google font api添加< link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Tangerine">作为示例,但您想要的任何字体: https//www.google.com/fonts/ (不幸的是,没有Lucida Grande)

@degr : If you just remove Lucida Grande, it will work because other fonts specified are supported by your browser whereas Lucida Grande is not (this the case for google chrome on windows). @degr:如果你只是删除Lucida Grande,它会起作用,因为你的浏览器支持指定的其他字体,而Lucida Grande不支持(这是windows上谷歌浏览器的情况)。 Html2canvas can only deal with your default font, otherwise you have to download them. Html2canvas只能处理您的默认字体,否则您必须下载它们。 That's why it works if you don't specified any font or if you specified only fonts supported by your browser. 这就是为什么它没有指定任何字体或只指定浏览器支持的字体的原因。

To see fonts supported by your browser, just adjust settings and somewhere in default fonts and encoding, you have a list box containing the list of all font supported which let you choose the default font you want to be displayed (or you can play with javascript as it's suggested here: list every font a user's browser can display ) All the fonts listed will work. 要查看浏览器支持的字体,只需调整设置以及默认字体和编码中的某个位置,您就会有一个列表框,其中包含所有支持的字体列表,您可以选择要显示的默认字体(或者您可以使用javascript播放)这里建议: 列出用户浏览器可以显示的每种字体 )列出的所有字体都可以使用。 If not you have to use the trick above 如果不是,你必须使用上面的技巧

我发现基本上是Unicode(Lucida Sans Unicode)字体在chrome中没有正确使用HTML2Canvas,而其他东西是支持font-Size这个是小,小,大,大等...虽然这个信息没有解决您当前的问题,但如果您可以替换这些东西,那么您可以避免这个问题

Issue is that HTML2Canvas does not properly support svg files (more explanation here https://github.com/niklasvh/html2canvas/issues/95 ). 问题是HTML2Canvas不能正确支持svg文件(更多解释见https://github.com/niklasvh/html2canvas/issues/95 )。

An alternative you can do if you still need HTML2Canvas is to convert the SVG to Canvas first (canvg.js does this) then use HTML2Canvas on that, then revert it back. 如果你仍然需要HTML2Canvas,你可以做的另一种方法是首先将SVG转换为Canvas(canvg.js这样做)然后在其上使用HTML2Canvas,然后将其还原。 An example of the code that does this can be found on the link above. 可以在上面的链接中找到执行此操作的代码示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM