【问题标题】:p5.js code doesn't throw errors, but won't load on mouse clickp5.j​​s 代码不会抛出错误,但不会在鼠标单击时加载
【发布时间】:2016-06-08 21:45:07
【问题描述】:

我正在分析总统候选人的演讲。我有一个包含以下变量的数据文件:

> names(cl.context)
[1] "id"        "category"  "statement" "nchar"     "polarity" 

statement 变量由三个句子中的一个 category 填充。 polarity 的范围从 -1 到 1,反映句子是否具有正面偏见、中性或负面偏见。
我在 p5 中尝试做的是当用户在画布内单击鼠标时,按类别显示语句,随机 x,y 位置。语句本身根据它们的极性着色。
我终于到了开发人员控制台不会抛出任何错误并绘制画布的地步。但是当我在画布内单击时,什么也没有发生。没有语句出现。
我对 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);
};  

编辑:让我感到困惑的一件事是,我在处理论坛上获得的有关此代码的帮助不包括在 draw 函数中调用 mouseClicked() 函数,所以我补充说。不完全确定我这样做是否正确,或者是否有必要。

【问题讨论】:

  • 您能否提供数据文件,或者最好将您的代码缩小到minimal reproducible example
  • 你为什么要mouseIsPressed &lt; width?你认为这会做什么? mouseIsPressed 不是布尔值,width 不是数字吗?
  • 感谢mouseIsPressed、@Kevin Workman 的提醒。正如我所说,我对 JavaScript 很陌生。我已更改为mouseXmouseY。至于缩小我的代码范围,如果我这样做,我担心不会出现解决方案,因为我的代码没有在开发者控制台中抛出任何错误,所以我不确定问题出在哪里。您可以找到 'cl_context.csv data file here on GitHub. 抱歉,我最初没有包含它。

标签: javascript canvas mouseevent p5.js


【解决方案1】:

你的代码有很多事情要做。我将尝试完成所有内容,没有特定的顺序:

为什么需要这些变量?

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 类。那么让我们来看看吧。

我将添加一些 cmets:

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?

如您所见,您在这里所做的事情没有多大意义。您需要更改此构造函数,使其接受 arguments,然后您需要传入这些参数。像这样:

function Statement(category, polarity, statement) {
  this.category = category;
  this.statement = statement;
  this.polarity = polarity;
}

现在我们有了,我们可以将 for 循环中的行更改为:

inds[i] = new Statement(category, statement, polarity);

但这仍然没有意义。为什么要为语句、类别和极性设置单独的数组?您不只想要一个使用Statement 类的实例来保存所有这些的数组吗?所以让我们去掉indspolarity 变量,因为它们没有任何用途。

然后我们将该行更改为:

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 类中的 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);
};

我们从未真正声明过xydxdy 变量,所以让我们将它们添加到构造函数中:

  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 的原因,因为像这样调试整个事情非常痛苦。您需要开始将目标缩小为更小的部分。

例如,如果您现在希望一次只显示一个语句,从一个更简单的示例草图开始,它只显示一个硬编码语句。在您尝试将其集成到您的主程序之前,让它完美运行。如果您希望语句按类别排序,那么从一个更简单的示例草图开始,它只显示基于类别的语句,没有任何额外的逻辑。这样,如果您对某个特定问题有疑问,您可以发布该小代码,它会更容易为您提供帮助。

祝你好运。

【讨论】:

  • 没错,这并不完全符合我的设想,但它完全有效。谢谢你。 :) 非常感谢您的“超越电话”响应。
  • 我确实断言,我从您的回复中学到了更多,@KevinWorkman,比我在过去 3 周的“JavaScript:权威指南”中学到的更多。非常感谢...
  • @LesleyLathrop 哈哈,听到这个消息真棒,谢谢。请不要犹豫发布另一个问题,只要确保您使用尽可能小的步骤即可。这只会让您的生活更轻松!
  • 嗨@KevinWorkman。我按照你的指示做了,昨天的动画效果很好。但是今天早上突然间,它不再起作用了,尽管我没有做任何不同的事情。现在发生的情况是,当我按下鼠标时,每个语句(实际上,每个语句的一半)出现在画布上,但它们不再移动。它们只是静态的。这不是this.dx = random(-5, 5);this.dy = random(-5, 5) 所做的,即让语句随机移动吗?我一直在阅读 p5.js 的书,看看我是否能弄清楚,但是,唉,没有。
  • @LesleyLathrop 一定发生了一些变化。您将不得不尝试将其缩小到minimal reproducible example。这可能涉及从头开始,一次只添加一行,直到您发现问题(或者,更有可能的是,看不到问题!)。这听起来可能令人讨厌,但无论如何你都应该这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 2015-01-04
  • 2019-07-15
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
相关资源
最近更新 更多