在 p5js 中绘制和动画多个矩形

问题描述 投票:0回答:1

我有一个对象数组,其中每个对象都包含特定矩形的详细信息。我制作了一个动画矩形函数,这样当给函数 targetX 和 targetY 位置以及数组中对象的索引时,它会将矩形动画到该位置。

函数这样做是成功的,但是当我将该索引(比如 0)与数组的另一个索引(让它为 1)交换时,那个特定的矩形(索引 1 的矩形)也移动到我为前一个矩形设置动画的位置(索引 0 的矩形)。它就像索引链接到那个特定位置。

这是我的代码的最小可重现示例

let arr = [
    {
        value:3,
        height: -204,
        width: 50,
        posX: 315,
        posY: 350,
        color: '#8D72E1'
    },
    {
        value: 1,
        height: -68,
        width: 50,
        posX: 365,
        posY: 350,
        color: '#8D72E1'
    }
];


function setup() {
  createCanvas(windowWidth, windowHeight * 2);
  background(220);
  button = createButton("Swap");
  button.position(0,0);
  button.mousePressed(swap);
}

function addElement()
{
    drawObj();
    moveRectToPosition(200, 200, 0.09, 0);
}

function moveRectToPosition(targetX, targetY, speed, index) {
    let isAnimationRunning = true;
  
    function animate() {
      if (!isAnimationRunning) {
        return;
      }
  
      let distanceX = targetX - arr[index].posX;
      let distanceY = targetY - arr[index].posY;
      let distance = dist(arr[index].posX, arr[index].posY, targetX, targetY);
  
      if (distance === 0) {
        isAnimationRunning = false;
        return;
      }
  
      let moveX = distanceX * speed;
      let moveY = distanceY * speed;
  
      arr[index].posX += moveX;
      arr[index].posY += moveY;
  
      background(220);

      drawObj();
      requestAnimationFrame(animate);
    }
  
    animate();
  }
  
function drawObj()
{
    for(let i=0;i<arr.length;i++)
    {
        fill(arr[i].color);
        rect(arr[i].posX,arr[i].posY,arr[i].width,arr[i].height,8);
    }
}


function swap()
{
    let temp = arr[1];
    arr[1] = arr[0];
    arr[0] = temp;

}


setTimeout(() => {
  addElement();
},500);
html, body { margin: 0; padding: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

这是这段代码的预览: https://editor.p5js.org/ayushap05/full/hm4ty5Qck

当按下交换按钮时,第二个矩形也从它的位置移动到第一个矩形的位置。

我认为问题可能出在交换对象时,但是在交换前后进行控制台日志后我发现交换对象后,动画函数开始自动调用。

javascript animation javascript-objects p5.js
1个回答
0
投票

一个问题是距离在这里永远不会完全达到零:

      let distance = dist(arr[index].posX, arr[index].posY, targetX, targetY);

      if (distance === 0) {
        isAnimationRunning = false;
        return;
      }

浮点的性质是这样的,当你将位置越来越接近目标,剩余距离的一小部分:

      let moveX = distanceX * speed;
      let moveY = distanceY * speed;
  
      arr[index].posX += moveX;
      arr[index].posY += moveY;

distance
的值逐渐变小,但不会达到零。因此,当您交换数组中的两个元素时,
animate
函数仍在运行,并将索引 0 处的任何内容移动到原始调用中指定的位置
moveRectToPosition
:

let arr = [
    {
        value:3,
        height: -204,
        width: 50,
        posX: 315,
        posY: 350,
        color: '#8D72E1'
    },
    {
        value: 1,
        height: -68,
        width: 50,
        posX: 365,
        posY: 350,
        color: '#8D72E1'
    }
];

let distDisp;

function setup() {
  createCanvas(windowWidth, windowHeight * 2);
  background(220);
  button = createButton("Swap");
  button.position(10,10);
  button.mousePressed(swap);
  
  distDisp = createInput('');
  distDisp.position(10, 50);
  distDisp.size(200);
}

function addElement()
{
    drawObj();
    moveRectToPosition(200, 200, 0.09, 0);
}

function moveRectToPosition(targetX, targetY, speed, index) {
    let isAnimationRunning = true;
  
    function animate() {
      if (!isAnimationRunning) {
        return;
      }
  
      let distanceX = targetX - arr[index].posX;
      let distanceY = targetY - arr[index].posY;
      let distance = dist(arr[index].posX, arr[index].posY, targetX, targetY);
  
      if (distance === 0) {
        isAnimationRunning = false;
        distDisp.value('ZERO');
        return;
      } else {
        distDisp.value(distance);
      }
  
      let moveX = distanceX * speed;
      let moveY = distanceY * speed;
  
      arr[index].posX += moveX;
      arr[index].posY += moveY;
  
      background(220);

      drawObj();
      requestAnimationFrame(animate);
    }
  
    animate();
  }
  
function drawObj()
{
    for(let i=0;i<arr.length;i++)
    {
        fill(arr[i].color);
        rect(arr[i].posX,arr[i].posY,arr[i].width,arr[i].height,8);
    }
}


function swap()
{
    let temp = arr[1];
    arr[1] = arr[0];
    arr[0] = temp;

}


setTimeout(() => {
  addElement();
},500);
html, body { margin: 0; padding: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.