PhoebeB
PhoebeB

Reputation: 8570

SVG use element to clone SVG

Is it possible to "use" a whole other svg within a separate svg? I want to use an map generated with d3 as an icon on the same page. This is what I tried but it doesn't work.

 <svg id="map">
    svg stuff here
 </svg>


 <svg id="bar"> 
     svg stuff here
     <use xlink:href="#map" height="20" width="30" ...>
 </svg>

Also tried the cloning approach but ended up with an entire svg within another svg and couldn't get it to scale. eg. makeicon("#map", "#icon")

function makeicon(source, destination) {
    //https://groups.google.com/forum/?fromgroups=#!topic/d3-js/-EEgqt29wmQ
    var src = d3.select(source);
    var dest = d3.select(destination);

    if (!src.empty() && !dest.empty()) {

        var newNode = d3.select(dest.node().insertBefore(src.node().cloneNode(true),
            src.node().nextSibling))
            .attr("id", "newnode")
            .attr("width", null)  // remove height and width of original svg
            .attr("height", null)

            .attr("viewBox", "0 0 20 30");   // try to make it smaller

        return newNode;

Upvotes: 5

Views: 5704

Answers (4)

Pedro404
Pedro404

Reputation: 178

Since SVG 2, the [ xlink:href ] attribute is deprecated in favor of [ href ].

<use xlink:href="#myId" />

Deprecated: This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time. INFO...

<use href="#myId" />

<svg viewBox="0 0 30 10" width="300" height="100" xmlns="http://www.w3.org/2000/svg">
  <circle id="myCircle" cx="5" cy="5" r="4" stroke="blue"/>
  <use href="#myCircle" x="10" fill="blue"/>
  <use href="#myCircle" x="20" fill="white" stroke="red"/>
  <!--
stroke="red" will be ignored here, as stroke was already set on myCircle.
Most attributes (except for x, y, width, height and (xlink:)href)
do not override those set in the ancestor.
That's why the circles have different x positions, but the same stroke value.
  -->
</svg>

Demo-codepen.io

Upvotes: 0

Eliran Malka
Eliran Malka

Reputation: 16263

Considering very limited support at the moment (Gecko engines only), this can be done using the CSS 3 element() function.

The MDN docs also specifies your case as a common use case:

... A particularly useful scenario for using this would be to render an image in an HTML <canvas> element, then use that as a background.


Live Demo

Upvotes: 0

Nicolas Hoizey
Nicolas Hoizey

Reputation: 2031

You can use svgWeb to make it work in webkit browsers.

Upvotes: 0

Erik Dahlstr&#246;m
Erik Dahlstr&#246;m

Reputation: 60976

It should work fine.

Here's a simple example that works fine in Firefox, Opera and Chrome: http://jsfiddle.net/gew54/

Source:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <style type='text/css'>
            svg {
                width: 100px;
                height: 100px;
            }
        </style>
    </head>
    <body>
        <svg id="map" viewBox="0 0 100 100">
            <circle cx="50" cy="50" r="20" fill="lime"/>
        </svg>
        <svg id="bar" viewBox="0 0 100 100">
            <use xlink:href="#map" />
        </svg>
    </body>
</html>

Upvotes: 3

Related Questions