d3.js如何仅加载部分数据/同步数据

3
我有很多数据,我用堆积条形图来绘制。我的测试数据大约有500k个JSON对象(=50k行,每行有10个堆叠的部分)。
我的问题是我不知道如何只加载部分数据。它在浏览器中显示,因此宽度大约为1200到1920像素。我使用一个比例尺来计算线的大小。但是,如果我将窗口宽度设置为比数据大小小的值,d3.js会将每条线的宽度计算为0,这意味着什么都没有显示。因此,我必须设置一个50k的宽度来显示所有内容,但这有点不太实用-而且它让浏览器崩溃,只有当我使用大约10k的数据然后设置10k像素的宽度时才能工作。第二件事是它需要非常长的时间(5秒)才能渲染。
1.) 如何将数据显示在宽度为1920的窗口中,并在移动箭头键或概览图时加载其他数据?
2.) 如何同步数据?例如:如果我有一个长滑块,这个滑块应该确定我感兴趣的数据。因此,范围从0到50k,然后我滑动它并在~4000处。我想跳转到那个位置的图表中。
   dataset = data;
    var stack = d3.layout.stack();
    stack(dataset);

    var x= d3.scale.ordinal()
            .domain(d3.range(dataset[0].length))
            .rangeRoundBands([0, w]);

    var y= d3.scale.linear()
            .domain([0, 1])
            .range([0, h]);

    var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h);

    var groups = svg.selectAll("g")
                    .data(dataset)
                    .enter()
                    .append("g");

    var rects = groups.selectAll("rect")
                    .data(function (d) {
                        return d;
                    })
                    .enter()
                    .append("rect")
                    .attr("x", function (d, i) {
                        return x(i);
                    })
                    .attr("y", function (d) {
                        return y(d.y0 + d.y);
                    })
                    .attr("height", function (d) {
                        return h - y(d.y0);
                    })
                    .attr("width", x.rangeBand())
                    .attr("fill", function (d, i) {
                        return color(i);
                    });

1
你需要在服务器端实现这个功能。使用D3时不能仅加载文件的部分内容。 - Lars Kotthoff
我该怎么做?... - EsoMoa
这是否意味着我只能一次绘制一个数据系列?我简直无法相信每个人都只有那么少的数据,以至于它总是适合一页。 - EsoMoa
我指的是加载数据。您不必一次使用所有加载的数据。 - Lars Kotthoff
@LarsKotthoff,那么有什么适当且快速的方法可以加载大量数据(约10k行)并快速更新可见数据,而不需要一直重新绘制呢? - EsoMoa
你需要对数据进行子集划分才能进行绘图,可以参考Mark的回答。 - Lars Kotthoff
1个回答

0

您可以使用slice方法对数据进行子集划分。这不会减少加载的数据量,但是可以让您一次性减少绘制在图表上的条形数量。

data = all_data.slice(start_index, end_index);

然后根据您想要显示的数据设置start_indexend_index。您可以添加一个事件监听器,回调函数更改起始和结束索引。

var refresh(){
    data = all_data.splice(start_index, end_index)
    //your code to redraw the graph using updated indices goes here
}

d3.select("body")
    .on("keydown", function() {
        if(d3.event.keyCode == 37){
            //left key press
            start_index = start_index - 4000;
            end_index = end_index-4000;
            if (start_index < 0){
                //handle boundary case
                start_index = 0;
                end_index = 4000;
            }
            refresh();
        }
        else if(d3.event.keyCode == 39){
            //right key press
            start_index = start_index + 4000;
            end_index = end_index + 4000;
            if (end_index > all_data.length){
                start_index = all_data.length-4000;
                end_index = all_data.length;
            }
            refresh();
        }
    });

好的,谢谢。由于我有一个二维数组的JSON对象,所以我必须为此编写自己的splice函数。但是这样会导致所有内容都被重新绘制,在“更新”时会发生吗? - EsoMoa
你需要在 refresh() 中更改域并重新绘制条形图。在刷新中可能有一些 SVG 的部分不需要更新(例如标题、轴线)。 - Mark
当我更新这些内容时,如果只是将数据从(0到300)更改为(1到301),那么d3会保留299个现有的SVG还是重新计算和重绘它们? - EsoMoa
您可以为数据分配一个关键函数来实现对象恒定性。如果您想进行动画转换,则这非常重要。请参阅http://bost.ocks.org/mike/constancy/。 - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接