aii aii - 1 month ago 13
Javascript Question

D3v4: indexing and selecting color set by scaleOrdinal

I have a code that plots line graphs on a svg canvas, but I'm struggling to change the colors as I define with the d3.scaleOrdinal function.

I am defining 12 distinguishable colors but the result I get is this.
Can anyone help me? Thanks.

var color2 = d3.scaleOrdinal().range([
'#673ab7',
'#9c27b0',
'#e91e63',
'#f44336',
'#ff5722',
'#ff9800',
'#ffc107',
'#ffeb3b',
'#cddc39',
'#8bc34a',
'#4caf50',
'#009688'])
.domain(d3.range(1,13));

var line = d3.line()
.x(function(d) { return x(d.day); })
.y(function(d) { return y(d.temp); });

var lineChart = function(csvfile, i) {
d3.csv(csvfile, function(error, data){
data.forEach(function(d){
d.month = +d.month,
d.day= +d.day,
d.temp= +d.temp;
});

svg.append('path')
.data([data])
.attr('class','line')
.style('stroke', function(i){ return color2(i);})
.attr('d', line);

}); //end of read csv
}; //end of line chart

lineChart('/static/data/temp1.csv'1);
lineChart('/static/data/temp2.csv'2);
lineChart('/static/data/temp3.csv'3);
lineChart('/static/data/temp4.csv'4);
lineChart('/static/data/temp5.csv',5);
lineChart('/static/data/temp6.csv',5);
lineChart('/static/data/temp7.csv',6);
lineChart('/static/data/temp8.csv',7);
lineChart('/static/data/temp9.csv',8);
lineChart('/static/data/temp10.csv',80);
lineChart('/static/data/temp11.csv',90);
lineChart('/static/data/temp12.csv',100);

Answer

First problem: in D3, the first argument is always the data, no matter if you name it d, i or p. So, this:

.style('stroke', function(i){ return color2(i);})

Should be this:

.style('stroke', function(d, i){ return color2(i);})

But this change will not work, because of the second problem.

Second problem: you are calling lineChart for each line, and every time you call it the index will be 0.

A possible solution is passing the index as an argument:

lineChart('/static/data/temp1.csv', 1);
lineChart('/static/data/temp2.csv', 2);
lineChart('/static/data/temp3.csv', 3);
//...

And, in the function (I'm guessing here, because you didn't paste the function declarations):

function lineChart(url, index){
    //all your previous code
    .style('stroke', function(){ return color2(index);})
    .attr('d', line);
};

Check this demo:

var svg = d3.select("body").append("svg").attr("width", 500).attr("height", 200);

var color2 = d3.scaleOrdinal().range(['#673ab7','#9c27b0','#e91e63','#f44336','#ff5722','#ff9800','#ffc107','#ffeb3b','#cddc39','#8bc34a','#4caf50','#009688'])
    .domain(d3.range(1,13));

function draw(dimention, index){
  svg.append("rect").attr("x", Math.random()*470)
  .attr("y", Math.random()*170).attr("width", dimention).attr("height", dimention)
  .attr("fill", function(d,i){ console.log("index is " + i); return color2(index)});
}
  
draw(30, 1);draw(10, 2);draw(25, 3);draw(20, 4);draw(5, 5);
draw(10, 6);draw(8, 7);draw(12, 8);draw(10, 9);draw(17, 10);
<script src="https://d3js.org/d3.v4.min.js"></script>