D3图表无法更新 - 选择的输入和退出属性都为空

时间:2016-10-04 23:29:31

标签: javascript json d3.js

我试图使用.json文件制作散点图。它将允许用户选择要显示的json文件中的哪组数据。所以我试图使用更新模式。

以下代码将进行第一次绘制,但每次调用selectGroup()(代码都在html文件中)时,都没有更新。 console.log(选择)每次都返回一个新数组,但该选择的enter和exit属性始终为空。 任何人都可以帮我看看吗?非常感谢!

var margin = {
    top: 30,
    right: 40,
    bottom: 30,
    left: 40
}
var width = 640 - margin.right - margin.left,
    height = 360 - margin.top - margin.bottom;
var dataGroup;
var groupNumDefault = "I";
var maxX, maxY;
var svg, xAxis, xScale, yAxis, yScale;



//select and read data by group
function init() {
    d3.json("data.json", function (d) {
        maxX = d3.max(d, function (d) {
            return d.x;
        });
        maxY = d3.max(d, function (d) {
            return d.y;
        });
        console.log(maxY);

        svg = d3.select("svg")
            .attr("id", "scatter_plot")
            .attr("width", 960)
            .attr("height", 500)
            .append("g")
            .attr("id", "drawing_area")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        //x-axis 
        xScale = d3.scale.linear().range([0, width]).domain([0, maxX]);
        xAxis = d3.svg.axis()
            .scale(xScale).orient("bottom").ticks(6);

        //y-axis
        yScale = d3.scale.linear().range([0, height]).domain([maxY, 0]);
        yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(6);

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

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

    });

    selectGroup(groupNumDefault);
}

//update data 
function selectGroup(groupNum) {
    d3.json("/data.json", function (d) {
        dataGroup = d.filter(function (el) {
            return el.group == groupNum;
        });
        console.log(dataGroup);
        drawChart(dataGroup);

    });
}


//drawing function
function drawChart(data) {
    var selection = d3.select("svg").selectAll("circle")
        .data(data);
    console.log(selection);

    selection.enter()
        .append("circle")
        .attr("class", "dots")
        .attr("cx", function (d) {
            console.log("updating!");
            return xScale(d.x);
        })
        .attr("cy", function (d) {
            return yScale(d.y);
        })
        .attr("r", function (d) {
            return 10;
        })
        .attr("fill", "red");

    selection.exit().remove();
}

init();

1 个答案:

答案 0 :(得分:2)

这里的问题有两个方面:

首先,您在data()调用中缺少关键函数意味着默认情况下数据与索引(数据数组中的位置)匹配,这意味着如果发送旧数据集和当前数据集,则不会进入和退出选择data()大小相同。相反,当d3与索引匹配时,大多数(可能全部)数据将被放入 update 选择中(旧数据集中的第一个数据=新数据集中的第一个数据,旧数据集中的第二个数据=第二个数据)在新的数据集等))

var selection = d3.select("svg").selectAll("circle")
        .data(data);

请参阅:https://bl.ocks.org/mbostock/3808221

基本上,您需要将数据调用调整为这样的(如果您的数据具有.id属性或其他任何可以唯一标识每个数据的内容)

var selection = d3.select("svg").selectAll("circle")
            .data(data, function(d) { return d.id; });

这将根据数据的实际内容生成enter()和exit()(和更新)选择,而不仅仅是它们的索引。

其次,并非第二轮的所有内容都保证在输入或退出选择中。有些数据可能只是现有数据的更新,而不是这些选择中的任何一种(在您的情况下,它可能每次都是全新的)。但是,考虑到上面描述的情况,它几乎可以保证您的大部分数据都将在更新选择中,其中一些是错误的。要显示更新,您需要更改这样的代码(我在这里假设d3 v3,显然它与v4略有不同)

selection.enter()
        .append("circle")
        .attr("class", "dots")
        .attr("r", function (d) {
            return 10;
        })
        .attr("fill", "red");

// this new bit is the update selection (which includes the just added enter selection
// now, the syntax is different in v4)
selection // v3 version
// .merge(selection)  // v4 version (remove semi-colon off preceding enter statement)
        .attr("cx", function (d) {
            console.log("updating!");
            return xScale(d.x);
        })
        .attr("cy", function (d) {
            return yScale(d.y);
        })

   selection.exit().remove();

这两个更改应该看到您的可视化工作正常,除非问题是第二次这样简单的空数据集,这也可以解释: - )