I am working on a d3 pie chart with an input range element to dynamically generate values that should determine the pie chart.
If I add value for
var selectedYear
in app.js manually e.g. (var selectedYear = 1967
) the pie chart worksIf I add value for
var selectedYear
dynamically throughgetElementById
method, e.g.(var selectedYear = document.getElementById("sliderId").value
) a wrong value 100, which I guess is the standard max value for input range, is retrieved and so the pie chart does not get created.
What is my mistake here? I suspect it has to do with the dom.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pie Chart Exercise</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<svg
version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg" >
</svg>
<script src="https://d3js.org/d3.v4.js"></script>
<div id="sliderDiv">
<label id="label1" for="points">Choose a year:</label>
<input type="range" id="sliderId" name="slider" step="1" value='1967' >
</div>
<script src="birthData.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js
var width = 600,
height = 600;
var selectedYear = 1967; //parseInt(document.getElementById("sliderId").value); doe not work
var radius = Math.min(width, height) / 2;
var yearData = birthData.filter(d => d.year === selectedYear);
var yearDataBirths = yearData.map(d => {return d.births});
var rangeDataYears = birthData.map(d => {return d.year});
var minDataYear = d3.min(rangeDataYears);
var maxDataYear = d3.max(rangeDataYears);
function sliderInputCode(){
var sliderInput = document.getElementById("sliderId");
sliderInput.setAttribute('min',minDataYear);
sliderInput.setAttribute('max',maxDataYear);
var selectedYearV2 = parseInt(document.getElementById("sliderId").value);
};
sliderInputCode();
var colorScale = d3.scaleOrdinal()
.domain( yearDataBirths)
.range(d3.schemeCategory20);
var svg = d3.select('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform','translate(' width/2 ',' height/2 ')')
.classed('chart', true);
var pie = d3.pie();
var arc = d3.arc()
.innerRadius(150)
.outerRadius(radius);
var arcs = svg.selectAll('.arc')
.data(pie(yearDataBirths))
.enter()
.append('g')
.attr('class','arc')
.append('path')
.attr('fill', (d,i) => colorScale(i))
.attr('d', arc);
style.css
svg {
margin: 0 auto;
display: block;
}
.arc {
stroke: black;
}
#label1{
display:block;
}
#sliderDiv{
margin: 0 auto;
margin-top: 2em;
display: block;
text-align: center;
}
input[type="text"] {
display: block;
margin : 0 auto;
}
birthData.js ( I abbreviated the data here from 1967 to 1969 for shortness and oversightness. Original data goes from 1967 to 2014 )
var birthData = [
{
"year": 1967,
"month": "January",
"births": 31502
},
{
"year": 1967,
"month": "February",
"births": 26703
},
{
"year": 1967,
"month": "March",
"births": 28853
},
{
"year": 1967,
"month": "April",
"births": 26958
},
{
"year": 1967,
"month": "May",
"births": 28591
},
{
"year": 1967,
"month": "June",
"births": 29545
},
{
"year": 1967,
"month": "July",
"births": 30086
},
{
"year": 1967,
"month": "August",
"births": 30947
},
{
"year": 1967,
"month": "September",
"births": 32338
},
{
"year": 1967,
"month": "October",
"births": 32296
},
{
"year": 1967,
"month": "November",
"births": 30326
},
{
"year": 1967,
"month": "December",
"births": 28994
},
{
"year": 1968,
"month": "January",
"births": 30691
},
{
"year": 1968,
"month": "February",
"births": 27902
},
{
"year": 1968,
"month": "March",
"births": 29706
},
{
"year": 1968,
"month": "April",
"births": 28800
},
{
"year": 1968,
"month": "May",
"births": 28957
},
{
"year": 1968,
"month": "June",
"births": 28245
},
{
"year": 1968,
"month": "July",
"births": 29111
},
{
"year": 1968,
"month": "August",
"births": 29793
},
{
"year": 1968,
"month": "September",
"births": 31402
},
{
"year": 1968,
"month": "October",
"births": 31429
},
{
"year": 1968,
"month": "November",
"births": 29516
},
{
"year": 1968,
"month": "December",
"births": 28266
},
{
"year": 1969,
"month": "January",
"births": 436201
},
{
"year": 1969,
"month": "February",
"births": 401016
},
{
"year": 1969,
"month": "March",
"births": 439157
},
{
"year": 1969,
"month": "April",
"births": 419464
},
{
"year": 1969,
"month": "May",
"births": 430195
},
{
"year": 1969,
"month": "June",
"births": 425021
},
{
"year": 1969,
"month": "July",
"births": 455342
},
{
"year": 1969,
"month": "August",
"births": 454915
},
{
"year": 1969,
"month": "September",
"births": 451233
},
{
"year": 1969,
"month": "October",
"births": 448391
},
{
"year": 1969,
"month": "November",
"births": 424455
},
{
"year": 1969,
"month": "December",
"births": 445127
}]
CodePudding user response:
You need to set the max value for your input type=range, there is a default value set which is 100. If you set the value to your max value, it will work.
Now i have changed the arrangement of app.js :
var width = 600,
height = 600;
sliderInputCode();
var selectedYear = parseInt(document.getElementById("sliderId").value);
var radius = Math.min(width, height) / 2;
var yearData = birthData.filter(d => d.year === selectedYear);
var yearDataBirths = yearData.map(d => {return d.births});
function sliderInputCode(){
var rangeDataYears = birthData.map(d => {return d.year});
var minDataYear = d3.min(rangeDataYears);
var maxDataYear = d3.max(rangeDataYears);
var sliderInput = document.getElementById("sliderId");
sliderInput.setAttribute('min',minDataYear);
sliderInput.setAttribute('max',maxDataYear);
var selectedYearV2 = parseInt(document.getElementById("sliderId").value);
};
//sliderInputCode();
var colorScale = d3.scaleOrdinal()
.domain( yearDataBirths)
.range(d3.schemeCategory20);
var svg = d3.select('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform','translate(' width/2 ',' height/2 ')')
.classed('chart', true);
var pie = d3.pie();
var arc = d3.arc()
.innerRadius(150)
.outerRadius(radius);
var arcs = svg.selectAll('.arc')
.data(pie(yearDataBirths))
.enter()
.append('g')
.attr('class','arc')
.append('path')
.attr('fill', (d,i) => colorScale(i))
.attr('d', arc);
so now function sliderInputCode() will create input min and max values before var selectedYear = parseInt(document.getElementById("sliderId").value) will retrieve the input element value from the html. It now works as in the pie chart is created. But now moving the input slider does not get me other input element values which is should do to the codeline var selectedYear = parseInt(document.getElementById("sliderId").value);
Does anyone see the error here ? Thank you