javascriptd3.jssvgsvg-path

D3: How to adjust SVG image path elements programmatically?


Using Icons as Data Points

Inspired by the ability to use svg images as data elements, as this block demonstrates, I wanted to take it a level further and use SVG images (SVG paths), so that I could also adjust their stroke color & thickness.

Here is a screenshot of the block I have linked above:

enter image description here


Using SVG Paths as Icons

The code uses an image, instead of an SVG path. I mimicked the code, pointing my equivalent of .attr("xlink:href", "https://github.com/favicon.ico") to an svg image instead. E.g., .attr("xlink:href", "../images/my_logo.svg"), where my_logo.svg is an icon, similar to what is shown in the example above, but with a valid svg element. E.g., the my_logo.svg element starts something like this:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
 "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
 width="900.000000pt" height="900.000000pt" viewBox="0 0 900.000000 900.000000"
 preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,900.000000) scale(0.100000,-0.100000)">
<path d="M4280 8997 c-3 -2 -54 -7 -115 -10 -684 -37 -1449 -290 -2080 -690
-621 -393 -1182 -990 -1525 -1622 -24 -44 -53 -98 -65 -120 -44 -81 -139 -294

. . .

2310 880 278 21 516 20 785 -6z" stroke="red" stroke-width="2" fill="red" />

. . .


Incorporating These SVG Path Files into D3 Environment

However, I am reading this SVG in incorrectly, so that it is treated as an image. I am copying the example in the block mentioned above, which does things like:

node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")

Specifically, in my case I am trying to make a scatterplot, so my code looks like:

var points = svg.selectAll('image').data(data)
                .enter().append('image').classed('point', true)
                .attr("xlink:href", "../images/my_logo.svg")

This obviously brings the SVG in as an "image", which does not allow for me to adjust the stroke width or color or these things which I wish to adjust. For instance, if I look at the elements in the console, using d3.selectAll("image"), I'll see that I have access to x, y, width, height, etc., just as I would with a normal image, not a truly flexible SVG path element.

I know that the issue is because I am importing this icon as an image, but I just don't know the right way to do it.


Solution

  • You, of course, can't modify an SVG that's brought in as an image. You can, however, load the SVG via AJAX and manipulate and inject it from there. You may be better off using a format that is not strictly SVG so that it's easier to modify and inject. For example, an SVG fragment (just the contents of the <svg> element) would be directly injectable and then could be modified through CSS.


    Here is a full example to demonstrate how this can be done, using d3.xhr.