我遇到绑定数据的问题,其中数据绑定到某些选择而不绑定到其他选择。
对于上下文,我在csv文件中有一系列行。使用d3,我遍历每一行并为csv文件中的每一行生成一个svg。如下所示。
var svgArea = d3.select("body").append("svg")
.attr("class", "barSvg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
然后我打算使用此选择将<g>
元素和一系列<rect>
元素绑定到svg选择:
//creating a <g> elements
var vehicleText = svgArea.select("g")
.data(d)
.enter()
.append("g")
.attr("id", function(d) {return "vehicle_" + d.vehicle});
//creating a grouped bar chart
var vehicleBars = svgArea.selectAll("rect")
.data(d.sales)
.enter()
.append("rect")
.attr("class", "vehicleBars")
.attr("id", function (d) {return "vehicle_" + d.vehicle + "_" + d.year})
.attr("width", width / 4)
.attr( "x", function (d){
return xYears(d.year)
})
.attr("y", function(d){
return yScale(d.value)
})
.attr("height", function(d) {return height - yScale(d.value)})
.attr("fill", function(d) {return colorScale(d.year)});
问题在于<g>
元素没有出现,但<rect>
元素尽管使用了完全相同的选择。我一直在想,这可能是我将数据绑定到元素的方式的问题。我到底错在了什么?为什么它绑定了一组元素的数据,而不是绑定它的集合? For reference, here is my code
答案 0 :(得分:1)
这里有两个主要问题:
svg中已有<g>
个元素。因此,输入选择应该选择不存在的内容,而不是select("g")
,而不是selectAll("foo")
。
d
是一个对象。但是,data
函数只接受三件事:数组,函数或什么都没有。因此,它应该是data([d])
。
这个问题#2解释了为什么,正如你所说的......
数据被绑定到某些选择而不是其他选择。
...以及console.log(vehicleText.datum())
返回Cannot read property '__data__' of null
话虽如此,这是你更新的plunker:https://plnkr.co/edit/igliOTB1eq1k31eQ9nY5?p=preview
然而,这不是实现你想要的最好的方式,也不是我自己做的最好的方式:请记住,我只回答你的问题,而不是更多。
PS:请勿使用d
作为chartGenerator
功能中数据的参数。在D3代码中,d
通常用于匿名函数中的第一个参数(数据)。像你一样使用d
会增加一些混乱,特别是对于经验丰富的D3编码员。
答案 1 :(得分:1)
您可以直接将属性设置为标签文本。试试这种方式。
var vehicleText = svgArea.append("g")
.attr("id", "vehicle_" + d.vehicle);
vehicleText.append("text")
.attr("class", "annotation")
.attr("dx","4em")
.attr("dy",height+20)
.text( d.vehicle);
var rows = [{
"vehicle": "Ford F - Series PU",
"Mar-2016": 65179,
"Mar-2017": 72089,
"perc_change": 10.6
},
{
"vehicle": "Chevrolet Silverado PU",
"Mar-2016": 45009,
"Mar-2017": 45280,
"perc_change": 0.6
},
{
"vehicle": "Dodge Ram PU",
"Mar-2016": 34152,
"Mar-2017": 36885,
"perc_change": 8
},
{
"vehicle": "Toyota Camry",
"Mar-2016": 30942,
"Mar-2017": 28189,
"perc_change": -8.9
},
{
"vehicle": "Toyota RAV4",
"Mar-2016": 27376,
"Mar-2017": 28116,
"perc_change": 2.7
},
{
"vehicle": "Honda Accord",
"Mar-2016": 25571,
"Mar-2017": 27182,
"perc_change": 6.3
},
{
"vehicle": "Toyota Corolla / Matrix",
"Mar-2016": 24183,
"Mar-2017": 26747,
"perc_change": 10.6
},
{
"vehicle": "Nissan Rogue",
"Mar-2016": 22566,
"Mar-2017": 26629,
"perc_change": 18
},
{
"vehicle": "Honda CR-V",
"Mar-2016": 25939,
"Mar-2017": 25758,
"perc_change": -0.7
},
{
"vehicle": "Honda Civic",
"Mar-2016": 25052,
"Mar-2017": 25303,
"perc_change": 1
},
{
"vehicle": "Ford Escape",
"Mar-2016": 20806,
"Mar-2017": 23012,
"perc_change": 10.6
},
{
"vehicle": "Chevrolet Equinox",
"Mar-2016": 19636,
"Mar-2017": 21600,
"perc_change": 10
},
{
"vehicle": "Toyota Highlander",
"Mar-2016": 12742,
"Mar-2017": 21241,
"perc_change": 66.7
},
{
"vehicle": "Nissan Altima",
"Mar-2016": 20573,
"Mar-2017": 20039,
"perc_change": -2.6
},
{
"vehicle": "Ford Explorer",
"Mar-2016": 16690,
"Mar-2017": 19628,
"perc_change": 17.6
},
{
"vehicle": "GMC Sierra PU",
"Mar-2016": 16520,
"Mar-2017": 18900,
"perc_change": 14.4
},
{
"vehicle": "Chevrolet Malibu",
"Mar-2016": 10813,
"Mar-2017": 18577,
"perc_change": 71.8
},
{
"vehicle": "Subaru Outback",
"Mar-2016": 13075,
"Mar-2017": 17769,
"perc_change": 35.9
},
{
"vehicle": "Ford Fusion",
"Mar-2016": 19446,
"Mar-2017": 17560,
"perc_change": -9.7
},
{
"vehicle": "Jeep Grand Cherokee",
"Mar-2016": 17653,
"Mar-2017": 17230,
"perc_change": -2.4
}
];
// Code goes here
//setting the margins
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 20
}
//setting width and height
var width = 300 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
yearVals = ["Mar-2016", "Mar-2017"]
//ranges
var xVehicles = d3.scaleBand().rangeRound([0, width], .1).paddingInner(0.1);
var xYears = d3.scaleBand().domain(yearVals).range([0, xVehicles.bandwidth()])
.paddingInner(.1)
.paddingOuter(5.0);
var yScale = d3.scaleLinear().domain([0, 85000]).range([height, 0]);
var colorScale = d3.scaleOrdinal()
.range(["#87ceeb", "#00bfff"]);
rows.forEach(function(data) {
chartGenerator(data)
})
d3.selectAll("svg.barSvg")
.data(rows)
.enter()
.append("text")
.text(function(d) {
return d.vehicle;
})
function chartGenerator(d) {
d.sales = yearVals.map(function(year) {
return {
"vehicle": d.vehicle,
year: year,
value: +d[year]
}
})
//create vehicle name
var vehicle = []
vehicle["name"] = d.vehicle;
var svgArea = d3.select("body")
.append("svg")
.attr("class", "barSvg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append("g");
//vehicleText not appended to g element
//console.log(vehicleText.datum());
var vehicleBars = svgArea.selectAll("rect")
.data(d.sales)
.enter()
.append("rect")
.attr("class", "vehicleBars")
.attr("id", function(d) {
return "vehicle_" + d.vehicle + "_" + d.year
})
.attr("width", width / 4)
.attr("x", function(d) {
return xYears(d.year)
})
.attr("y", function(d) {
return yScale(d.value)
})
.attr("height", function(d) {
return height - yScale(d.value)
})
.attr("fill", function(d) {
return colorScale(d.year)
});
var vehicleText = svgArea.append("g")
.attr("id", "vehicle_" + d.vehicle);
vehicleText.append("text")
.attr("class", "annotation")
.attr("dx", width / 4)
.attr("dy", height + 20)
.text(d.vehicle);
}
&#13;
/* Styles go here */
body {
width: 1200px;
}
h2,
h3 {
font-family: sans-serif;
padding: 20px 50px 0px 50px;
}
.barSvg {
background: white;
}
.vehicleData {
background: grey;
width: 25px;
height: 15px;
}
.annotation {
stroke: black;
stroke-width: black;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<h2>Auto Sales - March 2017</h2>
</body>
&#13;