【问题标题】:SVG scripting - inserting image dynamically failsSVG 脚本 - 动态插入图像失败
【发布时间】:2017-01-15 13:12:10
【问题描述】:

我正在尝试向 SVG 添加一些 polyfill 功能。为了做到这一点,我向 SVG 添加了一些 JavaScript 代码,在其中我创建了一个画布元素,在其上绘制,获取画布的 dataURL 并将其添加为 SVG 中的image 元素。以下是SVG

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   height="297mm"
   width="210mm"
   viewBox="0 0 744.09448819 1052.3622047"
   id="svg11346"
>
  <script type="application/ecmascript"> <![CDATA[
    var svg = document.querySelector('svg');
    svg.onload = function () {
      var canvas = document.createElementNS('http://www.w3.org/1999/xhtml','canvas');
      canvas.width = 50;
      canvas.height = 50;
      var ctx = canvas.getContext('2d');
      ctx.clearRect(0,0,50,50);
      ctx.fillStyle = '#0f0';
      ctx.fillRect(20,20,20,20);

      var img = document.createElementNS('http://www.w3.org/2000/svg','image');
      img.setAttribute('xlink:href', canvas.toDataURL());
      img.setAttribute('x',0);
      img.setAttribute('y',0);
      img.setAttribute('width',50);
      img.setAttribute('height',50);
      svg.appendChild(img);

    };
  ]]> </script>
  <rect
          style="fill:#f00;fill-opacity:1;"
          id="rect11482"
          width="100"
          height="100"
          x="200"
          y="0" />


</svg>

使用此代码,除了红色的 SVG 矩形元素之外,我希望在左上角附近看到一个小的绿色矩形。但是当我在 Chrome 或 Firefox 中加载这个 SVG 时,我看不到它。但是,当我检查 DOM 时,我看到 image 标记已添加到 svg 元素中。当我在 Devtools 中将鼠标悬停在它上面时,我可以看到页面上突出显示了一个矩形。这意味着 image 元素正在被添加,但没有被渲染。

为了验证画布绘图是否正常工作,我从开发工具中复制了image,然后手动将其插入到 SVG 文件中,禁用脚本代码并在浏览器中重新加载 SVG。我可以看到预期的绿色矩形。

这告诉我,在我动态插入图像元素后,SVG 实现可能不会刷新文档的呈现。我试图从脚本中动态插入一个原生 SVG 元素(一个圆圈),它显示正确。所以它可能只与图像元素有关。

有什么想法吗?我可以做些什么来触发重绘吗?有没有其他方法可以在 SVG 中显示动态生成的画布内容?

【问题讨论】:

    标签: javascript svg


    【解决方案1】:

    您需要 setAttributeNS 来获取 NameSpaced 属性(至少在 SVG1.1 中),xlink:href 就是其中之一。

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    
    <svg
       xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       height="297mm"
       width="210mm"
       viewBox="0 0 744.09448819 1052.3622047"
       id="svg11346"
    >
      <script type="application/ecmascript"> <![CDATA[
        var svg = document.querySelector('svg');
          var canvas = document.createElementNS('http://www.w3.org/1999/xhtml','canvas');
          canvas.width = 50;
          canvas.height = 50;
          var ctx = canvas.getContext('2d');
          ctx.clearRect(0,0,50,50);
          ctx.fillStyle = '#0f0';
          ctx.fillRect(20,20,20,20);
    
          var img = document.createElementNS('http://www.w3.org/2000/svg','image');
          img.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', canvas.toDataURL());
          img.setAttribute('x',0);
          img.setAttribute('y',0);
          img.setAttribute('width',50);
          img.setAttribute('height',50);
          svg.appendChild(img);
    
    
      ]]> </script>
      <rect
              style="fill:#f00;fill-opacity:1;"
              id="rect11482"
              width="100"
              height="100"
              x="200"
              y="0" />
    
    
    </svg>

    【讨论】:

    • 太棒了。我监听 onload 事件,因为我想访问 defs 下的一些元素,这些元素只有在 DOM 加载后才可用。您对使用 setAttributeNS 的建议也适用于我使用 onload 的代码版本,因此看起来不错。 w3.org/TR/SVG/script.html#LoadEvent
    • @Jayesh Hmm 只是在加载事件和我的 FF 上有一个错误......(它只在窗口上触发,而不是 doc 或 doc.docElement 但我认为你是对的它应该触发;-) 但是您也可以将脚本节点附加到 svg 文档的底部(我通常这样做)
    猜你喜欢
    • 2011-12-20
    • 2020-02-16
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多