简体   繁体   English

在d3中从单个折线图到多折线图的两个数据集之间的过渡

[英]transition between two datasets, from a single line chart to a multiline chart, in d3

I'm trying to build a chart that goes from 1 line to many lines. 我正在尝试构建从1条线到多条线的图表。 I have built the two charts separately, but am having trouble combining them. 我已经分别构建了两个图表,但是在合并它们时遇到了麻烦。 The idea is that I want to show the total of all fruit sold per year, and then show how much of each fruit is sold per year. 我的想法是,我要显示每年出售的所有水果的总数,然后显示每年出售的每种水果的数量。

This is the template I'm working from: http://bl.ocks.org/d3noob/a048edddbf83bff03a34 这是我正在使用的模板: http : //bl.ocks.org/d3noob/a048edddbf83bff03a34

In my code, the single line shows up fine. 在我的代码中,单行显示得很好。 When I click update, the axes update as they should, but the data doesn't. 当我单击更新时,轴将按其应有的方式进行更新,但数据不会更新。 Any help would be greatly appreciated. 任何帮助将不胜感激。

My code is in a plunker, here: https://plnkr.co/edit/dgwsGLIRbZ2qm7faEvSw?p=preview 我的代码在一个插件中,在这里: https ://plnkr.co/edit/dgwsGLIRbZ2qm7faEvSw?p = preview

The code is also below. 代码也在下面。

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
    body { font: 12px Arial;}
    path {
        stroke: #333;
        stroke-width: 2;
        fill: none;
    }
    .axis path,
    .axis line {
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
    }
    </style>
    <body>
    <div id="option">
      <input name="updateButton" id="updateData" type="button" value="Update" />
        <input name="revertButton" type="button" value="Revert" onclick="revertData()" />
    </div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>

    <script>

    var margin = {top: 30, right: 20, bottom: 30, left: 50},
        width = 800 - margin.left - margin.right,
        height = 470 - margin.top - margin.bottom;

    var x = d3.scaleLinear().range([0, width]);
    var y = d3.scaleLinear().range([height, 0]);

    var xAxis = d3.axisBottom().scale(x)
        .ticks(7)
        .tickFormat(d3.format("d"))

    var yAxis = d3.axisLeft().scale(y)
        .ticks(5);

    var valueline = d3.line()
        .x(function(d) { return x(d.Year); })
        .y(function(d) { return y(d.Count); });

    var svg = d3.select("body")
        .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
        .append("g")
            .attr("transform",
                  "translate(" + margin.left + "," + margin.top + ")");

    d3.csv("datab.csv", function(error, data2) {
      d3.csv("dataa.csv", function(error, data) {
        data.forEach(function(d) {
            d.Year = +d.Year;
            d.Count = +d.Count;
        });

        x.domain(d3.extent(data, function(d) { return d.Year; }));
        y.domain([0, d3.max(data, function(d) { return d.Count; })]);

        dataNest1 = d3.nest()
                .key(function(d) {return d.Type;})
                .entries(data);

        var result1 = dataNest1.filter(function(val,idx, arr){
              return $("." + val.key)
            })

      var calls = d3.select("svg").selectAll(".line")
        .data(result1, function(d){return d.key})

        var color1 = d3.scaleOrdinal().range(["#333",  "none", "none", "none", "none", "none"]);

      calls.enter().append("path")
          .attr("class", "line")
        .attr("stroke","#333")
        .attr("d", function(d){
          return valueline(d.values)
        })
        .attr("transform",
              "translate(" + margin.left + "," + margin.top + ")");

          svg.append("g")
              .attr("class", "x axis")
              .attr("transform", "translate(0," + height + ")")
              .call(xAxis);

          svg.append("g")
              .attr("class", "y axis")
              .call(yAxis);

            d3.select('#updateData').on('click',function(){
              updateData(data2)
            })
     });
    });

    function updateData(data2) {

            data2.forEach(function(d) {
                d.Year = +d.Year;
                d.Count = +d.Count;
            });

          dataNest = d3.nest()
                  .key(function(d) {return d.Descriptor;})
                  .entries(data2);

            var result = dataNest.filter(function(val,idx, arr){
                      return $("." + val.key)
                    })

            x.domain(d3.extent(data2, function(d) { return d.Year; }));
            y.domain([0, d3.max(data2, function(d) { return d.Count; })]);

        var svg = d3.select("body").transition();
        svg.selectAll('.circle').duration(0).remove()

        d3.select("svg").selectAll(".line")
        .data(result, function(d){return d.key})

        d3.select("svg").selectAll("path.line")
            .transition()
            .duration(700)
          .style("stroke", "#333")
                .attr("d", function(d){
                    return valueline(d.values)
                });

            // svg.select(".line")   // change the line
            //     .duration(750)
            //     .attr("d", valueline(rats));

            svg.select(".x.axis")
                .transition()
                .duration(750)
                .call(xAxis);
            svg.select(".y.axis")
                .duration(750)
                .call(yAxis);

    }

    function revertData() {

        // Get the data again
        d3.csv("totalsbyyear.csv", function(error, data) {
            data.forEach(function(d) {
                d.Year = +d.Year;
                d.Count = +d.Count;
            });

            // Scale the range of the data again
            x.domain(d3.extent(data, function(d) { return d.Year; }));
            y.domain([0, d3.max(data, function(d) { return d.Count; })]);

        // Select the section we want to apply our changes to
        var svg = d3.select("body").transition();

        // Make the changes
            svg.select(".line")   // change the line
                .duration(750)
                .attr("d", valueline(data));
            svg.select(".x.axis") // change the x axis
                .duration(750)
                .call(xAxis);
            svg.select(".y.axis") // change the y axis
                .duration(750)
                .call(yAxis);

        });
    }

    </script>
    </body>

