Home > OS >  dot (symbol) color on d3.js multiline chart
dot (symbol) color on d3.js multiline chart

Time:09-29

I am trying to replicate this example of a multiline chart with dots. My data is basically the same, where I have an object with name and values in the first level, and then a couple of values in the second level inside values. For the most part, my code works, but for some reason, the j index in the anonymous function for the fill returns an array of repeated circle instead of returning the parent of the current element. I believe this may have something to do with the way I created the svg and selected the elements, but I can't figure it out. Below is an excerpt of my code that shows how I created the svg, the line path and the circles.

var svgb = d3.select("body")
       .append("svg")
       .attr("id","svg-b")
       .attr("width", width)
       .attr("height", height)

var gameb = svgb.selectAll(".gameb")
                .data(games)
                .enter()
                .append("g")
                .attr("class", "gameb");

gameb.append("path")
     .attr("class", "line")
     .attr("d", function(d) {return line_count(d.values); })
     .style("stroke", function(d) { return color(d.name); })
     .style("fill", "none");

gameb.selectAll("circle")
     .data(function(d) {return d.values;})
     .enter()
     .append("circle")
     .attr("cx", function(d) {return x(d.date);})
     .attr("cy", function(d) {return y_count(d.count);})
     .attr("r", 3)
     .style("fill", function(d,i,j) {console.log(j)
                                return color(games[j].name);});

CodePudding user response:

j (or more accurately, the third parameter) will always be the nodes in the selection (the array of circles here), not the parent. If you want the parent datum you can use:

 .attr("fill", function() { 
   let parent = this.parentNode;
   let datum = d3.select(parent).datum();
   return color(datum.name);
  })

Note that using ()=> instead of function() will change the this context and the above will not work.

However, rather than coloring each circle independently, you could use a or the parent g to color the circles too:

gameb.append("g")
     .style("fill", function(d) { return color(d.name); })
     .selectAll("circle")
     .data(function(d) {return d.values;})
     .enter()
     .append("circle")
     .attr("cx", function(d) {return x(d.date);})
     .attr("cy", function(d) {return y_count(d.count);})
     .attr("r", 3);

Here we add an intermediate g (though we could use the original parent with a few additional modifications), apply a fill color to it, and then the parent g will color the children circles for us. The datum is passed on to this new g behind the scenes.

  • Related