I am trying to plot a bubble chart that also lets you display change in data over time using a range slider. This would require "scrolling" through an array and update the x,y and r values of the bubbles accordingly. I was able to setup the range slider and plot the basic chart but I have no idea how I can update the values with the slider. Everything I found online until now just used the value of the slider as an input for the data.
The data structure i thought would make sense would look like this:
let data = [
{
name: 'Entry1',
year: [2000, 2001, 2002, 2003, 2004, 2005],
radius: [0, 0, 20, 30, 40, 60],
xVal: [0, 0, 40, 40, 50, 30],
yVal: [0, 0, 20, 40, 10, 70]},
{
name: 'Entry2',
year: [2000, 2001, 2002, 2003, 2004, 2005],
radius: [0, 0, 0, 0, 20, 15],
xVal: [0, 0, 0, 0, 15, 30],
yVal: [0, 0, 0, 0, 20, 50]},
{
name: 'Entry3',
year: [2000, 2001, 2002, 2003, 2004, 2005],
radius: [10, 20, 30, 40, 30, 10],
xVal: [5, 20, 20, 50, 40, 20],
yVal: [10, 30, 20, 80, 40, 20]},
];
It would be great if someone could point me in the right direction here :) Thanks guys!
Here is the code I have right now (I removed the arrays to make it work) https://jsfiddle.net/qgesxf1k/11/
CodePudding user response:
I solved the problem myself but wanted to leave the question up if anyone has a similar issue.
//The Data
let data = [
{ name: 'Entry1',radius: [30, 35, 40, 45, 50], xVal: [.20, .25, .30, .35, .40], yVal: [.20, .25, .30, .35, .40]},
{ name: 'Entry2',radius: [10, 15, 20, 25, 30], xVal: [.60, .65, .70, .75, .80], yVal: [.60, .65, .70, .75, .80]},
];
//Plot SVG
const width = 600;
const height = 600;
const margin = { top: 20, right: 20, bottom: 20, left: 20 };
const svg = d3.select('#content').append('svg').attr('viewBox', [0, 0, width, height]).attr('preserveAspectRatio', 'xMidYMid meet');
//Build Axis
const xScale = d3.scaleLinear().domain([0, 1]).range([margin.left, width - margin.right]);
const yScale = d3.scaleLinear().domain([1, 0]).range([margin.top, height - margin.bottom]);
const xAxis = d3.axisBottom(xScale).ticks(1);
const yAxis = d3.axisLeft(yScale).ticks(1);
const xAxisGroup = svg.append('g').attr("transform", "translate(0," (height - margin.top) ")").call(xAxis);
const yAxisGroup = svg.append('g').attr("transform", "translate(" (margin.right) ",0)").call(yAxis);
//Load the initial Data and set the index of the array to 0
const bubbles = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', d => xScale(d.xVal[0]))
.attr('cy', d => yScale(d.yVal[0]))
.attr('r', d => d.radius[0])
//Update when slider input changes --> HTML oninput="updateData();"
function updateData() {
//get the slider value
let i = document.getElementById('timeSlider').value;
d3.select('svg')
.selectAll('circle')
//call the data
.data(data)
//slide trough the index of the array and return the corresponding value
.attr('cx', d => xScale(d.xVal[i]))
.attr('cy', d => yScale(d.yVal[i]))
.attr('r', d => d.radius[i])
}
<script src="https://d3js.org/d3.v7.min.js"></script>
<div id="content"></div>
<input id="timeSlider" type="range" value="0" min="0" max="4" oninput="updateData();">