d3js只更新一次 [英] d3js updates only once

查看:208
本文介绍了d3js只更新一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可视化任务,我需要使它与d3.js完成。这是我的代码。

  var w = 700; 
var h = 500;
var offset = 100;
var padding = 20;
var colors = d3.scale.category10();
var svg = d3.select(body)
.append(svg)
.attr(width,w)
.attr H);




var texts = function(ds,ds2){
var stack = d3.layout.stack();
stack_data = stack(ds);

var xScale = d3.scale.ordinal()
.domain(d3.range(ds [0] .length))
.rangeRoundBands([0,w-offset ],0.50);


var yScale = d3.scale.linear()
.domain([0,
d3.max(stack_data,function(d){
return d3.max(d,function(d){
return d.y0 + dy -20;
});
})
])
。范围([padding,h-50]);

var xAxis = d3.svg.axis()
.scale(xScale)
.orient(bottom)
.ticks(ds [0]。长度);

gs = svg.selectAll(g)。data(stack_data);

for(var i5 = 0; i5< ds.length; i5 ++){
gs.enter()
.append(g)
。 attr(class,stacked_bars)
.attr(fill,function(d,i){
return colors(i);
});

asd = gs.selectAll(rect)。data(function(d){return d;});

asd.enter()。append(rect);

asd.transition()
.duration(1000)
.attr(x,function(d,i){
return xScale
})
.attr(y,function(d){
return h - yScale(d.y0) - yScale(dy);
})
.attr(height,function(d){
return yScale(dy);
})
.attr(width,xScale.rangeBand())
.attr(class,rectbar);

};

gs.append(g)//向svg添加一个组元素
.attr(class,axis)//将类axis b $ b .attr(transform,translate(0,+(h - padding)+))//将轴移动到底
.call(xAxis); //调用轴函数

gs.exit()。remove();
}


res = dataGenerator(Europe);
dataset = res [0];
dataset2 = res [1];

texts(dataset,dataset2);

d3.select(#selector)。on(change,function(){
cont = d3.select(this).property('value');
res = dataGenerator(cont)

dataset = res [0]
dataset2 = res [1]

//svg.selectAll ).remove()

texts(dataset,dataset2);


});

它基本上获取数据并生成堆叠条。当用户在页面上使用select元素时,它会更新数据并生成新结果。它成功获得第一个结果,当用户选择另一个选项,它也使它发生。但是当用户再次尝试使用选择部件。



因此,在这种特殊情况下,我有国家和他们的数据作为数字,在首次加载和第一次更新它成功显示除了当第二次更新时,它只生成数据集中第一个国家的条。这是几个小时,我想解决这个问题。我知道我只有一点点错误,但不能解决。



这里也是代码的jsfiddle: https://jsfiddle.net/510ep9ux/4/



在d3.js,我可能不理解更新的概念很好。
所以,任何猜测?

解决方案

我对你的代码做了2个简单但关键的更改。 b
$ b

https://jsfiddle.net/guanzo/510ep9ux/6/

  gs = svg.selectAll(g)。 

  gs = svg.selectAll(g.stacked_bars)。data(stack_data); 

轴也包含在 g 元素,因此您必须确保只选择用于数据的元素,而不是不相关的元素。



  gs.append(g)
.attr(class,axis)
.attr(transform translate(0,+(h - padding)+))
.call(xAxis);

  svg.append(g)
.attr(class,axis)
.attr(transform +))
.call(xAxis);

如果你进入浏览器检查器,你会看到一个轴元素为EVERY stacked_bars 元素,你只需要1明显。它只是看起来像有1轴,因为它们是绝对定位和堆叠在彼此的顶部。



我改变它,以便在创建svg时添加轴,并且每次选择新数据时,轴将自动更新。


I have a visualization task that I need to make it done with d3.js. Here's my code.

                var w = 700;
                var h = 500;
                var offset = 100;
                var padding = 20;
                var colors = d3.scale.category10();
                var svg = d3.select("body")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);




                var texts = function(ds,ds2){
                    var stack = d3.layout.stack();
                    stack_data = stack(ds);

                    var xScale = d3.scale.ordinal()
                        .domain(d3.range(ds[0].length))
                        .rangeRoundBands([0, w-offset], 0.50);


                    var yScale = d3.scale.linear()
                        .domain([0,             
                            d3.max(stack_data, function(d) {
                                return d3.max(d, function(d) {
                                    return d.y0 + d.y -20;
                                });
                            })
                        ])
                        .range([padding, h-50]);

                    var xAxis = d3.svg.axis()
                        .scale(xScale)
                        .orient("bottom")
                        .ticks(ds[0].length);

                    gs = svg.selectAll("g").data(stack_data);

                    for (var i5 = 0; i5 < ds.length; i5++) {
                        gs.enter()
                        .append("g")
                        .attr("class", "stacked_bars")
                        .attr("fill", function(d, i) {
                            return colors(i);
                        });

                        asd = gs.selectAll("rect").data(function(d) { return d; });

                        asd.enter().append("rect");

                        asd.transition()
                            .duration(1000)
                            .attr("x", function(d, i) {
                                return xScale(i);
                            })
                            .attr("y", function(d) {
                                return h - yScale(d.y0) - yScale(d.y);
                            })
                            .attr("height", function(d) {
                                return yScale(d.y);
                            })
                            .attr("width", xScale.rangeBand())
                            .attr("class", "rectbar");

                    };

                    gs.append("g")  // add a group element to the svg
                        .attr("class", "axis") //Assign class "axis" to group
                        .attr("transform", "translate(0," + (h - padding) + ")")  // shift the axis to bottom
                        .call(xAxis);   // call the axis function 

                    gs.exit().remove();
}


                res = dataGenerator("Europe");
                dataset = res[0];
                dataset2 = res[1];

                texts(dataset,dataset2);

            d3.select("#selector").on("change", function() {
                    cont = d3.select(this).property('value');
                    res = dataGenerator(cont)

                    dataset = res[0]
                    dataset2 = res[1]

                    //svg.selectAll(".sym").remove()

                    texts(dataset,dataset2);


                }); 

It basically gets the data and generates stacked bars. When user uses the select element on the page, it updates the data and generates new results. It successfully gets the first results and when user selects another option, it makes it happen also. But when user tries to use select part once again. It only generates bars for dataset's first item.

So, in this particular case I have countries and their data as numbers, at first load and first update it successfully shows all but when it comes to second update, it only generate bars for first country in dataset. It's been hours that I'm trying to fix this. I know I only have a little mistake but couldn't make it to solve.

Also here's the jsfiddle of the code: https://jsfiddle.net/510ep9ux/4/

Since I'm new at d3.js, I may not understand the update concept well. So, any guesses?

解决方案

I made 2 simple but crucial changes to your code.

https://jsfiddle.net/guanzo/510ep9ux/6/ From

gs = svg.selectAll("g").data(stack_data);

to

gs = svg.selectAll("g.stacked_bars").data(stack_data);

The axis is also contained in a g element, so you have to ensure you're only selecting elements that are used for your data, and not unrelated elements.

From

gs.append("g")
.attr("class", "axis") 
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);

to

svg.append("g")
.attr("class", "axis") 
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);

If you go into the browser inspector you'll see that you have an axis element for EVERY stacked_bars element, you only need 1 obviously. It only looks like there's 1 axis because they're absolutely positioned and stacked on top of each other.

I changed it so that the axis is appended when the svg is created, and every time new data is selected, the axis will update itself.

这篇关于d3js只更新一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