Q-man
Q-man

Reputation: 127

D3.js is it possible to draw circles on each point using nested data?

I have a graph that i need to render that has multiple lines. There are individual points and a line that runs through them. On each point, i want to draw a circle. For the lines, i am using d3.nest() function that converts a csv file into a data array which is than nested using a key that i provide, and to draw the circles on each point, i am just using the raw 'data' array. What i want to know is, is there a way to plot circles on points using the NESTED array as an input? or do i HAVE to use the raw data file to draw circles on each point? enter image description here

Upvotes: 0

Views: 1830

Answers (1)

Ruben Helsloot
Ruben Helsloot

Reputation: 13139

Of course that's possible. If you create one "group" per group in your nested data set, then you can draw one line for each of those groups, and also one circle for each of the points in each of the groups. Take a look at the following:

const fruits = ["Apples", "Oranges", "Bananas"];
const colors = ["red", "orange", "yellowgreen"];
const rawData = fruits.map((obj, f) => {
  let v = 1;
  return d3.range(30).map(i => ({
    fruit: f,
    index: i,
    value: v *= (0.95 + Math.random() * 0.1)
  }));
}).flat();

const nestedData = d3.nest()
  .key(d => d.fruit)
  .entries(rawData);

const width = 800,
  height = 200;

const x = d3.scaleLinear()
  .domain([0, 29])
  .range([0, width]);

const y = d3.scaleLinear()
  .domain(d3.extent(rawData, d => d.value))
  .range([height, 0])
  .nice();

const color = d3.scaleOrdinal()
  .domain(fruits)
  .range(colors);

const line = d3.line()
  .x(d => x(d.index))
  .y(d => y(d.value));

const svg = d3.select("svg")
  .attr("width", width)
  .attr("height", height);

const lineGroup = svg.selectAll(".line-group")
  .data(nestedData)
  .enter()
  .append("g")
  .attr("class", "line-group");

lineGroup.append("path")
  .datum(d => d.values)
  .attr("class", "line")
  .attr("stroke", d => color(d[0].fruit))
  .attr("d", line);

lineGroup.selectAll("circle")
  .data(d => d.values)
  .enter()
  .append("circle")
  .attr("class", "dot")
  .attr("stroke", d => color(d.fruit))
  .attr("r", 5)
  .attr("cx", d => x(d.index))
  .attr("cy", d => y(d.value));
.line {
  fill: none;
  stroke-width: 2px;
}

.dot {
  stroke-width: 2px;
  fill: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

Upvotes: 2

Related Questions