Bind external svg to data - svg

Community,
I would like to bind an external svg file to my data-array.
I loaded the element into my dom like this:
defs = d3.select("defs");
d3.html("combisymbol.svg", function(data) {
//get a selection of the image so we can pull out the icon
xml = d3.select(data);
icon = document.importNode(xml.select("#star").node(), true);
icon.id = "staricon";
defs.node().appendChild(icon);
// console.log("icon", icon);
Then I tried to make it visible. I used the same approach as when I take circles that I bind to my data. With the circles it works, but my external svg is not visible.
d3.select("body").select("div#divCombiSVG")
.selectAll("star")
.data(combiData)
.enter()
.append("svg:use")
.attr("xlink:href", "#staricon");
I don't see the svgs.
I have also tried this:
d3.select("body").select("div#divCombiSVG")
.selectAll("star")
.data(combiData)
.enter()
.append("svg")
.attr("width",200)
.attr("height",200)
.node().appendChild(icon);
But then the icon gets only added to the first data-element and not the second. Even though it's added to the first, it's still not visible.
The svg file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904 /DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="200px" height="200px" viewBox="0 0 37.207 100" enable-background="new 0 0 37.207 100"
xml:space="preserve">
<path xmlns="http://www.w3.org/2000/svg" id="star" cx="50" cy="50" r="20" r2="43"
orient='point' points='3' radial-shift='0' outerCurve='86'
outerOffset='4.1' innerCurve='56' innerOffset='2.2' d="M300,168
C347.7790400396858,178.49361334198113
345.7070270919484,217.64466544113793 337.23909236273084,228.5
C350.87405522189334,226.59422068634012 385.8158673985199,244.3753308862077 371.014083110324,291
C338.0368273588341,327.1310557718112
305.1670281299449,305.76111387252195 300,293 C294.83297187005513,305.76111387252195
261.9631726411659,327.1310557718112 228.98591688967605,291 C214.1841326014801,244.37533088620776
249.12594477810666,226.59422068634015 262.7609076372691,228.50000000000003
C254.29297290805158,217.64466544113793 252.22095996031422,178.4936133419811 300,168 "
fill="yellow" stroke="black" stroke-width="2"></path>
</svg>
combiData currently has two objects.
I have looked for hours at other examples but I can't make it work. I think I'm close though...I'm pretty new to d3 (but very motivated) so please be patient with me. :-)
Thanks in advance for your help!

In the first case, you are doing a .selectAll('star') (searching for the tag star), which probably should have been a .selectAll('#star') (searching for a tag with id star).
Your second approach can be tweaked a little to work as well. Calling node() on a d3 selection always returns just one node. Hence, the subsequent .appendChild happens only on the first node.
You can try this, if you find this more amenable to what you wanted to do:
d3.select("body").select("div#divCombiSVG")
.selectAll("star")
.data(combiData)
.enter()
.append("svg")
.attr("width",200)
.attr("height",200)
.each(function (d) {
this.appendChild(icon);
});
Since in the comments you asked for which option to prefer: I would recommend the first approach of using the use element. It results in less code and you can even refer to the file containing the star externally which means that you will not have to download and inline the SVG yourself (note the caveat about IE).

Related

How do I convert svg code to svg path image?

How would I be able to convert this type of svg:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250">
<metadata><?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c145 79.163499, 2018/08/13-16:40:22 ">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/">
<xmpRights:Marked>True</xmpRights:Marked>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?></metadata>
<image id="N_side_slit" data-name="N side slit" x="21" y="44" width="178" height="148" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAALIAAACUCAYAAAA3f3NDAAADx0lEQVR4nO3a3Y3rNhCA0dm9eUtTaSA9pIX0ky5SQFJCmslj4GCBXcAw1j+SSHGGPN+zJdP0sSCTertcLpeo2VvRcc/eEE/vhUFU/QGqQ++fp4RZpXu/GjzMKtv7zcBhVsluIQfMqth3kANmVese5IBZlXoEOWBWlZ5BDphVoVcgB8zK3quQA2ZlbgvkgFlZ2wo5YFbG9kAOmJWtvZDjE/M/BXHAPGFHIH/0e0T8C7NGdxTy3xHxK8wa3VHIAbMy1AJywKzRtYIcMGtkLSEHzBpVa8gBs0bUA3LArLPrBTlg1pn1hBww66x6Qw6YdUZnQA6Y1buzIAfM6tmZkANm9epsyAGzejQCcsCs1o2CHDCrZSMhB8xq1WjIAbNalAFywKyjZYEcMOtImSAHzNpbNsgBs/aUEXLArK1lhRwwa0uZIQfMerXskANmvVIFyAGznjUS8m8bXw+z7jYS8h8wq1UjIf+AWa0afY8Ms5qU4c8ezDpcllULmHWoTMtvMGt32daRYdauMm6IwKzNZd3Zg1mbyrxFDbNeLvuzFjDrpSo8NASznlbl6TeY9bAqkANmPaoS5IBZ96oGOWDWd1WEHDDrtqqQA2ZdVxlywKyvqkMOmBWTQA6YNQvkgHntZoIcMK/bbJAD5jWbEXLAvF6zQg6Y12pmyAHzOs0OOWBeoxUgB8zz93a5DPu8I974v4j4acdxv0TEnxHx88ecdRhXz84e7xBQq1yRv/qx8zhX5uStBvlIMCcO5G3BnDSQtwdzwkDeF8zJAnl/MCcK5GNdY67WVJhXW0eOTuuqH+vMf3U47xm1no8h3yvIbat6lWs5JzZEJqjart9X5W8zQG4fzAMCuU8wnxzI/YL5xEDuG8wnBXL/YD4hkM8J5s6BfF4wdwzkc4O5UyCfH8wdAnlMMDcO5HHB3DCQxwZzo0AeH8wNAjlHMB8M5DzBfCCQcwXzzkDOF8w7AjlnMG8M5LxVxTwkkHMH84uBnD+YXwjkGsH8JJDrBPODQK4VzHcCuV4wfxPINYP5JpDrBvNVINcO5s9Art/ymAPkaVoeM8jztDRmkOdqWcwgz9eSmEGes+UwgzxvS2EGee6WwQzy/C2BGeQ1mh4zyOs0NWaQ12pazCCv15SYQV6z6TCDvG5TYQZ57abBDLKmwAyyYgbMIOur0phB1nVlMYOs20piBlnfVQ4zyLpXKcwg61FlMIOsZ5XADLJeKT1mkPVqqTGDrC2lxQyytpYSM8jaUzrMIGtvqTCDrCOlwQyyjpYCM8hq0XDMIKtV4zBHxP/bUFzI1KMfEAAAAABJRU5ErkJggg=="/>
</svg>
To a type of svg that has a path and is usable in html like this:
<svg width="36px" height="24px" viewBox="0 0 36 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M8.98885921,23.8523026 C8.8942483,23.9435442 8.76801031,24 8.62933774,24 L2.03198365,24 C1.73814918,24 1.5,23.7482301 1.5,23.4380086 C1.5,23.2831829 1.55946972,23.1428989 1.65570253,23.0416777 L13.2166154,12.4291351 C13.3325814,12.3262031 13.4061076,12.1719477 13.4061076,11.999444 C13.4061076,11.8363496 13.3401502,11.6897927 13.2352673,11.587431 L1.68841087,0.990000249 C1.57298556,0.88706828 1.5,0.733668282 1.5,0.561734827 C1.5,0.251798399 1.73814918,2.85130108e-05 2.03198365,2.85130108e-05 L8.62933774,2.85130108e-05 C8.76855094,2.85130108e-05 8.89532956,0.0561991444 8.98994048,0.148296169 L21.4358709,11.5757407 C21.548593,11.6783875 21.6196864,11.8297916 21.6196864,11.999444 C21.6196864,12.1693815 21.5483227,12.3219261 21.4350599,12.4251432 L8.98885921,23.8523026 Z M26.5774333,23.8384453 L20.1765996,17.9616286 C20.060093,17.8578413 19.9865669,17.703871 19.9865669,17.5310822 C19.9865669,17.3859509 20.0390083,17.2536506 20.1246988,17.153855 L23.4190508,14.1291948 C23.5163648,14.0165684 23.6569296,13.945571 23.8131728,13.945571 C23.9602252,13.945571 24.0929508,14.0082997 24.1894539,14.1092357 L33.861933,22.9913237 C33.9892522,23.0939706 34.0714286,23.2559245 34.0714286,23.4381226 C34.0714286,23.748059 33.8332794,23.9998289 33.5394449,23.9998289 L26.9504707,23.9998289 C26.8053105,23.9998289 26.6733958,23.9382408 26.5774333,23.8384453 Z M26.5774333,0.161098511 C26.6733958,0.0615881034 26.8053105,0 26.9504707,0 L33.5394449,0 C33.8332794,0 34.0714286,0.251769886 34.0714286,0.561706314 C34.0714286,0.743904453 33.9892522,0.905573224 33.861933,1.00822006 L24.1894539,9.89030807 C24.0929508,9.99152926 23.9602252,10.0542579 23.8131728,10.0542579 C23.6569296,10.0542579 23.5163648,9.98354562 23.4190508,9.87063409 L20.1246988,6.8459739 C20.0390083,6.74617837 19.9865669,6.613878 19.9865669,6.46874677 C19.9865669,6.29624305 20.060093,6.14198767 20.1765996,6.03848544 L26.5774333,0.161098511 Z" fill="#FFFFFF"></path>
</svg>
(These are 2 different images)
You'll need to load the first one into a vector editor (eg Inkscape) and use the editor's drawing tools to manually recreate the shape(s).
After 2-3 hours of messing with every possible online program. I downloaded Inkscape and tried to make a svg.
It took another 2 hours because it was showing 0 path every time I was trying to make a svg. Then I found out it didn't detect the shape because it was white.
So I had to go back to photoshop, change the colour to black, save as a PNG then open it on Inkscape then re-path it. Took me way to long to figure this out.
You will need a thirdparty program to make svgs, there is no escaping them. I tried.
Thank you Paul for the suggestion.

D3 and SVG namespaces for custom svg elements or attributes to be valid?

I created some custom svg attributes yet want to pass the svg validator test.
I saw the D3 > Namespace page, the previous How can I specify a custom XML/SVG namespace with D3.js? and thus processed as follow:
// d3.ns.prefix.geo = "http://www.example.com/boundingbox/";
// d3.ns.prefix.inkscape = "http://www.inkscape.org/namespaces/inkscape";
// SVG injection:
var width = 600;
var svg = d3.select("#hook").append("svg")
.attr("name", "Country's_name_administrative_map_\(2015\)")
.attr("id", "Country_s_name")
.attr("width", width)
.attr(':xmlns:geo','http://www.example.com/boundingbox/')
.attr(':xmlns:inkscape','http://www.inkscape.org/namespaces/inkscape')
.attr(":xmlns:cc","http://creativecommons.org/ns#");
// Tags:
svg.append(":geo:g")
.attr(':xmlns:geo','http://www.example.com/boundingbox/')
.attr(":geo:id","geo")
.attr(':geo:syntax', "WSEN bounding box in decimal degrees")
.attr(':geo:west', WEST)
.attr('geo:south', SOUTH)
.attr(':geo:east', EAST)
.attr(':geo:north', NORTH)
.attr(':geo:title', title);
Produce :
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
name="Country's_name_administrative_map_(2015)"
id="Country_s_name"
xmlns:geo="http://www.example.com/boundingbox/"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:cc="http://creativecommons.org/ns#"
width="600"
height="579.2009758421691"
version="1.1">
<defs xmlns="http://www.w3.org/1999/xhtml">
<style type="text/css"><![CDATA[
svg { border: 1px solid rgb(100, 100, 100); }]]>
</style>
</defs>
<geo:g xmlns:geo="http://www.example.com/boundingbox/"
geo:id="geo"
geo:syntax="WSEN bounding box in decimal degrees"
geo:west="-5.8"
south="41"
geo:east="10"
geo:north="51.5"
geo:title="Country's name" />
<defs><pattern id="hash2_4" width="6" h…
…
</svg>
I still get all the errors (larger image) :
The first type of error is related to the custom <geo:g … > element itself, visible above. The 2nd type of errors is related to custom attributes such geo:west="…" or inkscape:group="…", which I expected to be valid due to the earlier xmlns declarations.
Am I walking the wrong road ? How to make custom attribute valid via d3js ?
EDIT: a minimal jsfiddle provide a demo of the buggy output.
About d3js and namespaces. According to Selvin on D3 doesn't append xmlns:something namespace properly to svg element, it's a D3js know bug with known but not yet implemented solution. Also, current way to overcome it is via JQuery
I made some mildly successful tries.
1) Reading: To produce valid svg document which could be saved, #Selim pointed out that d3.ns.prefix is NOT suitable (see d3 doesn't append namespace attributes to svg element ).
2) Reading more: So I read Namespaces Crash Course. The key point is that
[...] namespace prefixes are used to prefix attribute names and tag [element] names [...]
From the official doc with declaration and usages, for the attributes (<script> changed into <a>) :
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:href="space-rocket.html">...</a>
</svg>
and for elements:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<body>
<h1>SVG embedded inline in XHTML</h1>
<svg:svg width="300px" height="200px">
<svg:circle cx="150" cy="100" r="50" fill="#ff0000"/>
</svg:svg>
</body>
</html>
2) Porting: So I went ahead, NOT d3.ns.prefix, but with the handmade custom namespace ("geo") declaration as an attribute to the svg element via :
d3.select("svg").attr(":xmlns:geo","http://www.example.com/something/")
together with usages such
svg.append("geo").attr("id","geo")
.attr('manual', "WSEN bounding box in decimal degrees")
.attr('WEST', "-4.05")
.attr('SOUTH', "40.5")
.attr('EAST', "10.0")
.attr('NORTH', "54.5")
.attr('Title', "Imaginary map of Kinglons ruling Europe");
or
svg.append("geo").attr("id","geo")
.attr(':geo:manual', "WSEN bounding box in decimal degrees")
.attr(':geo:WEST', "-4.05")
.attr(':geo:SOUTH', "40.5")
.attr(':geo:EAST', "10.0")
.attr(':geo:NORTH', "54.5")
.attr(':geo:Title', "Imaginary map of Kinglons ruling Europe");
or
svg.append(":geo:geo").attr("id","geo")
.attr(':geo:manual', "WSEN bounding box in decimal degrees")
.attr(':geo:WEST', "-4.05")
.attr(':geo:SOUTH', "40.5")
.attr(':geo:EAST', "10.0")
.attr(':geo:NORTH', "54.5")
.attr(':geo:Title', "Imaginary map of Kinglons ruling Europe");
and about 3 other variants, but none is valid, all fails the svg validator.
I have no more ideas how to get a valid svg.
Fiddle (downloadable) , svg validator

SVG (1.1) : how to 'link-to' or 'centre' on a shape in a browser?

Is there is browser-independant way getting the browser to centre on a particular shape (by 'id' attribute) ?
I have tried using xlinks wrapped around shapes like this:
<a xlink:href="#node24"> .... </a>
I have reasonably busy (100+ shapes) directed graph diagrams (generated from dot): and when I load them up in Chrome , more often than not, the intial screen is just blank - forcing the user to use scrollbars to find the diagram at all.
I'm afraid I don't have any good news for you.
For stand-alone SVG documents, you can manipulate the part of an SVG displayed when following a link by linking to a <view> element (distinct from, but making use of, the SVG "viewBox" attribute). The view element specifies the viewBox to use and possibly some other parameters, and the graphic will be displayed with those parameters instead of the default ones.
Example code:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMin meet" >
<circle cx ="50" r="40"/>
<view id="panUp" viewBox="0 -50 100 100" />
<view id="zoomIn" viewBox="25 25 50 50" />
</svg>
If you linked to the file as a whole it would show you an image with half a circle centered at the top of the screen.
If, however, you linked to it like http://example.com/sample.svg#panUp, the circle would be the same size but centered on screen. If you linked to http://example.com/sample.svg#zoomIn, you'd only see the bottom edge of a circle that is twice as big.
(I don't have anywhere to host the file that can serve up raw SVG files, but this CodePen uses data URI to show the effects, although the data URI fragment identifiers doesn't seem to work in Firefox.)
You are supposed to be able to even specify the desired viewBox, transforms, or other attributes as part of the URL fragment (like http://example.com/sample.svg#myView(viewBox(0,0,200,200))), but I don't think that's widely implemented -- it had no effect on either Firefox or Chrome.
And even <view> fragments don't seem to work when the SVG is embedded within an HTML document. So unless your SVG is stand-alone, creating a view for each element (or one view that your dynamically change to match the clicked element), isn't going to be worth the trouble.
So what does work?
The default behaviour, when linking to a fragment (element id) that is not a <view> is to display the nearest ancestor <svg> element that contains that element ("nearest ancestor" because an SVG can contain nested <svg> tags). So if your document has a natural structure to it, you could replace some <g> elements with <svg> with a specified x,y,height and width parameter, and then linking to an element within that sub-graphic would show that view. That should work even when the SVG is embedded within a larger HTML document. But if you've got hundreds of elements moving around, it's probably not a practical solution.
Which leaves #Ian's solution of programmatically manipulating the main SVG viewBox. If you don't want to zoom in, just pan, leave the width and height as the full size of your visualization, and just change the x and y offsets. Something like:
function centerViewOnElement( el ) {
var bbox = el.getBBox()
var elCenterX = bbox.x + bbox.width/2,
elCenterY = bbox.y + bbox.height/2;
svg.setAttribute("viewBox", [(elCenterX - width/2),
(elCenterY - height/2),
width,
height
].join(" ") );
//assuming you've got the svg, width and height already saved in variables...
}
Thought I would do a simpler example, as this feels quite useful in general...with a jsfiddle here
<svg id="mySvg">
<circle id="myCirc" cx="20" cy="20" r="20"/>
<rect id="myRect" x="50" y="50" width="50" height="50"/>
</svg>
var mySvg = document.getElementById("mySvg");
function getNewViewbox( el ) {
var bbox = el.getBBox();
return newViewbox = bbox.x + " " + bbox.y + " " + bbox.width + " " + bbox.height;
}
function focusElement( ev ) {
ev.stopPropagation();
mySvg.setAttribute("viewBox", getNewViewbox( ev.target ) );
}
//click on any element, or even the svg paper
document.getElementById("mySvg").addEventListener("click", focusElement);

How to append a text element with inline tspan children?

Starting with a DOM that already contains something like
<svg id="svg0" width="600" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>
...I want to programmatically modify the element in d3.select("#svg0") so that I end up with
<svg id="svg0" width="600" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
<text x="20" y="20">
Lorem ipsum
<tspan style="alignment-baseline:text-before-edge">dolor</tspan>
sit amet</text>
</svg>
This is as far as I can get:
var $svg = d3.select("#svg0");
$svg.append("text").text("Lorem ipsum ")
.attr({x:"20", y:"20"});
It looks as though the rest should be easy, but I've spent the last two hours trying all the "obvious" things to finish this without success.1
What does one have to do to finish the task described above?
1I've tried far too many things to describe them all. Suffice it to say that the text method, when used as a setter, wipes out whatever textContent the text object had before. This means that, effectively, this method can be called only once, which precludes solutions relying on calling .text(...) a second time to add the " sit amet" fragment.)
Normally you would think to use the html function for this, but from the docs:
Note: as its name suggests, selection.html is only supported on HTML
elements. SVG elements and other non-HTML elements do not support the
innerHTML property, and thus are incompatible with selection.html.
Consider using XMLSerializer to convert a DOM subtree to text. See
also the innersvg polyfill, which provides a shim to support the
innerHTML property on SVG elements.
Here's with the polyfill: http://jsfiddle.net/GNGF5/
And if you don't want to do that, you can hack it up using multiple tspan elements w/ a transform, as seen here: http://jsfiddle.net/cAuCM/
var $svg = d3.select("#svg0");
var $text = $svg.append("text");
var $tspan1 = $text.append('tspan');
var $tspan2 = $text.append('tspan');
var $tspan3 = $text.append('tspan');
$text.attr('transform', 'translate(0, 18)');
$tspan1.text('Lorem ipsum');
$tspan2.text('dolor').style('alignment-baseline', 'text-before-edge');
$tspan3.text('sit amet');
Here's how to do it with Snap.svg:
var paper = Snap("#svg0");
var t1 = paper.text(50, 50, "Snap");
var t2 = paper.text(50, 70, ["S","n","a","p"]);
<script src="https://cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script>
<svg id="svg0" width="600" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>

Is it possible to import svg shapes in d3.js?

First day with d3.js, going well, but I need to change my placeholder circle shapes to something a litte more complex.
Can SVG shapes that I've created in, say, Illustrator, be "imported" into a d3.js chart?
I know I can redraw it in d3... but my head hurts right now... er...
it's a simple bubble with a point:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="77px" height="41px" viewBox="0 0 77 41" enable-background="new 0 0 77 41" xml:space="preserve">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#999999" d="M0,13C0,5.82,5.82,0,13,0h51c7.18,0,13,5.82,13,13s-5.82,13-13,13
H47l-7,15l-7-15H13C5.82,26,0,20.18,0,13z"/>
</svg>
Can that be imported as a shape?
Or is there a way to translate that path directly in d3js?
Thanks!
If by "imported" you mean be part of the page markup and then used by your d3 code, then yes you can use svg defs element to hold the definition of your custom shape. Then later in your code you create a use element to reference it:
var node = svg.selectAll("g.node")
.data(nodes)
.enter()
.append("g")
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; } )
node.append("use")
.attr("xlink:href","#myshape")
Here is a full example of the above approach. I used Inkscape but the concept is the same:
http://bl.ocks.org/explunit/5988971
Note that the xlink namespace in the svg definition is important for the use element to work properly, and I see you have it your code already:
xmlns:xlink="http://www.w3.org/1999/xlink"
If by "imported" you mean loaded on-the-fly, then a different approach is needed, as suggested by #LarsKotthoff. But it sounds like you just want to reuse an existing shape definition, and the above approach lets you do it. The <g> element sets the position of the shapes, and then child node <use> is added to pull in the actual shape defined earlier.
The definition of the shape is in the svg element in the body, not in the javascript itself. This differs from many D3.js examples which have the svg element created dynamically by the javascript code.
The only connection between the two is the string ID that you put in the href ("myshape" in this case) to match the id in the defs section:
node.append("use").attr("xlink:href","#myshape")

Resources