D3.js 进入、更新、退出问题

D3.js Enter, Update, Exit issue

我有一个相对简单的条形图。我想在具有 .on("click") 事件的数据集之间 .transition()。我得到的是完全重绘附加到 DOM id 的附加图表,而不是删除原始图表并转换或替换它。我想我误解了如何正确 .remove().

d3.json("data/cfilt-steps.json", function(d) {

    d.forEach(function(d) { 
        parseDate = d3.time.format("%Y-%m-%d").parse;
        d.date = parseDate(d.date); d.value = +d.value;
        });

    margin      = {top:5, right:5, bottom: 40, left:5},
    height      = 150 - margin.top - margin.bottom, 
    width       = 500 - margin.left - margin.right, 
    barPadding  = 1;

    steps    = crossfilter(d), 
    monthdim = steps.dimension(function(d){ thisDate = new Date(d.date); return thisDate.getMonth(); }),
    monthgrp = monthdim.group().reduceSum(function(d){ return d.value; });
    daydim   = steps.dimension(function(d){ thisDate = new Date(d.date); return thisDate.getDay(); }),
    daygrp   = daydim.group().reduceSum( function(d) { return d.value; });

    stepColor = d3.scale.threshold()
            .domain([100, 150, 200, 250, 300, 400, 500])
            .range(["#E3E3E3", "#D0DFD2", "#C3DABC", "#BDCB87", "#CAB44E", "#E29517", "#FF6600"]);

    d3.select("#monthly-steps-previous-selector")
            .on("click", function(d) {reDraw(monthgrp.all()) })   

    d3.select("#monthly-steps-next-selector")
            .on("click", function(d) {reDraw(daygrp.all()); })    

    function reDraw(data) {

        xScale = d3.scale.ordinal().domain(monthdim).range(0, width);

        yScale = d3.scale.linear().domain([0, d3.max(data, function(d){return d.value;})]).range([height, 5]);

        var stepbars = d3.select("#steps-bar")
            .append("svg:svg")
            .attr("width", width)
            .attr("height", height)

        stepbars.selectAll("rect")
            .data(data)
            .enter().append("rect")
            .attr("x", function(d,i){ return i * width/data.length; })
            .attr("y", function(d){ return yScale(d.value); })
            .attr("width", width/data.length - barPadding)
            .attr("height", function(d) { return height-yScale(d.value); })
            .attr("fill", function(d){ return stepColor(d.value/2000); })

    } 

reDraw(monthgrp.all());

});

谁能告诉我这应该是什么样子,或者告诉我哪里做错了?

你的 reDraw 函数附加了 svg,这意味着每次你调用 redraw 时都会附加一个新的 svg,因此是双图表。我建议把行

var stepbars = d3.select("#steps-bar")
        .append("svg:svg")
        .attr("width", width)
        .attr("height", height)

在重绘函数之上。

此外,您的重绘函数没有调用remove。我会做类似的事情:

//Select and bind to data
var selection = stepbars.selectAll("rect")
        .data(data);

//Enter and create new rectangles
selection.enter()
        .append("rect");

//Update all rectangles
selection.attr("x", function(d,i){ return i * width/data.length; })
        .attr("y", function(d){ return yScale(d.value); })
        .attr("width", width/data.length - barPadding)
        .attr("height", function(d) { return height-yScale(d.value); })
        .attr("fill", function(d){ return stepColor(d.value/2000); });

//Remove unused rectangles
selection.exit().remove();