Mike Williamson Mike Williamson - 2 months ago 29
Javascript Question

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
is an icon, similar to what is shown in the example above, but with a valid svg element. E.g., the
element starts something like this:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
<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:

.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
, I'll see that I have access to
, 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.


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.