p5.js 代码不会抛出错误,但不会在鼠标单击时加载
p5.js code doesn't throw errors, but won't load on mouse click
我正在分析总统候选人的演讲。我有一个包含以下变量的数据文件:
> names(cl.context)
[1] "id" "category" "statement" "nchar" "polarity"
statement
变量由属于三个句子中的一个 category
的句子填充。 polarity
的取值范围是-1到1,反映了句子是偏向正向、中向还是偏向负向。
我在 p5 中尝试做的是当用户在 canvas 内单击鼠标时,按类别显示语句,随机放置 x,y。陈述本身根据其极性着色。
我终于到了开发者控制台不会抛出任何错误并绘制 canvas 的地步。但是当我在 canvas 中单击时,没有任何反应。没有出现任何陈述。
我是 JavaScript 的新手,因为它没有抛出错误消息,所以我无法解决问题所在。希望在这里得到一些建议。
我的 p5 代码:
var clContext;
var x;
var y;
const STATEMENTS = 118, CATEGORY = 3, QTY = STATEMENTS/CATEGORY | 0,
POLARITY = 3,
statements = Array(STATEMENTS), inds = Array(CATEGORY), polarity = Array(POLARITY);
//load the table of Clinton's words and frequencies
function preload() {
clContext = loadTable("cl_context.csv", "header");
}
function setup() {
createCanvas(647, 400);
background(51);
// Calling noStroke once here to avoid unecessary repeated function calls
noStroke();
// iterate over the table rows
for(var i=0; i<clContext.getRowCount(); i++){
//- Get data out of the relevant columns for each row -//
var inds = clContext.get(i, "category");
var statements = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity")
}
for (let i = 0; i < statements; randomCategoryStates(i++));
// create your Statement object and add to
// the statements array for use later
inds[i] = new Statement();
console.info(inds);
}
function draw() {
if(mouseClicked == true){
for(var i=0; i<inds.length; i++) {
inds[i].display();
}
}
}
function mouseClicked() {
if((mouseX < width) && (mouseY < height)) {
randomCategoryStates(~~random(CATEGORY));
redraw();
return false;
}
}
// Function to display statements by a random category with each mouse click
function randomCategoryStates(group) {
let idx = inds[group], rnd;
while ((rnd = ~~random(QTY)) == idx);
inds[group] = rnd;
}
// Function to align statements, categories, and polarity
function Statement() {
this.x = x;
this.y = y;
this.xmax = 10;
this.ymax = 4;
this.cat = inds;
this.statement = statements;
this.polarity = polarity;
// set a random x,y position for each statement
this.dx = (Math.random()*this.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.ymax) * (Math.random() < .5 ? -1 : 1);
}
// Attach pseudo-class methods to prototype;
// Maps polarity to color and x,y to random placement on canvas
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
var cols = map(this.polarity == -1, 205, 38, 38);
var cols = map(this.polarity == 0, 148, 0, 211);
var cols = map(this.polarity == 1, 0, 145, 205);
fill(cols);
textSize(14);
text(this.statement, this.x, this.y);
};
编辑: 让我感到困惑的一件事是,我在 Processing 论坛上使用此代码获得的帮助没有包括对 mouseClicked()
函数的调用draw
函数,所以我添加了它。不完全确定我做对了或者是否有必要。
您的代码有很多问题。我将尝试完成所有内容,没有特别的顺序:
为什么需要这些变量?
var x;
var y;
我知道您认为您正在使用它们将位置传递给 Statement
,但您从未设置这些变量!让我们暂时摆脱它们,因为它们什么也没做。这会导致您的代码出错,但我们会在一秒钟内修复它。
看这个for循环:
for(var i=0; i<clContext.getRowCount(); i++){
//- Get data out of the relevant columns for each row -//
var inds = clContext.get(i, "category");
var statements = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity")
}
您在此处读取的是 CSV 文件,但您并未对这些变量执行任何操作。然后你用这个跟进:
for (let i = 0; i < statements; randomCategoryStates(i++));
// create your Statement object and add to
// the statements array for use later
inds[i] = new Statement();
注意 for 循环后面的分号! 这意味着 inds[i] = new Statement()
行在 外部 循环,它不没有任何意义。我也不知道你在用 randomCategoryStates(i++)
部分做什么。
您需要将所有这些组合成一个循环:
for (var i = 0; i < clContext.getRowCount(); i++) {
var category = clContext.get(i, "category");
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity")
inds[i] = new Statement();
}
但这仍然没有任何意义, 因为您永远不会将这些变量传递给您的 Statement
class。那么让我们来看看吧。
我将添加一些评论:
function Statement() {
this.x = x; //when do you ever set the value of x?
this.y = y; //when do you ever set the value of y?
this.cat = inds; //cat is the array that holds all statements? What??
this.statement = statements; //statement is the statements array, but nothing is ever added to that array?
this.polarity = polarity; //when do you ever set the value of polarity?
如您所见,您在这里所做的事情没有多大意义。您需要更改此构造函数,使其接受 参数 ,然后您需要将这些参数传入。类似这样的内容:
function Statement(category, polarity, statement) {
this.category = category;
this.statement = statement;
this.polarity = polarity;
}
现在我们已经有了,我们可以将 for 循环中的行更改为:
inds[i] = new Statement(category, statement, polarity);
但这仍然没有意义。为什么你有单独的数组用于语句、类别和极性?难道你不想要一个包含所有这些的数组,使用 Statement
class 的实例吗?所以让我们去掉 inds
和 polarity
变量,因为它们没有任何用途。
然后我们将该行更改为:
statements[i] = new Statement(category, polarity, statement);
我们还必须更改仍在使用 inds
变量的其他所有地方,但我们在这样做时遇到了其他问题。
让我们从您的 draw()
函数开始:
function draw() {
if (mouseClicked == true) {
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
}
}
所以我猜你只想在按下鼠标时显示任何内容,而不是在未按下鼠标时不显示任何内容?我不确定这是否有意义,但没关系。即便如此,这段代码也没有意义,因为mouseClicked
是函数,不是变量。判断鼠标是否按下,需要用到mouseIsPressed
变量,你不需要 == true
部分。
if (mouseIsPressed) {
我不知道这两个函数应该做什么:
function mouseClicked() {
if ((mouseX < width) && (mouseY < height)) {
randomCategoryStates(~~random(CATEGORY));
redraw();
return false;
}
}
// Function to display statements by a random category with each mouse click
function randomCategoryStates(group) {
let idx = statements[group],
rnd;
while ((rnd = ~~random(QTY)) == idx);
statements[group] = rnd;
}
有更简单的方法来获取随机数据。我现在要删除它们,因为它们带来的麻烦超过了它们的价值。我们可以稍后返回并添加随机逻辑。
现在,让我们看看 Statement
class:
中的 display()
函数
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
var cols = map(this.polarity == -1, 205, 38, 38);
var cols = map(this.polarity == 0, 148, 0, 211);
var cols = map(this.polarity == 1, 0, 145, 205);
fill(cols);
textSize(14);
text(this.statement, this.x, this.y);
};
我们实际上从未声明过 x
、y
、dx
或 dy
变量,所以让我们将它们添加到构造函数中:
this.x = random(width);
this.y = random(height);
this.dx = random(-5, 5);
this.dy = random(-5, 5);
回到display()
函数,这些行没有任何意义:
var cols = map(this.polarity == -1, 205, 38, 38);
var cols = map(this.polarity == 0, 148, 0, 211);
var cols = map(this.polarity == 1, 0, 145, 205);
为什么要声明同一个变量 3 次?为什么要尝试将布尔值映射到数字值?这没有任何意义。现在,让我们摆脱这些行并简化您的逻辑:
if(this.polarity == -1){
fill(255, 0, 0);
}
else if(this.polarity == 1){
fill(0, 255, 0);
}
else{
fill(0, 0, 255);
}
这将使负极性红色、正极性绿色和中性极性蓝色。
现在我们有了这个,我们实际上可以 运行 代码了。当您按住鼠标时,您会看到您的报表随机显示和移动。但是,它们会很快填满您的屏幕,因为您从未清除过旧框架。 只要你想清除旧帧,就需要调用 background()
函数。 我们可以在 draw()
函数的开头,或者就在if(mouseIsPressed)
语句,for 循环之前。
if (mouseIsPressed) {
background(51);
for (var i = 0; i < statements.length; i++) {
如果您进行了所有这些更改,您将拥有一个工作程序。 我敢打赌它仍然不能完全按照您的要求进行。 您将不得不从更简单的开始。您的代码有点乱,这是尝试一次编写整个程序而不是测试小块的结果一次。 这就是我们要求 MCVE, 的原因,因为像这样调试整个过程非常痛苦。您需要开始将目标缩小为更小的部分。
例如,如果您现在想要一次只显示一个语句,从一个更简单的示例草图重新开始,它只显示一个硬编码语句。 在尝试将其集成到您的主程序中之前,请使其完美运行。如果您希望语句按类别排序,那么从一个更简单的示例草图开始,它只显示基于类别的语句,没有任何额外的逻辑。这样一来,如果您对某些特定问题有疑问,您可以 post 那个小代码,它会更容易帮助您。
祝你好运。
我正在分析总统候选人的演讲。我有一个包含以下变量的数据文件:
> names(cl.context)
[1] "id" "category" "statement" "nchar" "polarity"
statement
变量由属于三个句子中的一个 category
的句子填充。 polarity
的取值范围是-1到1,反映了句子是偏向正向、中向还是偏向负向。
我在 p5 中尝试做的是当用户在 canvas 内单击鼠标时,按类别显示语句,随机放置 x,y。陈述本身根据其极性着色。
我终于到了开发者控制台不会抛出任何错误并绘制 canvas 的地步。但是当我在 canvas 中单击时,没有任何反应。没有出现任何陈述。
我是 JavaScript 的新手,因为它没有抛出错误消息,所以我无法解决问题所在。希望在这里得到一些建议。
我的 p5 代码:
var clContext;
var x;
var y;
const STATEMENTS = 118, CATEGORY = 3, QTY = STATEMENTS/CATEGORY | 0,
POLARITY = 3,
statements = Array(STATEMENTS), inds = Array(CATEGORY), polarity = Array(POLARITY);
//load the table of Clinton's words and frequencies
function preload() {
clContext = loadTable("cl_context.csv", "header");
}
function setup() {
createCanvas(647, 400);
background(51);
// Calling noStroke once here to avoid unecessary repeated function calls
noStroke();
// iterate over the table rows
for(var i=0; i<clContext.getRowCount(); i++){
//- Get data out of the relevant columns for each row -//
var inds = clContext.get(i, "category");
var statements = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity")
}
for (let i = 0; i < statements; randomCategoryStates(i++));
// create your Statement object and add to
// the statements array for use later
inds[i] = new Statement();
console.info(inds);
}
function draw() {
if(mouseClicked == true){
for(var i=0; i<inds.length; i++) {
inds[i].display();
}
}
}
function mouseClicked() {
if((mouseX < width) && (mouseY < height)) {
randomCategoryStates(~~random(CATEGORY));
redraw();
return false;
}
}
// Function to display statements by a random category with each mouse click
function randomCategoryStates(group) {
let idx = inds[group], rnd;
while ((rnd = ~~random(QTY)) == idx);
inds[group] = rnd;
}
// Function to align statements, categories, and polarity
function Statement() {
this.x = x;
this.y = y;
this.xmax = 10;
this.ymax = 4;
this.cat = inds;
this.statement = statements;
this.polarity = polarity;
// set a random x,y position for each statement
this.dx = (Math.random()*this.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.ymax) * (Math.random() < .5 ? -1 : 1);
}
// Attach pseudo-class methods to prototype;
// Maps polarity to color and x,y to random placement on canvas
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
var cols = map(this.polarity == -1, 205, 38, 38);
var cols = map(this.polarity == 0, 148, 0, 211);
var cols = map(this.polarity == 1, 0, 145, 205);
fill(cols);
textSize(14);
text(this.statement, this.x, this.y);
};
编辑: 让我感到困惑的一件事是,我在 Processing 论坛上使用此代码获得的帮助没有包括对 mouseClicked()
函数的调用draw
函数,所以我添加了它。不完全确定我做对了或者是否有必要。
您的代码有很多问题。我将尝试完成所有内容,没有特别的顺序:
为什么需要这些变量?
var x;
var y;
我知道您认为您正在使用它们将位置传递给 Statement
,但您从未设置这些变量!让我们暂时摆脱它们,因为它们什么也没做。这会导致您的代码出错,但我们会在一秒钟内修复它。
看这个for循环:
for(var i=0; i<clContext.getRowCount(); i++){
//- Get data out of the relevant columns for each row -//
var inds = clContext.get(i, "category");
var statements = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity")
}
您在此处读取的是 CSV 文件,但您并未对这些变量执行任何操作。然后你用这个跟进:
for (let i = 0; i < statements; randomCategoryStates(i++));
// create your Statement object and add to
// the statements array for use later
inds[i] = new Statement();
注意 for 循环后面的分号! 这意味着 inds[i] = new Statement()
行在 外部 循环,它不没有任何意义。我也不知道你在用 randomCategoryStates(i++)
部分做什么。
您需要将所有这些组合成一个循环:
for (var i = 0; i < clContext.getRowCount(); i++) {
var category = clContext.get(i, "category");
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity")
inds[i] = new Statement();
}
但这仍然没有任何意义, 因为您永远不会将这些变量传递给您的 Statement
class。那么让我们来看看吧。
我将添加一些评论:
function Statement() {
this.x = x; //when do you ever set the value of x?
this.y = y; //when do you ever set the value of y?
this.cat = inds; //cat is the array that holds all statements? What??
this.statement = statements; //statement is the statements array, but nothing is ever added to that array?
this.polarity = polarity; //when do you ever set the value of polarity?
如您所见,您在这里所做的事情没有多大意义。您需要更改此构造函数,使其接受 参数 ,然后您需要将这些参数传入。类似这样的内容:
function Statement(category, polarity, statement) {
this.category = category;
this.statement = statement;
this.polarity = polarity;
}
现在我们已经有了,我们可以将 for 循环中的行更改为:
inds[i] = new Statement(category, statement, polarity);
但这仍然没有意义。为什么你有单独的数组用于语句、类别和极性?难道你不想要一个包含所有这些的数组,使用 Statement
class 的实例吗?所以让我们去掉 inds
和 polarity
变量,因为它们没有任何用途。
然后我们将该行更改为:
statements[i] = new Statement(category, polarity, statement);
我们还必须更改仍在使用 inds
变量的其他所有地方,但我们在这样做时遇到了其他问题。
让我们从您的 draw()
函数开始:
function draw() {
if (mouseClicked == true) {
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
}
}
所以我猜你只想在按下鼠标时显示任何内容,而不是在未按下鼠标时不显示任何内容?我不确定这是否有意义,但没关系。即便如此,这段代码也没有意义,因为mouseClicked
是函数,不是变量。判断鼠标是否按下,需要用到mouseIsPressed
变量,你不需要 == true
部分。
if (mouseIsPressed) {
我不知道这两个函数应该做什么:
function mouseClicked() {
if ((mouseX < width) && (mouseY < height)) {
randomCategoryStates(~~random(CATEGORY));
redraw();
return false;
}
}
// Function to display statements by a random category with each mouse click
function randomCategoryStates(group) {
let idx = statements[group],
rnd;
while ((rnd = ~~random(QTY)) == idx);
statements[group] = rnd;
}
有更简单的方法来获取随机数据。我现在要删除它们,因为它们带来的麻烦超过了它们的价值。我们可以稍后返回并添加随机逻辑。
现在,让我们看看 Statement
class:
display()
函数
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
var cols = map(this.polarity == -1, 205, 38, 38);
var cols = map(this.polarity == 0, 148, 0, 211);
var cols = map(this.polarity == 1, 0, 145, 205);
fill(cols);
textSize(14);
text(this.statement, this.x, this.y);
};
我们实际上从未声明过 x
、y
、dx
或 dy
变量,所以让我们将它们添加到构造函数中:
this.x = random(width);
this.y = random(height);
this.dx = random(-5, 5);
this.dy = random(-5, 5);
回到display()
函数,这些行没有任何意义:
var cols = map(this.polarity == -1, 205, 38, 38);
var cols = map(this.polarity == 0, 148, 0, 211);
var cols = map(this.polarity == 1, 0, 145, 205);
为什么要声明同一个变量 3 次?为什么要尝试将布尔值映射到数字值?这没有任何意义。现在,让我们摆脱这些行并简化您的逻辑:
if(this.polarity == -1){
fill(255, 0, 0);
}
else if(this.polarity == 1){
fill(0, 255, 0);
}
else{
fill(0, 0, 255);
}
这将使负极性红色、正极性绿色和中性极性蓝色。
现在我们有了这个,我们实际上可以 运行 代码了。当您按住鼠标时,您会看到您的报表随机显示和移动。但是,它们会很快填满您的屏幕,因为您从未清除过旧框架。 只要你想清除旧帧,就需要调用 background()
函数。 我们可以在 draw()
函数的开头,或者就在if(mouseIsPressed)
语句,for 循环之前。
if (mouseIsPressed) {
background(51);
for (var i = 0; i < statements.length; i++) {
如果您进行了所有这些更改,您将拥有一个工作程序。 我敢打赌它仍然不能完全按照您的要求进行。 您将不得不从更简单的开始。您的代码有点乱,这是尝试一次编写整个程序而不是测试小块的结果一次。 这就是我们要求 MCVE, 的原因,因为像这样调试整个过程非常痛苦。您需要开始将目标缩小为更小的部分。
例如,如果您现在想要一次只显示一个语句,从一个更简单的示例草图重新开始,它只显示一个硬编码语句。 在尝试将其集成到您的主程序中之前,请使其完美运行。如果您希望语句按类别排序,那么从一个更简单的示例草图开始,它只显示基于类别的语句,没有任何额外的逻辑。这样一来,如果您对某些特定问题有疑问,您可以 post 那个小代码,它会更容易帮助您。
祝你好运。