使用 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,但同样,回调函数在 此代码运行后 被调用,因此在它被调用时, i37.

无论如何,回到你的代码。希望上面的示例向您展示了代码中发生的事情: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 循环内的作用域内。因此,循环的每次迭代都有自己的副本,您的函数现在将按您预期的方式工作。