Reputation: 6435
I have a an SVG where I am targeting a certain path element with id: _116
.
I can fill the path easily with a solid colour by doing this:
d3.select("path#_116").style("fill", 'blue');
However lets say I have a linear scale colour so that I want a gradient applied to it:
let scale = d3.scaleLinear()
.domain([1,10])
.range(["white", "blue"]);
d3.select("path#_116").style("fill", scale);
This just doesn't work. For some reason it's setting the fill to a black colour (#212a39) which seems like is coming from the sibling element as shown below:
Any ideas on what's happening here?
Upvotes: 1
Views: 424
Reputation: 38231
The scale function will return a single color for a provided value (as is true for all D3 scaling functions), which likely explains the output you are seeing. The scale by default is not clamped, so the scale will interpolate values outside the domain and return values outside the range, which explains why you have a value that doesn't appear to fit in your domain.
Scaling functions do not modify the DOM but a gradient requires elements within the SVG to represent the gradients. Usually gradients are children of a defs tag:
<svg>
<defs>
<linearGradient id="gradient">
<stop stop-color="white" offset="0%"/>
<stop stop-color="blue" offset="100%"/>
</linearGradient>
</defs>
<rect width=300 height=100 fill="url(#gradient)"></rect>
</svg>
If you have an existing SVG and want to amend a single path, we can append the defs, the gradient, the stops, and apply it to a given path:
d3.xml("https://upload.wikimedia.org/wikipedia/commons/a/ab/Isobates-simple_example.svg")
.then(function(image) {
let svg = d3.select("body")
.append(()=>image.documentElement);
let gradient = svg.append("defs")
.append("linearGradient")
.attr("id","gradient");
gradient.append("stop")
.attr("stop-color","white")
.attr("offset","0%")
gradient.append("stop")
.attr("stop-color","blue")
.attr("offset","100%");
svg.selectAll("#path3156")
.style("fill", "url(#gradient)");
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.0/d3.min.js"></script>
There are ways you can more efficiently do this, though generally you'll be going about achieving the same structure in the DOM (using .append() and .html() can save some lines). And D3 is completely optional as well - this is just adding a few elements to the DOM and setting an existing element's fill.
Your question appears to be concerned with a singular gradient, but if we have many gradients the answer gets a bit more complicated if we want the gradients to be data driven and incorporate scaling into the mix. Since I don't think you are asking about that I'll leave that for another time.
Upvotes: 1