D3.js graph display error

I am trying to run a data visualization application, I am using D3.js, my code works, but when I change the selected option, the graph changes but goes down and it resets with every change. I don't know 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 is a screenshot of my problem:

first try enter image description here

second try enter image description here

and here is an excerpt 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
},

      

+3


source to share


1 answer


Don't add a new SVG every time you select an option.

So instead of:

var myChart = d3.select('#chart').append('svg')
    .attr('width', width + margin.right + margin.left)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    //etc...

      

Just do:



var myChart = svg.append('g')
    //etc...

      

Here is a plunker with this change just using the little JSON sample you provided: https://plnkr.co/edit/PMnNI4hoBz3Q2k5fQTp5?p=preview

PS: As I said in my comment , this code now has a lot of problems, the main one being that you erase everything inside the SVG just to re-draw it, and secondly, the fact that you load the same JSON every time when you select an option. That being said, you should revisit the main refactoring in this code. Please be aware that here I am only answering the problem pointed out in your question.

+1


source







All Articles