D3如何在从下拉菜单中选择新数据后更新图表

时间:2017-08-08 23:14:40

标签: d3.js

我在D3中建立瀑布图。当页面加载时,它将呈现默认页面,但用户可以选择不同的页面 '公司'和'年'从下拉菜单中。我能够创建我想要的图表。但是,当我选择任何不同的公司或年份时, D3会在现有的基础上添加另一个图表而不是替换它,因为我会从HTML中定位特定的div / svg。 如何使用D3使用新数据更新图表而是添加另一个?如果我可以通过过渡进行图表条的移动,那将是非常棒的。

HTML是一个简单的svg:

<svg class="chart"></svg>

这是创建在Ajax调用成功时调用的图表的函数:

function waterfallChart (dataset) {

            var data = [];

            for (var key in dataset[0]) {
              data.push({
                name: key,
                value: dataset[0][key]
              })
            }

        var margin = {top: 20, right: 30, bottom: 30, left: 40},        
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom,
            padding = 0.3;

    var x = d3.scaleBand()
            .domain(data.map(function(d) {
                return d.name
                }))
            .range([0, width])
            .padding(padding);

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

    var xAxis = d3.axisBottom(x)


    var yAxis = d3.axisLeft(y)
        .tickFormat(function(d) {
            return dollarFormatter(d);
        });

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

        var cumulative = 0;
        for (var i = 0; i < data.length; i++) {
            data[i].start = cumulative;
            cumulative += data[i].value;
            data[i].end = cumulative;

            data[i].class = (data[i].value >= 0) ? 'positive' : 'negative'
        }
        data.push({
            name: 'Total',
            end: cumulative,
            start: 0,
            class: 'total'
        });

        x.domain(data.map(function(d) {
            return d.name;
        }));
        y.domain([0, d3.max(data, function(d) {
            return d.end;
        })]);

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

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

        var bar = chart.selectAll(".bar")
            .data(data)
            .enter().append("g")
            .attr("class", function(d) {
                return "bar " + d.class
            })
            .attr("transform", function(d) {
                return "translate(" + x(d.name) + ",0)";
            });

        bar.append("rect")
            .attr("y", function(d) {
                return y(Math.max(d.start, d.end));
            })
            .attr("height", function(d) {
                return Math.abs(y(d.start) - y(d.end));
            })
            .attr("width", x.bandwidth());

        bar.append("text")
            .attr("x", x.bandwidth() / 2)
            .attr("y", function(d) {
                return y(d.end) + 5;
            })
            .attr("dy", function(d) {
                return ((d.class == 'negative') ? '-' : '') + ".75em"
            })
            .text(function(d) {
                return dollarFormatter(d.end - d.start);
            });

        bar.filter(function(d) {
                return d.class != "total"
            }).append("line")
            .attr("class", "connector")
            .attr("x1", x.bandwidth() + 5)
            .attr("y1", function(d) {
                return y(d.end)
            })
            .attr("x2", x.bandwidth() / (1 - padding) - 5)
            .attr("y2", function(d) {
                return y(d.end)
            })

            function dollarFormatter(n) {
                  n = Math.round(n);
                  var result = n;
                  if (Math.abs(n) > 1000) {
                    result = Math.round(n/1000) + 'B';
                  }
                  return '$ ' + result;
                }
        }

以下是我有事件监听器的代码,在选择时它将运行上述函数:

$("#airline-selected, #year-selected").change(function chartsData(event) {
            event.preventDefault();
            var airlineSelected = $('#airline-selected').find(":selected").val();
            var yearSelected = $('#year-selected').find(":selected").val();

            $.ajax({
                url: "{% url 'airline_specific_filtered' %}",
                method: 'GET',
                data : {
                    airline_category: airlineSelected,
                    year_category: yearSelected
                        },
                success: function(dataset){
                        waterfallChart(dataset)
         },
                error: function(error_data){
                console.log("error")
                console.log(error_data)
         }
            })
        });

0 个答案:

没有答案