There are a few problems here. 这里有一些问题。 The first one being that your datasets are very different and I don't see anywhere in the code to compensate for there being multiple different fruit in the same year. 第一个是您的数据集非常不同,我看不到代码中的任何地方来补偿同一年中存在多个不同的结果。 This is something you will need to address either by modifying your csv file or in your updateData function to extract just a single fruit. 您需要通过修改csv文件或在updateData函数中仅提取单个水果来解决此问题。

I have made some changes to your plunker that will allow the updateFunction to work but without fixing the input data it won't really matter. 我已经对您的监听器进行了一些更改,这些更新将允许updateFunction起作用,但是如果不修复输入数据,那将不会有什么实质性的影响。

https://plnkr.co/edit/DSg09NWPrBADLLbcL5cx?p=preview https://plnkr.co/edit/DSg09NWPrBADLLbcL5cx?p=preview

The main thing that needed to be fixed was 需要解决的主要问题是

d3.select("svg").selectAll("path.line")
  .data(result, function(d){return d.key})
  .transition()
  .duration(700)
  .style("stroke", "#337")
     .attr("d", function(d){
     return valueline(result)
   });

And putting the d3.csv on datab.csv call in the updateData function instead of wrapping it around the main table creation function. 并将d3.csv放在updateData函数中的datab.csv调用上,而不是将其包装在主表创建函数周围。

I was probably being unclear in my question asking. 我的问题可能不清楚。 I figured out what I needed to do to make it work as intended. 我想出了要使其按预期工作所需要做的事情。 Code here: 代码在这里:

