img src=svg in the same document

2019-09-15 07:56发布

I have inline SVG with patterns. I need two different page layouts - one for "media print" another one for browsers. I am creating everything in #svgCanvas dynamically and I need it to appear at the bottom of my print layout.

My first idea was to clone whole svg, but then I ended up with things having same ID's and Firefox and Edge got really upset about it. What are the alternatives to achieve this?

I had a look at doing svg to html5 canvas conversion but for some reason that did not really work out for me so I though maybe there is another easier way like the one below? I know it is possible to do something like this:

<img src="external.svg">

so thought I should be able to do the same with inline svg.

<span class="media-print-only">
  some stuff
  <img src="#svgCanvas">
</span>

<span class="no-media-print">
  some more stuff
  <svg id="svgCanvas">
    <defs> some <patterns> </defs>
    some lines and rectangles that are using patterns in defs
  </svg>
  again more stuff
</span>

2条回答
Fickle 薄情
2楼-- · 2019-09-15 08:20

You can use use element for this purpose. When you create SVG graphic with id, you can refer it in any place by using use element, like this.

<span class="media-print-only">
  <div class="svg-container">
    <svg width="200px" height="200px">
      <use xlink:href="#svgCanvas"/>
    </svg>   
  </div>
</span>

<span class="media-no-print">
  <div class="svgRealPlace">
    <svg width="200px" height="200px">
      <use xlink:href="#svgCanvas"/>
    </svg>
  </div>
</span>

<!--defining base SVG graphic-->
<svg width="0" height="0">
  <svg id="svgCanvas" width="200px" height="200px">
    <defs>
      <pattern id="pattern" width="10" height="10" patternUnits="userSpaceOnUse">
        <circle cx="5" cy="5" r="5" fill="blue"/>
      </pattern>
    </defs>
    <circle cx="100" cy="100" r="100" fill="url(#pattern)"/>
  </svg>   
</svg>

Note:
Base svg element or its ancestor elements must not have display:none style or hidden property, because they break reference to base svg. So I set size of container svg element to 0 to hide from screen.

查看更多
男人必须洒脱
3楼-- · 2019-09-15 08:37

I found a workaround to this problem - use jquery to move svg to printable place just before window.print() method and put the svg back to its original place straight after the method:

HTML

<span class="media-print-only">
  some-stuff
  <div class="svg-container"></div>
</span>

<span class="media-no-print">
  some more stuff
  <div class="svgRealPlace">
    <svg id="svgCanvas">
      <defs> some patterns </defs>
      some lines and rectangles that are using patterns in defs
    </svg>
  </div>
  again more stuff
</span>

JS

function printButtonClicked(){
    $(".svg-container").append($('#svgCanvas'));
    window.print();
    $(".svgRealPlace").append($('#svgCanvas'));
}

Tested on Chrome, Firefox and Edge. I really hope there exists a better solution since DOM modifications are almost never a good idea.

查看更多
登录 后发表回答