我可能做错了,但下面的小提琴显示出一些非常奇怪的行为:
https://jsfiddle.net/pkerpedjiev/42w01t3e/8/
在我解释之前,请参阅以下代码:
function skiAreaElevationsPlot() {
var width = 550;
var height = 400;
var margin = {
'top': 30,
'left': 30,
'bottom': 30,
'right': 40
};
function chart(selection) {
selection.each(function(data) {
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg").append("g");
svg.attr('width', width)
.attr('height', height);
var zoom = d3.behavior.zoom()
.on("zoom", draw);
data = Object.keys(data).map(function(key) {
return data[key];
}).sort(function(a, b) {
return b.max_elev - a.max_elev;
});
svg.insert("rect", "g")
.attr("class", "pane")
.attr("width", width)
.attr("height", height)
.attr('pointer-events', 'all')
.call(zoom);
var yScale = d3.scale.linear()
.domain([0, d3.max(data.map(function(d) {
return d.max_elev;
}))])
.range([height - margin.top - margin.bottom, 0]);
var xScale = d3.scale.linear()
.domain([0, data.length])
.range([0, width - margin.left - margin.right]);
var widthScale = d3.scale.linear()
.domain(d3.extent(data.map(function(d) {
return d.area;
})))
.range([10, 30]);
zoom.x(xScale).scaleExtent([1, data.length / 30]);
var gMain = gEnter.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
gMain.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
function skiAreaMouseover(d) {
gMain.select('#n-' + d.uid)
.attr('visibility', 'visible');
}
function skiAreaMouseout(d) {
gMain.select('#n-' + d.uid)
.attr('visibility', 'visible');
}
// the rectangle showing each rect
gMain.selectAll('.resort-rect')
.data(data)
.enter()
.append('rect')
.classed('resort-rect', true)
.attr("clip-path", "url(#clip)")
.attr('id', function(d) {
return 'n-' + d.uid;
})
.on('mouseover', skiAreaMouseover)
.on('mouseout', skiAreaMouseout);
var gYAxis = svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width - margin.right) + "," + margin.top + ")");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("right")
.tickSize(-(width - margin.left - margin.right))
.tickPadding(6);
gYAxis.call(yAxis);
draw();
function draw() {
function scaledX(d, i) {
console.log('xd', d);
return xScale(i);
}
function rectWidth(d, i) {
return widthScale(d.area);
}
gMain.selectAll('.resort-rect')
.attr('x', scaledX)
.attr('y', function(d) {
console.log('d', d);
return yScale(d.max_elev);
})
.attr('width', 20)
.attr('height', function(d) {
console.log('d:', d)
return yScale(d.min_elev) - yScale(d.max_elev);
})
.classed('resort-rect', true);
}
});
}
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
return chart;
}
var elevationsPlot = skiAreaElevationsPlot()
.width(550)
.height(300);
data = [{
"min_elev": 46,
"max_elev": 54,
"uid": "9809641c-ab03-4dec-8d51-d387c7e4f114",
"num_lifts": 1,
"area": "0.00"
}, {
"min_elev": 1354,
"max_elev": 1475,
"uid": "93eb6ade-8d78-4923-9806-c8522578843f",
"num_lifts": 1,
"area": "0.00"
}, {
"min_elev": 2067,
"max_elev": 2067,
"uid": "214fdca9-ae62-473b-b463-0ba3c5755476",
"num_lifts": 1,
"area": "0.00"
}];
d3.select('#ski-area-elevations')
.datum(data)
.call(elevationsPlot)
因此,首次加载页面时,中间会显示一个矩形。如果您尝试在图表上滚动,console.log
函数中的draw
语句将生成输出。请注意,xd:
和d:
语句都只包含数据集中的一个对象。
现在,如果您将鼠标悬停在矩形上并再次尝试缩放(使用滚轮)。将显示一堆NaN
错误。现在,一些d:
和xd:
语句现在将打印对象列表。
为什么会这样?底层绑定数据从未改变过。
令我困惑的是,如果这些陈述:
gMain.select('#n-' + d.uid)
更改为:
gMain.selectAll('#n-' + d.uid)
小提琴表现得很好。为什么这会有所不同?这是一个错误,还是我错过了什么?
对于googleability,这是我得到的错误:
Error: Invalid value for <rect> attribute y="NaN"
答案 0 :(得分:1)
简单的解决方案是用d3.select替换鼠标事件例程中的gMain.select/gMain.selectAll(this)
复杂的解决方案似乎是,如果您正在对现有选择进行操作,则单个选择会将父数据绑定到所选的任何内容。 gMain是一个现有的选择,并且有3个数据值作为绑定到它的数组 - console.log(gMain.datum())来查看 - 所以当你执行gMain.select时(&#34;#oneoftherects&#34;)将#oneoftherects中的单个对象替换为该数组,从而解决了期望一个对象的x,y,width,height等例程。 (使用d3.select并不像d3那样做选择)