https://plnkr.co/edit/YrABkbc8l9oeT1ywMspy?p=preview https://plnkr.co/edit/YrABkbc8l9oeT1ywMspy?p=preview

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
    body { font: 12px Arial;}
    path {
        stroke: #333;
        stroke-width: 2;
        fill: none;
    }
    .axis path,
    .axis line {
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
    }
    </style>
    <body>

    <div id="option">
      <input name="updateButton" id="updateData" type="button" value="Update" />
        <input name="revertButton" type="button" value="Revert" onclick="revertData()" />
    </div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>

    <script>

    var margin = {top: 30, right: 200, bottom: 30, left: 50},
        width = 850 - margin.left - margin.right,
        height = 470 - margin.top - margin.bottom;

    var x = d3.scaleLinear().range([0, width]);
    var y = d3.scaleLinear().range([height, 0]);

    var xAxis = d3.axisBottom().scale(x)
        .ticks(7)
        .tickFormat(d3.format("d"))

    var yAxis = d3.axisLeft().scale(y)
        .ticks(5);

    var valueline = d3.line()
        .x(function(d) { return x(d.Year); })
        .y(function(d) { return y(d.Count); });

    var svg = d3.select("body")
        .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
        .append("g")
            .attr("transform",
                  "translate(" + margin.left + "," + margin.top + ")");

    d3.csv("datab.csv", function(error, data2) {
      d3.csv("dataa.csv", function(error, data) {
        data.forEach(function(d) {
            d.Year = +d.Year;
            d.Count = +d.Count;
        });

        x.domain(d3.extent(data, function(d) { return d.Year; }));
        y.domain([0, d3.max(data, function(d) { return d.Count; })]);

        svg.append("path")
            .attr("class", "line")
            .attr("d", valueline(data));

        svg.append("text")
            .attr("transform", function(d) { return "translate(" + x(2017) + "," + y(35074) + ")"; })
            .attr("x", 3)
            .attr("dy", "0.35em")
            .attr('class','toplinetext')
            .style("font", "10px sans-serif")
            .text(function(d) { return "All"; });

        circles = svg.selectAll("circle")
              .data(data)
              .enter()
              .append("circle")
              .attr('class','circle')
              .attr('cx',function(d){ return x(d.Year)})
              .attr('cy',function(d){ return y(d.Count)})
              .attr('r',3)

          svg.append("g")
              .attr("class", "x axis")
              .attr("transform", "translate(0," + height + ")")
              .call(xAxis);

          svg.append("g")
              .attr("class", "y axis")
              .call(yAxis);

          svg.exit().remove();

            d3.select('#updateData').on('click',function(){
              updateData(data2)
            })
     });
    });

    function updateData(data2) {

          data2.forEach(function(d) {
                d.Year = +d.Year;
                d.Count = +d.Count;
            });

          var notapples = data2.filter(function(d){return d.Descriptor == "Peach" || d.Descriptor == "Pear" || d.Descriptor == "Plum" || d.Descriptor == "Banana"})

          dataNest = d3.nest()
                  .key(function(d) {return d.Descriptor;})
                  .entries(notapples);

            var result = dataNest.filter(function(val,idx, arr){
                      return $("." + val.key)
                    })

         $('.toplinetext').text('Apples');


            x.domain(d3.extent(data2, function(d) { return d.Year; }));
            y.domain([0, d3.max(data2, function(d) { return d.Count; })]);

        var svg = d3.select("body").transition();
        svg.selectAll('.circle').duration(0).remove()

        var typeOfCall = d3.select("svg").selectAll(".dline")
          .data(result, function(d){return d.key})
          .enter().append("g")
          .attr("class", function(d){return "type " + d.key})
          .attr("transform",
                "translate(" + margin.left + "," + margin.top + ")");

          var color2 = d3.scaleOrdinal().range(["#ff0000",  "#333", "#333", "#333", "#333", "#333"]);

        typeOfCall.append("path")
          .attr("height", 0)
            .transition()
            .duration(700)
            .attr("class", "line")
          .style("stroke", function(d,i) { return color2(d.key); })
                .attr("d", function(d){
                    return valueline(d.values)
                });

          typeOfCall.append("text")
             .datum(function(d) { return {id: d.Descriptor, value: d.values[d.values.length - 1]}; })
              .attr("transform", function(d) { return "translate(" + x(d.value.Year) + "," + y(d.value.Count) + ")"; })
              .attr("x", 3)
              .attr("dy", "0.35em")
              .style("font", "10px sans-serif")
              .text(function(d) { return d.value.Descriptor; });

            typeOfCall.exit().remove();

            apples = data2.filter(function(d){return d.Descriptor == "Apple"})

            svg.select(".line")
                .duration(750)
                .attr("d", valueline(apples));

            svg.select(".x.axis")
                .transition()
                .duration(750)
                .call(xAxis);
            svg.select(".y.axis")
                .duration(750)
                .call(yAxis);
    }

    function revertData() {

        // Get the data again
        d3.csv("totalsbyyear.csv", function(error, data) {
            data.forEach(function(d) {
                d.Year = +d.Year;
                d.Count = +d.Count;
            });

          $('.toplinetext').text('All');
          $('.Peach,.Pear,.Banana,.Plum').remove();
            // Scale the range of the data again
            x.domain(d3.extent(data, function(d) { return d.Year; }));
            y.domain([0, d3.max(data, function(d) { return d.Count; })]);

        // Select the section we want to apply our changes to
        var svg = d3.select("body").transition();

        // Make the changes
            svg.select(".line")   // change the line
                .duration(750)
                .attr("d", valueline(data));
            svg.select(".x.axis") // change the x axis
                .duration(750)
                .call(xAxis);
            svg.select(".y.axis") // change the y axis
                .duration(750)
                .call(yAxis);

        });
    }

    </script>
    </body>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM