Gerle Batde
Gerle Batde

Reputation: 193

Adding color dynamically to a multiple line chart but it is not working in d3.js

I have created this curve line chart and I filled by purple color only. Then I decided to add color range and I used color scaling method is Category10 but it is not working. I am new to D3.js and it has been my headache for the past week.

enter image description here

In order to make it look more presentable, I need to add colors and I did tried to add this way by using .style attribute but

function buildLine(data){

        var xScale=d3.scale.linear()
                            .domain([0,d3.max(data,function(d){return d.spend;})])
                            .range([0, w]);

        var yScale=d3.scale.linear()
                            .domain([0,d3.max(data,function(d){return d.alpha;})])
                            .range([h/2, 0]);



        var yAxisGen=d3.svg.axis().scale(yScale).orient("left");                 
        var xAxisGen=d3.svg.axis().scale(xScale).orient("bottom");

        var svg=d3.select("body").append("svg").attr({width:w,height:h});

        var yAxis= svg.append("g")
                      .call(yAxisGen)
                      .attr("class","axis")
                      .attr("transform", "translate(50, " +10 +")");
        var xAxisTranslate = h/2 + 10;    
        var xAxis= svg.append("g")
                      .call(xAxisGen)
                      .attr("class","axis")
                      .attr("transform", "translate(50, " + xAxisTranslate  +")");

Adding color function here

        var color=d3.scale.category10               
        var lineFun = d3.svg.line()
                  .x(function (d) { return xScale(d.x); })
                  .y(function (d) { return yScale(d.y); })
                  .interpolate("basis");  

Here I tried to add it dynamically. '.style does not work. WHy?'

   var viz = svg.selectAll("path")
              .data(data)
              .enter()
              .append("path")
              .attr({
                d: function(d) {
                  return lineFun(d.arr)
                },
                "stroke": "purple",
                "stroke-width": 2,
                "fill": "none",
                "class":"line"
              })
              .style("stroke",function(){
                  return d.color=color(d.arr);
              })
              .attr("transform", "translate(48, " + 10 +")")
              ;    




}

      d3.json("sample-data.json",function(error,data){

                //check the file loaded properly
                if (error) {  //is there an error?
                    console.log(error);  //if so, log it to the console
                } else {      //If not we're golden!
                      //Now show me the money!
                    ds=data; //put the data in the global var
                }
            data.forEach(function(jsonData){
                 var lineData = d3.range(0, jsonData.spend, 100)
                    .map(x => [x, (jsonData.alpha * (1 - Math.pow(2.71828, (-jsonData.beta * x))))] );
                       /*  console.log("this is the data:",lineData);*/
                    //i think line date returns an array with each item in it also an array of 2 items
                    var arr = [];
                    for (var i = 0; i < lineData.length; i++) {
                        arr.push({
                           x: lineData[i][0],  
                           y: lineData[i][1]
                        });
                    }
                    jsonData.arr = arr;
                   console.log(jsonData);
            });

           buildLine(data);
      });

Upvotes: 1

Views: 1189

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

These are the problems:

  1. You have to call the scale function:

    var color=d3.scale.category10()
    //parentheses here ----------^
    
  2. You cannot use the argument d if you don't set the anonymous function parameter:

    .style("stroke",function(d){
        //parameter here-----^
        return d.color=color(d.arr);
    })
    
  3. scale.category10() works on a "first come, first served" basis. You just need the index:

    .style("stroke",function(d,i){
        return d.color=color(i);
    });
    

Here is a demo showing how to use that scale:

var color = d3.scale.category10();
var divs = d3.select("body").selectAll(null)
  .data(d3.range(10))
  .enter()
  .append("div")
  .style("background-color", function(d, i) {
    return color(i)
  })
div {
  width: 20px;
  height: 20px;
  display: inline-block;
  margin: 2px;
}
<script src="https://d3js.org/d3.v3.min.js"></script>

Upvotes: 2

Related Questions