I have managed to apply a gradient to my bar chart and the gradient effect gives the desired result.
var gradient = svg.append("defs")
.data(data)
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "00%")
.attr("spreadMethod", "pad");
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", function(d) {
return colors(d.name);
})
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", function(d) {
return colors(d.name);
})
.attr("stop-opacity", 0.3);
I also have a color scale that I'm using to assign colors to each category (name)
var colors = d3.scale.ordinal()
.range(["#C1D42F", "#2b328c", "#5AB88D", "#8F1F61", "#00A5D3", "#EC5D20", "#F59C28"])
This was working fine before I started to use gradient
However, now it appears that the function I'm using is only taking the first color (#C1D42F) from my range.
How can I apply the gradient as well as assign the ranged colors ?
Here is my fiddle
There are two issues related to this result
This is necessary to create a linearGradient element for each data point. Instead of:
var gradient = svg.append("defs")
.data(data)
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "00%")
.attr("spreadMethod", "pad");
You could use:
var gradient = svg.append("defs")
.selectAll("linearGradient") // Creates the initial selection of linear gradients
.data(data)
.enter() // Binds new linearGradient elements for each data point
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "00%")
.attr("spreadMethod", "pad");
Now, instead of having only one linearGradient element, you have one for each color. However, you will notice the problem persists, which leads to the second issue:
Different linearGradient elements need different IDs in order to reference the data they represent. Continuing the previous example, instead of:
var gradient = svg.append("defs")
.selectAll("linearGradient") // Creates the initial selection of linear gradients
.data(data)
.enter() // Binds new linearGradient elements for each data point
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "00%")
.attr("spreadMethod", "pad");
You could use:
var gradient = svg.append("defs")
.selectAll("linearGradient") // Creates the initial selection of linear gradients
.data(data)
.enter() // Binds new linearGradient elements for each data point
.append("linearGradient")
.attr("id", d => `gradient${d.name}`) // Create a unique data-driven id for each linearGradient
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "00%")
.attr("spreadMethod", "pad");
And in the bars, the code can now reference the correct linearGradient according to the data:
bars.append("rect")
...
.style("fill", d => `url(#gradient${d.name})`); // picks the gradient that match the data
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With