Jayesh
Jayesh

Reputation: 53345

SVG scripting - inserting image dynamically fails

I'm trying to add some polyfill functionality to SVG. In order to do that I'm adding some javascript code to the SVG, in which I create a canvas element, draw on it, get the dataURL of the canvas and add it as image element inside the SVG. Following is the 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>

With this code I'm expecting to see a small green rectangle near top-left corner besides the red SVG rect element. But I do not see it when I load this SVG in Chrome or Firefox. However when I inspect the DOM, I see that the image tag has been added to the svg element. When I hover over it in the Devtools, I can see a rectangle highlighted on the page. That means the image element is getting added, but is not being rendered.

To verify that the canvas drawing is working, I copied the image from the dev tools, then manually inserted it into the SVG file, disabled the script code and reloaded the SVG in the browser. I can see the expected green rectangle.

This tells me that probably the SVG implementation does not refresh the rendering of the document after I've dynamically inserted the image element. I tried to dynamically insert a native SVG element (a circle) from the script and it showed properly. So it probably only has to do with the image element.

Any thoughts? Can I do something to trigger the redraw? Is there any other method by which I can show dynamically generated canvas content in the SVG?

Upvotes: 0

Views: 57

Answers (1)

Kaiido
Kaiido

Reputation: 137014

You need setAttributeNS for NameSpaced attributes (at least in SVG1.1) and xlink:href is one of these.

<?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>

Upvotes: 1

Related Questions