Estoy tratando de centrar la ventana gráfica en un objeto y acercar/alejar cuando hago clic en un botón. Quiero tener una animación. Para hacer esto, estoy usando setInterval y moviendo la ventana gráfica en incrementos así:
const objectCenterCoordenates = { x: Math.round(rect1.left + rect1.width / 2), y: Math.round(rect1.top + rect1.height / 2) }; const centeredCanvasCoordenates = { x: objectCenterCoordenates.x - canvas.width / 2, y: objectCenterCoordenates.y - canvas.height / 2 }; let currentPoint = { x: Math.round(canvas.viewportTransform[4]) * -1, y: Math.round(canvas.viewportTransform[5]) * -1 }; console.log("Start animation"); let animation = setInterval(() => { console.log("New frame"); if (canvas.getZoom() !== 2) { let roundedZoom = Math.round(canvas.getZoom() * 100) / 100; let zoomStep = roundedZoom > 2 ? -0.01 : 0.01; let newZoom = roundedZoom + zoomStep; canvas.zoomToPoint( new fabric.Point(currentPoint.x, currentPoint.y), newZoom ); } let step = 5; let vpCenter = { x: Math.round(canvas.getVpCenter().x), y: Math.round(canvas.getVpCenter().y) }; if ( vpCenter.x === objectCenterCoordenates.x && vpCenter.y === objectCenterCoordenates.y ) { console.log("Animation Finish"); clearInterval(animation); } let xDif = Math.abs(vpCenter.x - objectCenterCoordenates.x); let yDif = Math.abs(vpCenter.y - objectCenterCoordenates.y); let stepX = Math.round(vpCenter.x) > Math.round(objectCenterCoordenates.x) ? -step : step; if (Math.abs(xDif) < step) stepX = Math.round(vpCenter.x) > Math.round(objectCenterCoordenates.x) ? -xDif : xDif; let stepY = Math.round(vpCenter.y) > Math.round(objectCenterCoordenates.y) ? -step : step; if (Math.abs(yDif) < step) stepY = Math.round(vpCenter.y) > Math.round(objectCenterCoordenates.y) ? -yDif : yDif; currentPoint = { x: currentPoint.x + stepX, y: currentPoint.y + stepY }; canvas.absolutePan(new fabric.Point(currentPoint.x, currentPoint.y)); }, 4);Pero a veces, no he podido determinar por qué, se atasca en un bucle que mueve unos pocos píxeles en un sentido y luego retrocede en el otro. Y el zoom está bien implementado, ya que es posible llegar al objeto antes de que termine de acercar/alejar.
Aquí hay un codepen con mi código: https://codepen.io/nilsilva/pen/vYpPrgq
Agradecería cualquier consejo sobre cómo mejorar mi algoritmo.
Parece que tiene un requisito de coincidencia exacta para su clearInterval...
if ( vpCenter.x === objectCenterCoordenates.x && vpCenter.y === objectCenterCoordenates.y ) { console.log("Animation Finish"); clearInterval(animation); } El caso que describe stuck in a loop moving one way then going back the other se debe a que nunca se hace la coincidencia exacta, podría deberse al paso que está tomando o podría ser un problema de redondeo.
Puede usar Math.hypot para verificar si los dos puntos están lo suficientemente cerca, lea más aquí:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot
La condición se verá así:
if (Math.hypot( vpCenter.x - objectCenterCoordenates.x, vpCenter.y - objectCenterCoordenates.y ) < step) { console.log("Animation Finish"); clearInterval(animation); }