I have an array of objects where each object contains the details of a particular rectangle. I made an animate rectangle function such that when given targetX and targetY position to the function and the index of the object in array, it animates the rectangle to that position.
The function is successful in doing so but when I swap that index (say 0) with another index(let it be 1) of array, that particular rectangle(rectangle of index 1) also moves to the position where I animated the previous rectangle(rectangle of index 0). Its like the index is linked to that specific position.
Here is a minimum reproducible example of my code
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>
And here is the preview of this code: https://editor.p5js.org/ayushap05/full/hm4ty5Qck
When the swap button is pressed the 2nd rectangle also moves from its position to the position of 1st rectangle.
I thought that problem might be while swapping the objects, but after doing console log before and after the swapping I found out that after the objects are swapped, the animation function is begin called automatically.
One issue is that distance never quite reaches zero here:
let distance = dist(arr[index].posX, arr[index].posY, targetX, targetY);
if (distance === 0) {
isAnimationRunning = false;
return;
}
The nature of floating points is such that as you move the position closer and closer to the target by a fraction of the remaining distance:
let moveX = distanceX * speed;
let moveY = distanceY * speed;
arr[index].posX += moveX;
arr[index].posY += moveY;
The value of distance
gets progressively smaller, but doesn't reach zero. Therefore when you swap the two elements in the array the animate
function is still running and moves whatever happens to be at index 0 to the position specified in the original call to 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>