使用 p5js 创建多个可点击的 Div
Creating Multiple Clickable Divs with p5js
编辑:我明白了。我只是走了一条完全不同的路线,制作了一个按钮 class 并在我的实际 canvas 上使用矩形来表示它们。
我试图在 p5js 中以编程方式制作多个可点击按钮,但我遇到了一个问题。所有的 div 都被创建,它们显示并具有适当的 HTML 与之相关联,但无论单击哪个,都只会诱导最后一个按钮的功能。
这是一张照片:
右边那些是我的按钮,但是无论你点击哪里,选择的颜色总是底部的紫色。
这是我的代码:
for (var i = 0; i < colorCodes.length ; i++){
var div = createDiv(str(i));
div.parent('control-holder');
div.style('background-color', colorCodes[i]);
div.style('height', '40px');
div.mousePressed(function(){
console.log(div.html()); //always prints 7
changeColor(int(div.html()));
});
buttons.push(div);
}
非常感谢任何帮助,我不明白为什么它不起作用。
这是一个常见的 JavaScript 陷阱。
当您使用 var
关键字时,您创建的变量具有 函数范围 ,这意味着变量(在您的情况下,您的 i
变量)保持它的值直到函数结束,而不是直到循环结束。考虑这段代码:
for(var i = 0; i < 10; i++){
console.log('i: ' + i);
}
console.log('final i: ' + i);
这段代码会在循环中打印出0-9,然后在循环结束后打印出10。
现在,让我们稍微更改一下代码:
for(var i = 0; i < 10; i++){
setTimeout(function(){
console.log('i: ' + i);
}, 1000);
}
console.log('final i: ' + i);
现在循环设置超时回调。这段代码会先打印出final i: 10
,然后会打印出i: 10
10次。这是因为 console.log('final i: ' + i);
行发生在 之前 回调函数被调用。由于该变量具有函数作用域,因此它采用最后给出的值。这是另一个例子:
var i = 42;
setTimeout(function() {
console.log('i: ' + i);
}, 1000);
i = 37;
您可能希望此代码打印出 42
,但同样,回调函数在 此代码运行后 被调用,因此在它被调用时, i
是 37
.
无论如何,回到你的代码。希望上面的示例向您展示了代码中发生的事情:var
关键字创建了一个函数范围的变量,这意味着在调用 mousePressed 回调时,该变量保留了它设置的最后一个值。
传统上,解决这个问题的方法是通过另一个函数调用:
for (var i = 0; i < 10; i++) {
callSetTimeout(i);
}
console.log('final i: ' + i);
function callSetTimeout(i) {
setTimeout(function() {
console.log('i: ' + i);
}, 1000);
}
但是从 JavaScript 6 开始,您可以使用 let
关键字代替 var
:
for(let i = 0; i < 10; i++){
setTimeout(function(){
console.log('i: ' + i);
}, 1000);
}
这会为您的变量提供 块作用域 ,这意味着该变量仅在 for
循环内的作用域内。因此,循环的每次迭代都有自己的副本,您的函数现在将按您预期的方式工作。
编辑:我明白了。我只是走了一条完全不同的路线,制作了一个按钮 class 并在我的实际 canvas 上使用矩形来表示它们。
我试图在 p5js 中以编程方式制作多个可点击按钮,但我遇到了一个问题。所有的 div 都被创建,它们显示并具有适当的 HTML 与之相关联,但无论单击哪个,都只会诱导最后一个按钮的功能。
这是一张照片:
右边那些是我的按钮,但是无论你点击哪里,选择的颜色总是底部的紫色。
这是我的代码:
for (var i = 0; i < colorCodes.length ; i++){
var div = createDiv(str(i));
div.parent('control-holder');
div.style('background-color', colorCodes[i]);
div.style('height', '40px');
div.mousePressed(function(){
console.log(div.html()); //always prints 7
changeColor(int(div.html()));
});
buttons.push(div);
}
非常感谢任何帮助,我不明白为什么它不起作用。
这是一个常见的 JavaScript 陷阱。
当您使用 var
关键字时,您创建的变量具有 函数范围 ,这意味着变量(在您的情况下,您的 i
变量)保持它的值直到函数结束,而不是直到循环结束。考虑这段代码:
for(var i = 0; i < 10; i++){
console.log('i: ' + i);
}
console.log('final i: ' + i);
这段代码会在循环中打印出0-9,然后在循环结束后打印出10。
现在,让我们稍微更改一下代码:
for(var i = 0; i < 10; i++){
setTimeout(function(){
console.log('i: ' + i);
}, 1000);
}
console.log('final i: ' + i);
现在循环设置超时回调。这段代码会先打印出final i: 10
,然后会打印出i: 10
10次。这是因为 console.log('final i: ' + i);
行发生在 之前 回调函数被调用。由于该变量具有函数作用域,因此它采用最后给出的值。这是另一个例子:
var i = 42;
setTimeout(function() {
console.log('i: ' + i);
}, 1000);
i = 37;
您可能希望此代码打印出 42
,但同样,回调函数在 此代码运行后 被调用,因此在它被调用时, i
是 37
.
无论如何,回到你的代码。希望上面的示例向您展示了代码中发生的事情:var
关键字创建了一个函数范围的变量,这意味着在调用 mousePressed 回调时,该变量保留了它设置的最后一个值。
传统上,解决这个问题的方法是通过另一个函数调用:
for (var i = 0; i < 10; i++) {
callSetTimeout(i);
}
console.log('final i: ' + i);
function callSetTimeout(i) {
setTimeout(function() {
console.log('i: ' + i);
}, 1000);
}
但是从 JavaScript 6 开始,您可以使用 let
关键字代替 var
:
for(let i = 0; i < 10; i++){
setTimeout(function(){
console.log('i: ' + i);
}, 1000);
}
这会为您的变量提供 块作用域 ,这意味着该变量仅在 for
循环内的作用域内。因此,循环的每次迭代都有自己的副本,您的函数现在将按您预期的方式工作。