问题描述
在用d3.js做一个柱状图的demo的时候,希望为柱状图添加鼠标交互事件监听。直接监听事件用链式调用的形式添加在元素的生长动画后面,报出错误:
代码如下:
var rects = svg.selectAll(".MyRect")
.data(dataset)
.enter()
.append("rect")
.attr("class", ".MyRect")
.attr("transform", "translate(" + padding.left + "," + padding.top + ")")
.attr("x", function (d, i) {
return xScale(i) + rectPadding / 2
})
.attr("y", function (d) {
return yScale(d);
})
.attr("width", xScale.rangeBand() - rectPadding)
.attr("fill", "steelblue")
// 监听事件要放在y的生长动画之前
.attr("y", function (d) {
var min = yScale.domain()[0];
return yScale(min)
})
.attr("height", function (d) { return 0 })
.transition()
.delay(function (d, i) {
return i * 200
})
.duration(2000)
.ease("bounce")
.attr("y", function (d) {
return yScale(d)
})
.attr("height", function (d) {
return height - padding.top - padding.bottom - yScale(d);
})
//直接将事件监听放在了生长动画之后
.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","yellow");
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill","steelblue")
})
但是如果放在生长动画之前,这样就没有问题,就事件监听函数就可以正常工作:
var rects = svg.selectAll(".MyRect")
.data(dataset)
.enter()
.append("rect")
.attr("class", ".MyRect")
.attr("transform", "translate(" + padding.left + "," + padding.top + ")")
.attr("x", function (d, i) {
return xScale(i) + rectPadding / 2
})
.attr("y", function (d) {
return yScale(d);
})
.attr("width", xScale.rangeBand() - rectPadding)
.attr("fill", "steelblue")
// 监听事件
.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","yellow");
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill","steelblue")
})
//bar chart生长动画
.attr("y", function (d) {
var min = yScale.domain()[0];
return yScale(min)
})
.attr("height", function (d) { return 0 })
.transition()
.delay(function (d, i) {
return i * 200
})
.duration(2000)
.ease("bounce")
.attr("y", function (d) {
return yScale(d)
})
.attr("height", function (d) {
return height - padding.top - padding.bottom - yScale(d);
})
困惑所在
不太明白为什么监听事件放在生长函数之前就可以正常工作了,这背后的机制是怎么一回事?希望有大神指点一二。
因为duration之后返还的对象不在是一开始的d3查找的元素了吧,而是个动画对象,不再支持链式调用