【问题标题】:Canvas: X value changing in console but not in canvas画布:X 值在控制台中更改,但在画布中不更改
【发布时间】:2017-09-30 03:21:57
【问题描述】:

我正在从 API 中提取坐标并将它们设置为 Rectangle 类。循环遍历数据数组时,我可以创建每个矩形,但是在移动它们时,我遇到了麻烦。

x 坐标在 move() 的 setInterval 处在控制台中发生变化,但方块本身并没有在屏幕上移动。

当我在move() 中有c.clearRect(0,0,innerWidth, innerHeight); 时,所有矩形都会消失。没有它,它们根本不动。

if(this % 6 === 0){
          c.fillStyle = "#000";
        } else {
        c.fillStyle = "" + this.color + "";

指的是数据数组,如果索引可以被 6 整除,则将该正方形设为黑色。尽管在这种情况下,它不起作用。

这是我的代码:

<script>
const canvas = document.getElementById("canvas");
const c = canvas.getContext('2d');

let xhReq = new XMLHttpRequest();
 xhReq.open("GET", "(api here)", false);
 xhReq.send(null);
 const data = JSON.parse(xhReq.responseText);

class Rectangle {
  constructor(x, y, w, h, vx, color) {
      this.x = x;
      this.y = y;
      this.w = w;
      this.h = h;
      this.vx = vx;
      this.color = color;
    }
    draw() {
        c.fillRect(this.x, this.y, this.w, this.h);
        if(this % 6 === 0){
          c.fillStyle = "#000";
        } else {
        c.fillStyle = "" + this.color + "";
      }

    }
    move(){
    c.clearRect(0,0,innerWidth, innerHeight);
     if (this.x > 800 || this.x < 0){
        this.vx = -this.vx;
      }
       this.x+= this.vx;
      c.beginPath();
       console.log("here is the x value:" + this.x);

  }
}

 for(let i=0; i<data.length; i++){
    let info = data[i]
    let rec = new Rectangle(info.x, info.y, info.w, info.h, info.vx, info.color);
    rec.draw();
    setInterval(function() {
      rec.move();
    }, 50);
  }
</script>

【问题讨论】:

  • setInterval(function() { rec.move(); }, 50 * i);
  • 不幸的是@MarouenMhiri 并没有改变任何东西

标签: javascript html canvas html5-canvas


【解决方案1】:

你的代码有很多问题。

  1. 您只是在更新位置,而不是再次进行绘图调用。 将rec.draw() 调用移到您的setInterval 中。 请记住,订购很重要。理想情况下,您应该先update(),然后再draw()

    setInterval(function() {
      rec.move();
      rec.draw();
    }, 50);
    
  2. 此外,请从move() 函数中删除这些行,因为您不想在每次更新变量时都清除画布。清除 draw() 函数开头的画布。另外,由于您处理的是fillRect(),因此您不需要包含beginPath()

    c.clearRect(0,0,innerWidth, innerHeight);
    ...
    c.beginPath();
    
  3. 您首先需要指定fillStyle,然后使用fillRect() 继续绘制矩形,而不是相反。 draw() 函数应如下所示:

    draw() {
        c.clearRect(0, 0, innerWidth, innerHeight);
        if(this % 6 === 0){               // <-- Not really sure what is going on here
            c.fillStyle = "#000";
        } else {
            c.fillStyle = "" + this.color + "";
        }
        c.fillRect(this.x, this.y, this.w, this.h);
    }
    
  4. 在点号 #3 的代码块中,您在类本身的实例上使用模运算符 %,即 this,而不是数字。我假设你想要像this.x 这样的东西。

除了上述几点之外,您的代码仍然存在一些问题。但这超出了这个问题的范围。

已编辑以下最终解决方案:

const canvas = document.getElementById("canvas");
const context = canvas.getContext('2d');
const xhr = new XMLHttpRequest();

// Usng var as we are making an async request and need to update this variable
var data = null;

// An empty array to store our rectangles
var collection = [];

// Using an asyn request as we don't necessarily need to wait for this step
xhr.open('GET', '<api>', true)

xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
        if(xhr.status >= 200 && xhr.status < 300){
            data = JSON.parse(xhr.responseText);
            dataLoaded();
        } else {
            // The request gave an error response
        }
    }
};

xhr.send();

function dataLoaded(){
    for(let i = 0; i < data.length; i++){
        let info = data[i];
        collection.push(new Rectangle(info.x, info.y, info.w, info.h, info.vx, info.color));
    }

    setInterval(animate, 50);
}

function animate(){
    context.clearRect(0, 0, canvas.width, canvas.height);

    for(let i = 0; i < collection.length; i++){
        let rect = collection[i];

        rect.update();
        rect.draw();
    }
}

class Rectangle {

    constructor(x, y, w, h, vx, color){
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.vx = vx;
        this.color = color;
    }

    update(){
        if (this.x > 800 || this.x < 0){
            this.vx = -this.vx;
        }
        this.x += this.vx;
    }

    draw(){
        context.fillStyle = this.color;
        context.fillRect(this.x, this.y, this.w, this.h);
    }

}

【讨论】:

  • 谢谢,这让我离我需要的地方更近了。 (this % 6 === 0 ) 指的是数据数组。如果数组的索引可以被 6 整除,则将其设为黑色。因此,在遍历数据数组时仅指此。 move 函数效果很好(谢谢!),但是 draw 函数会导致正方形快速闪烁,因为它每 50 毫秒清除一次画布。有没有办法解决这个问题?
  • 好的。我明白你想做什么。但它不起作用,因为this 不是 number 而是 object 并且对对象的任何数学运算都将返回 NaN(不是数字)。
  • 正如我在回答末尾所说的那样。您在此处构建代码的方式存在很多问题。由于执行顺序,矩形闪烁。代码在继续绘制另一个矩形之前不断清除画布。就好像您的代码正在与自己作斗争。老实说,在这里进行更改只会使情况恶化。整个脚本需要更改。如果你愿意,我可以指导你。
  • 那真的很有帮助,谢谢!我在linkedin上请求你,或者你可以给我发电子邮件amandajmunch@gmail.com
猜你喜欢
  • 1970-01-01
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-01-24
  • 2017-11-15
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多