html2canvas: Text tags in SVG overlap (duplicated / doubling)

(Sorry, I am not good at english)

Hello, I am using this awesome script to render SVG tags There is some text overlapping when I render the text tag in SVG to canvas Text tag be processed as a Text node and also SVG You can see that easily with transform property 2015-02-19 15 08 29_2 Here is sample code (with html2canvas 0.5.0-alpha2)

<html>
<head>
  <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
  <script type="text/javascript" src="js/html2canvas.js"></script>
</head>
<body>
  <svg width="100" height="100">
    <g transform="translate(20,20)">
      <text dy=".45em" y="10" x="0" dx="-.8em" transform="translate(0,0) rotate(-70)" style="font-size:12px;">Text</text>
    </g>
  </svg>
  <script>
    $(document).ready(function() {
      html2canvas(document.body, {
        onrendered: function(canvas) {
          document.body.appendChild(canvas);
        }
      });
    })
  </script>
</body>
</html

And Here is my quick change

NodeParser.prototype.getChildren = function(parentContainer) {
    return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
        var container = [node.nodeType === Node.TEXT_NODE && node.parentElement.tagName !== "text" ? 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 hope this will help

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 6
  • Comments: 24 (7 by maintainers)

Commits related to this issue

Most upvoted comments

@hyojin After test it on IE, your fix doesn’t works because parentElement property is not populate on the current node. Use parentNode instead ! In any case, it will be more clear because we are into the NodeParser and it talk about node.

Otherwise, instead test on tag name, i change my code to test the instance of parentNode and process the current node has a TextContainer only if the parentNode isn’t a SVGElement.

It works on chrome and ie11. on firefox i can’t test it because of blank canvas bug !

My code

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 hope this helps.

@hyojin @ncoquelet thanks for the investigation into this and the fix. I ran into the exact same problem the other day and I wasn’t entirely sure what was causing it.

More clear! I also checked that it works well on ff. I merged your fix and pull request was updated. Thanks 😃

Thanks for your fix !

you can also check on tspan tagName : node.nodeType === Node.TEXT_NODE && node.parentElement.tagName !== “text” && node.parentElement.tagName !== “tspan”