Quiero animar un rectángulo en un lienzo html. cuando el usuario haga clic en el lienzo, el rectángulo comenzará su animación e irá a la posición en la que se hizo clic. Usé delta x e y para sumar y restar píxeles de la posición x e y del rectángulo. Pero el problema con esta solución es que no puedo encontrar una manera de hacer que el rectángulo se anime en un camino recto.
Mi código:
'use strict' const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') const ratio = Math.ceil(window.devicePixelRatio) let height = window.innerHeight let width = window.innerWidth canvas.height = height * ratio canvas.width = width * ratio canvas.style.height = `${height}px` canvas.style.width = `${width}px` ctx.setTransform(ratio, 0, 0, ratio, 0, 0) let position = { x: 0, y: 0, deltaX: 0, deltaY: 0, size: 20 } let move = { x: 0, y: 0, } function animate() { if (position.x === move.x && position.y === move.y) { cancelAnimationFrame() } if (position.x !== move.x) { ctx.fillRect(position.x, position.y, position.size, position.size) position.x += position.deltaX } if (position.y !== move.y) { ctx.fillRect(position.x, position.y, position.size, position.size) position.y += position.deltaY } requestAnimationFrame(animate) } function moveTo(x, y) { move.x = x move.y = y position.deltaX = position.x > x ? -1 : 1 position.deltaY = position.y > y ? -1 : 1 animate() } canvas.addEventListener('click', (event) => { moveTo(event.clientX, event.clientY) }) ctx.fillRect(position.x, position.y, position.size, position.size) <canvas id="canvas"> </canvas>Si hace clic en el lienzo, el rectángulo comenzará a moverse, pero tomará un camino extraño, no puedo encontrar la manera de ir directamente a la posición en la que se hizo clic.
ver demostración en la página de Github
Aquí está la muestra de Matemáticas de algo que hice hace un tiempo...
Si hay algo que no entiendes ahí pregunta
En su código, se movía "raro" porque sus valores delta siempre eran 1 o -1, sin fracciones, lo que limita la forma en que el objeto puede viajar, en cambio, hacemos nuestros cálculos usando el ángulo.
const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') let player = { x: 0, y: 0, size: 10, delta: { x: 0, y: 0 }, move: { x: 0, y: 0 } } function animate() { let a = player.x - player.move.x; let b = player.y - player.move.y; if (Math.sqrt( a*a + b*b ) < 2) { player.delta = { x: 0, y: 0 } } player.x += player.delta.x player.y += player.delta.y ctx.fillRect(player.x, player.y, player.size, player.size) requestAnimationFrame(animate) } function moveTo(x, y) { player.move.x = x player.move.y = y let angle = Math.atan2(y - player.y, x - player.x) player.delta.x = Math.cos(angle) player.delta.y = Math.sin(angle) } canvas.addEventListener('click', (event) => { moveTo(event.clientX, event.clientY) }) animate() <canvas id="canvas"></canvas>