我在rect
元素中有16个svg
,其ID为photo0
,photo1
... photo15
我想为每个单元格创建mouser over效果,因此当用户将鼠标悬停在某个rect
上时,它会抓取某些图片来填充照片单元格。
然而,当我逐一编写mouserover
时,它完美无缺。如下所示:
d3.select('#photo'+0).on("mouseover", function(d){
d3.select('#photo').selectAll('img').remove();
d3.select('#photo').append("img")
.attr("src","/path/images/" + 0 + ".jpeg" )
.attr("x", -8)
.attr("y", -8)
.attr("width","500px")
.attr("height","500px");
});
d3.select('#photo'+1).on("mouseover", function(d){
d3.select('#photo').selectAll('img').remove();
d3.select('#photo').append("img")
.attr("src","/path/images/" + 1 + ".jpeg" )
.attr("x", -8)
.attr("y", -8)
.attr("width","500px")
.attr("height","500px");
});
d3.select('#photo'+2).on("mouseover", function(d){
d3.select('#photo').selectAll('img').remove();
d3.select('#photo').append("img")
.attr("src","/path/images/" + 2 + ".jpeg" )
.attr("x", -8)
.attr("y", -8)
.attr("width","500px")
.attr("height","500px");
});
...
然而,当我把它们放入for循环中时,它不会起作用。似乎每个细胞都以某种方式调用最后一张图片,任何人都可以帮忙吗?
for(i=0;i<16;i++){
d3.select('#photo'+i).on("mouseover", function(d){
d3.select('#photo').selectAll('img').remove();
d3.select('#photo').append("img")
.attr("src","/path/images/" + i + ".jpeg" )
.attr("x", -8)
.attr("y", -8)
.attr("width","500px")
.attr("height","500px");
});
}
答案 0 :(得分:2)
以下是发生的事情:
for(i=0;i<16;i++){
d3.select('#photo'+i).on("mouseover", function(d){
d3.select('#photo').selectAll('img').remove();
d3.select('#photo').append("img")
.attr("src","/path/images/" + i + ".jpeg" ) // Accesses `i` from closure,
// will always be last value
// that met `i < 16`
.attr("x", -8)
.attr("y", -8)
.attr("width","500px")
.attr("height","500px");
});
}
您需要的是一个功能值,它可以满足您的需求,然后使用该值而不是在每次迭代中创建新函数。这是一个例子(免责声明,我从未使用过d3,这是基于你的代码):
var populateCell = function(i) {
d3.select('#photo').selectAll('img').remove();
d3.select('#photo').append('img')
.attr('src', '/path/images/' + i + '.jpeg')
.attr('x', -8)
.attr('y', -8)
.attr('width', '500px')
.attr('height', '500px');
};
var selectCell = function(i) {
return d3.select('#photo' + i);
};
var i = 0; // explicit definition of `i`
for (; i < 16; i++) {
selectCell(i).on('mouseover', populateCell(i));
}
以下是使用JavaScript并假设console
的意外行为示例,以说明原则:
// Will output 16, 16 times.
var i = 0;
var f = [];
for (; i < 16; i++) {
f.push(function() { // new function created in each iteration
console.log(i); // captures access to `i`, outputs value of `i` at
// at time function is called.
});
}
for (var j = 0; j < f.length; j++) {
f[j]();
}
这是一个所需行为的例子,我修改了一些修正案。
// Will output 0 through 16.
var i = 0;
var f = [];
var fn = function(i) {
console.log(i);
}
for (; i < 16; i++) {
f.push(fn(i));
}
for (var j = 0; j < f.length; j++) {
f[j]();
}
更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures