Reputation: 131
I have created a multiline chart from an array of objects with nested data, however the circles are only appended to 1 line. I am using react on the frontend and getting the data from a rest api, As shown in this image Example The lines are created and the tooltip on the circles works properly but only one line has circles appended.
Object.values(data).forEach(item => {
var valueline = d3
.line()
.x(function(d) {
return x(d.circuit);
})
.y(function(d) {
return y(+d.points);
});
var colorScale = d3
.scaleSequential(interpolateRainbow) //.scaleSequential(d3.interpolateRainbow)
.domain([1, 20]);
console.log(colorScale(1));
svg
.append("path")
.data([item.results])
.attr("class", "line")
.style("stroke", colorScale(item.constructor))
.attr("d", valueline);
var xScale = d3
.scaleLinear()
.domain([0, item.results.length-1]) // input
.range([0, width]); // output
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg
.selectAll(".dot")
.data(item.results)
.enter()
.append("circle") // Uses the enter().append() method
.attr("class", "dot")
.attr("r", 5) // Assign a class for styling
.attr("cx", function(d, i) {
return xScale(i);
})
.attr("cy", function(d, i) {
return y(d.points);
}).on("mouseover", function(d) {
let points = item.results.filter(xd => xd.circuit==d.circuit)[0].points
div.transition()
.duration(200)
.style("opacity", .9);
div .html(item.name + "<br/>" + points)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
Upvotes: 0
Views: 573
Reputation: 619
Try the changes below noting the use of an iterator to differentiate the class/selection of dots for each line. You could use something else like an attribute of the data e.g. name etc.
Also not i've moved the line and color scale functions out of your forEach
loop as they don't need to be declared multiple times. The same applies to your tooltip which could resused instead of adding multiple divs to the DOM.
var valueline = d3
.line()
.x(function(d) {
return x(d.circuit);
})
.y(function(d) {
return y(+d.points);
});
var colorScale = d3
.scaleSequential(interpolateRainbow) //.scaleSequential(d3.interpolateRainbow)
.domain([1, 20]);
console.log(colorScale(1));
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
Object.values(data).forEach((item,k) => {
svg
.append("path")
.data([item.results])
.attr("class", "line")
.style("stroke", colorScale(item.constructor))
.attr("d", valueline);
var xScale = d3
.scaleLinear()
.domain([0, item.results.length-1]) // input
.range([0, width]); // output
svg
.selectAll(".dot-"+k)
.data(item.results)
.enter()
.append("circle") // Uses the enter().append() method
.attr("class", "dot-"+k)
.attr("r", 5) // Assign a class for styling
.attr("cx", function(d, i) {
return xScale(i);
})
.attr("cy", function(d, i) {
return y(d.points);
}).on("mouseover", function(d) {
let points = item.results.filter(xd => xd.circuit==d.circuit)[0].points
div.transition()
.duration(200)
.style("opacity", .9);
div .html(item.name + "<br/>" + points)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
Upvotes: 2