d3图缺少数组中的第一个项 [英] d3 plot missing the first item in an array

查看:140
本文介绍了d3图缺少数组中的第一个项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很努力。我在javascript中使用d3库创建一个点图。我想过滤实际被绘制的点,以便稍后我可以添加文本字段到数据集中名为highlight的列中指定的某些字段。作为一个测试,我只绘制标记为是的圆圈,但最终将绘制所有的圆圈。我只包括实际的绘图代码,因为我很确定数据结构是OK。以下代码按照我的预期绘制圆形。

  var category = plot.selectAll(。+ media + )
.data(plotData)
.enter()
.append(g)
.attr(transform,function(d){returntranslate 0,+ yScale(d.key)+);})
.attr(class,media +category)
.call(function(parent){
parent .append('text')
.attr(class,media +Subtitle)
.attr(x,margin.left)
.attr(y,0 )
.text(function(d){return d.key})

parent.selectAll('circles')
.data(function(d){
//console.log(\"object=,d)
let filtered = d.values.filter(function(d){
return d.highlight ==yes
} )
//console.log(\"circles filtered,filtered)
return filtered
})
.enter()
.append('circle')
.attr(class,function(d,i){
if(d.highlight ==yes){
return media +highlight
}
else {return media +fill}
})
.attr(id,function(d){return d.name ++ d.value ++ d.size}
.attr(cx,function(d){return xScale(d.value)})
.attr(cy,yScale.rangeBand()*。 attr(r,function(d){
if(size){return d.size *(yScale.rangeBand()*。003)}
else {return yOffset / 2}
}
.attr(transform,function(d){returntranslate(+(margin.left)+,+(0)+)})
.style (fill,colors [0])

剧情如下:





问题出现在我尝试添加文本时。我使用完全相同的过滤器来过滤数据,为.data aregument使用创建一个数组。但是由于某种原因,虽然第一个对象在数组中,但是没有绘制。我修改的代码如下所示:

  var category = plot.selectAll(。+ media +category)
.data(plotData)
.enter()
.append(g)
.attr(transform,function(d){returntranslate(0,+ yScale (d.key)+);})
.attr(class,media +category)
.call(function(parent){

parent。 append('text')
.attr(class,media +Subtitle)
.attr(x,margin.left)
.attr(y,0)
.text(function(d){return d.key})

parent.selectAll('circles')
.data(function(d){
//console.log(\"object=,d)
let filtered = d.values.filter(function(d){
return d.highlight ==yes
})
//console.log(\"circles filtered,filtered)
return filtered
})
.enter()
.append('circle')
.attr(class,function(d,i){
if(d.highlight ==yes){
return media +highlight
}
else {return media +fill}
})
.attr(id,function(d){return d.name ++ d.value ++ d.size})
.attr(cx,function(d){return xScale(d.value)})
.attr(cy,yScale.rangeBand()*。4)
.attr (r,function(d){
if(size){return d.size *(yScale.rangeBand()*。003)}
else {return yOffset / 2}
})
.attr(transform,function(d){returntranslate(+(margin.left)+,+(0)+)})
.style fill,colors [0])

parent.selectAll('text')
.data(function(d){
console.log(object = d)
let filtered = d.values.filter(function(d){
return d.highlight ==yes
})
console.log ,过滤)
返回已过滤
})
.enter()
.append('text')
.attr(x {
return xScale(d.value)+(margin.left);
})
.attr(y,function(d){
return yScale.rangeBand()*。4;
})
.text (d){
return d.name +''+ d.size
})
.attr(class,media +subtitle)

,但情节如下:



)。



解决方案:select别的:

  parent.selectAll('。somethingElse')//这里你不选择现有元素
.data(function(d){
console.log(object =,d)
let filtered = d.values.filter(function(d){
return d.highlight = =yes
})
console.log(text filtered,filtered)
return filtered
。 append('text')


I'm really struggling with this. I'm creating a dot-plot in javascript using the d3 library. I would like to filter the dots actually being plotted so that later I can add text fields to some of them specified in a column in the dataset called 'highlight. Just as a test I'm only plotting the circles that are marked 'yes' but will eventually plot all circles. I've only included the actual plotting code as I'm pretty sure the data structure is OK. The following code plots the circles as I expect it to.

var category = plot.selectAll("."+media+"category")
        .data(plotData)
        .enter()
        .append("g")
        .attr("transform", function (d) {return "translate(0," + yScale(d.key) + ")"; })
        .attr("class", media+"category")
        .call(function(parent){
    parent.append('text')
        .attr("class", media+"Subtitle")
        .attr("x",margin.left)
        .attr("y",0)
        .text(function(d){return d.key})

    parent.selectAll('circles')
    .data(function(d){
        //console.log("object= ",d)
        let filtered=d.values.filter(function(d){
            return d.highlight=="yes"
        })
        //console.log("circles filtered ", filtered)
        return filtered
    })
    .enter()
    .append('circle')
    .attr("class",function(d,i){
        if(d.highlight=="yes"){
            return media+"highlight"
        }
        else {return media+"fill"}
    })
    .attr("id",function(d){return d.name +" "+d.value+ " "+d.size})
    .attr("cx",function(d){return xScale(d.value)})
    .attr("cy",yScale.rangeBand()*.4)
    .attr("r", function(d) {
        if (size) {return d.size*(yScale.rangeBand()*.003   )}
        else {return yOffset/2}
    })
    .attr("transform", function (d) {return "translate("+(margin.left)+","+(0)+")"})
    .style("fill",colours[0])

The plot looks like this:

The problem comes when I try to add the text. I'm using exactly the same filter to filter the data which creates an array for the .data aregument to use. However for some reason, although the first object IS in the array it is not plotted. My revised code looks like this:

var category = plot.selectAll("."+media+"category")
        .data(plotData)
        .enter()
        .append("g")
        .attr("transform", function (d) {return "translate(0," + yScale(d.key) + ")"; })
        .attr("class", media+"category")
        .call(function(parent){

        parent.append('text')
            .attr("class", media+"Subtitle")
            .attr("x",margin.left)
            .attr("y",0)
            .text(function(d){return d.key})

        parent.selectAll('circles')
        .data(function(d){
            //console.log("object= ",d)
            let filtered=d.values.filter(function(d){
                return d.highlight=="yes"
            })
            //console.log("circles filtered ", filtered)
            return filtered
        })
        .enter()
        .append('circle')
        .attr("class",function(d,i){
            if(d.highlight=="yes"){
                return media+"highlight"
            }
            else {return media+"fill"}
        })
        .attr("id",function(d){return d.name +" "+d.value+ " "+d.size})
        .attr("cx",function(d){return xScale(d.value)})
        .attr("cy",yScale.rangeBand()*.4)
        .attr("r", function(d) {
            if (size) {return d.size*(yScale.rangeBand()*.003   )}
            else {return yOffset/2}
        })
        .attr("transform", function (d) {return "translate("+(margin.left)+","+(0)+")"})
        .style("fill",colours[0])

        parent.selectAll('text')
        .data(function(d){
            console.log("object= ",d)
            let filtered=d.values.filter(function(d){
                return d.highlight=="yes"
            })
            console.log("text filtered ", filtered)
            return filtered
        })
        .enter()
        .append('text')
        .attr("x",function(d){
                    return xScale(d.value)+(margin.left);
                    })
                    .attr("y",function(d){
                    return yScale.rangeBand()*.4;
                    })
                    .text(function(d){
                        return d.name+' '+d.size
                    })
                    .attr("class",media+"subtitle")

but the plot looks like this:

No matter how many circles I define in the dataset as 'yes' so that they are plotted, the first circle is always missing its label. I'm guessing the data is getting mutated somewhere but can't figure out where. I've also tried plotting the text first before the circles just to see but the result is always the same.

This is the output from the console showing that the .data araay has the first items in it

[Object, Object, Object, Object]
dot-plot.js:104 object=  Object {key: "Endland", values: Array[22]}
dot-plot.js:108 text filtered  [Object, Object]0: Objectgroup: "Endland"highlight: "yes"name: "Manchester City"size: "95.65695168"value: "55097"__proto__: Object1: Objectgroup: "Endland"highlight: "yes"name: "Stoke"size: "9.13121722"value: "27743"__proto__: Objectlength: 2__proto__: Array[0]
dot-plot.js:104 object=  Object {key: "Spain", values: Array[44]}
dot-plot.js:108 text filtered  [Object, Object, Object]0: Objectgroup: "Spain"highlight: "yes"name: "Barcelona"size: "47.32724506"value: "100000"__proto__: Object1: Objectgroup: "Spain"highlight: "yes"name: "Deportivo de La Coru_a"size: "59.93202583"value: "34600"__proto__: Object2: Objectlength: 3__proto__: Array[0]
dot-plot.js:104 object=  Object {key: "Italy", values: Array[22]}
dot-plot.js:108 text filtered  [Object]
dot-plot.js:104 object=  Object {key: "Germany", values: Array[20]}
dot-plot.js:108 text filtered  [Object, Object]

I'd appreciate any insight that anyone may have. Really sorry for being so verbose but I've never used js.fiddle or I'd put an example up

Thanks

解决方案

When you do this:

parent.append('text')
        .attr("class", media+"Subtitle")
        .attr("x",margin.left)
        .attr("y",0)
        .text(function(d){return d.key});

You are creating a text element in the SVG (in your case, the subtitle). So, when you do this later:

parent.selectAll('text')//here you select ALL text elements
    .data(function(d){
        console.log("object= ",d)
        let filtered=d.values.filter(function(d){
            return d.highlight=="yes"
        })
        console.log("text filtered ", filtered)
        return filtered
    })
    .enter()
    .append('text');

You are selecting that previous text (the subtitle). Thus, your enter selection has one element less (have a look here: The role of placeholders in "enter" selections).

Solution: select something else:

parent.selectAll('.somethingElse')//here you don't select existing elements
    .data(function(d){
        console.log("object= ",d)
        let filtered=d.values.filter(function(d){
            return d.highlight=="yes"
        })
        console.log("text filtered ", filtered)
        return filtered
    })
    .enter()
    .append('text') 

这篇关于d3图缺少数组中的第一个项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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