I'm trying to run an application for data visualization, I'm using D3.js, my code works but when I change the selected option, the graph change but go down and it goes down every change. I have no idea where the problem is.
That's my code :
<!DOCTYPE html>
<html>
<head>
<title> Graphique </title>
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
</head>
<body>
<FORM>
<SELECT id="Nb" size="1" onchange="Changement()">
<option>Selection</option>
<option>NbCopie</option>
<option>NbTache</option>
<option>NbCopieBW</option>
<option>NbCopieCouleur</option>
<option>MtTotal</option>
</SELECT>
</FORM>
<div id="chart"></div>
<svg width="960" height="500"></svg>
<script>
function Changement() {
d3.selectAll("svg > *").remove();
d3.json("Data.json", function(error, data) {
var Nb = data.map(function(d) {
var x = document.getElementById('Nb');
var i = x.selectedIndex;
var text = x.options[i].text;
if (text == "NbCopie")
return d.NbCopie;
else if (text == "NbTache")
return d.NbTache;
else if (text == "NbCopieBW")
return d.NbCopieBW;
else if (text == " NbCopieCouleur")
return d.NbCopieCouleur;
else if (text == "MtTotal")
return d.MtTotal;
});
var maxNb = d3.max(Nb);
var svg = d3.select("svg"),
margin = {
top: 30,
right: 30,
bottom: 40,
left: 50
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var animateDuration = 700;
var animateDelay = 30;
var tooltip = d3.select('body').append('div')
.style('position', 'absolute')
.style('background', '#f4f4f4')
.style('padding', '5 15px')
.style('border', '1px #333 solid')
.style('border-raduis', '5px')
.style('opacity', '0')
var yScale = d3.scaleLinear()
.domain([0, maxNb])
.range([0, height])
var xScale = d3.scaleBand()
.domain(d3.range(0, Nb.length))
.range([0, width])
var colors = d3.scaleLinear()
.domain([0, Nb.length])
.range(['#0080FF', '#FF3333'])
var myChart = d3.select('#chart').append('svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.style('background', '#f4f4f4')
.selectAll('rect')
.data(Nb)
.enter().append('rect')
.style('fill', function(d, i) {
return colors(i);
})
.attr('width', xScale.bandwidth())
.attr('x', function(d, i) {
return xScale(i)
})
.attr('height', 0)
.attr('y', height)
.on('mouseover', function(d) {
tooltip.transition()
.style('opacity', 1)
tooltip.html(d)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY + 'px'))
d3.select(this).style('opacity', 0.5)
})
.on('mouseout', function(d) {
tooltip.transition()
.style('opacity', 0)
d3.select(this).style('opacity', 1)
})
myChart.transition()
.attr('height', function(d) {
return yScale(d);
})
.attr('y', function(d) {
return height - yScale(d);
})
.duration(animateDuration)
.delay(function(d, i) {
return i * animateDelay
})
.duration(1000)
.ease(d3.easeElastic)
var vScale = d3.scaleLinear()
.domain([0, maxNb])
.range([height, 0])
var vAxis = d3.axisLeft()
.scale(vScale)
.ticks(5)
.tickPadding(5)
var vGuide = d3.select('svg')
.append('g')
vAxis(vGuide)
vGuide.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
vGuide.selectAll('path')
.style('fill', 'none')
.style('stroke', '#000')
vGuide.selectAll('line')
.style('stroke', '#000')
var hScale = d3.scaleTime()
.domain(d3.extent(data, function(d) {
var parseDate = d3.timeParse("%Y%m%d");
Date_Id = parseDate(d.Date_Id);
return Date_Id;
}))
.range([0, width - 150])
var hAxis = d3.axisBottom()
.scale(hScale)
.ticks(d3.timeMonth)
var hGuide = d3.select('svg')
.append('g')
.attr("class", "axis axis--x")
.attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")
.call(hAxis);
});
};
</script>
And here a screenshot of my problem:
first attempt enter image description here
second attempt enter image description here
and here is an extract of my JSON file
[{
"ConsoPhot_Id": "10148",
"idLotImport": 390,
"Date_Id": 20170201,
"Orga_Id": "203938",
"NbTache": 153,
"NbCopie": 798,
"NbCopieBW": 488,
"NbCopieCouleur": 310,
"MtTotal": 13.69
},
{
"ConsoPhot_Id": "10602",
"idLotImport": 391,
"Date_Id": 20161201,
"Orga_Id": "203938",
"NbTache": 153,
"NbCopie": 909,
"NbCopieBW": 779,
"NbCopieCouleur": 130,
"MtTotal": 7.93
},
{
"ConsoPhot_Id": "10905",
"idLotImport": 392,
"Date_Id": 20161101,
"Orga_Id": "203938",
"NbTache": 115,
"NbCopie": 515,
"NbCopieBW": 409,
"NbCopieCouleur": 106,
"MtTotal": 5.6
},
d3.jsonoutsideChangement, not the other way around (you don't need to load/parse the data every time you choose an option), and move most of the code outsideChangement, leaving there only the small parts of the code that change the scales and the bars.