Actualización: encontré una solución a mi propia pregunta. Vea la respuesta a continuación.
Estoy trabajando en una función de centro y zoom para mi lienzo. Cuando el usuario hace clic en la pantalla, el punto en el que se hizo clic debe moverse al centro y acercarse.
Tengo dos lienzos. El primer lienzo se representa en la pantalla y muestra una parte del segundo lienzo. El segundo lienzo no es un verdadero "OffscreenCanvas" sino que se almacena solo en la memoria.
La panorámica y el zoom se realizan en incrementos mediante requestAnimationFrame.
Dado que probablemente sea una buena idea dejar que el "lienzo fuera de la pantalla" permanezca inalterado, intento aplicar todos los cambios al lienzo en pantalla. La panorámica es bastante simple, pero ¿cómo combinar la panorámica y el zoom?
En el código actual, el zoom se logra reduciendo el tamaño de la ventana gráfica (viewportWidth o Height -= viewportWidth o Height * 0.01). Luego compenso la ventana gráfica más pequeña haciendo una panorámica un poco más de lo que hubiera hecho de otra manera (+ viewportWidth o Height * 0.01 * 0.5).
[![Imagen que explica mi problema con la panorámica y el zoom][1]][1]
Sin embargo, con esta solución, la pantalla se centra en un punto a la izquierda de donde hizo clic el usuario. ¿Puedes decirme qué estoy haciendo mal?
Alternativamente, si hay una mejor manera de hacerlo, me encantaría saberlo.
Esto es lo que he encontrado hasta ahora:
// Global variables: onscreenCanvas offscreenCanvas viewportPositionX viewportPositionY viewportWidth viewportHeight document.addEventListener('click', (event) => { let counter = 0 // Distance from clicked point to center of screen: let panX = -(window.innerWidth/2 - event.pageX) let panY = -(window.innerHeight/2 - event.pageY) function panAndZoom() { // Pan one percent of the distance: viewportPositionX += panX * 0.01 viewportPositionY += panY * 0.01 let ctx = onscreenCanvas.getContext('2d') ctx.drawImage( offscreenCanvas, viewportPositionX + viewportWidth * 0.01 * 0.5, viewportPositionY + viewportHeight * 0.01 * 0.5, viewportWidth - viewportWidth * 0.01, viewportHeight - viewportHeight * 0.01, 0, 0, window.innerWidth, window.innerHeight) // Shrink viewport by one percent: viewportWidth -= viewportWidth * 0.01 viewportHeight -= viewportHeight * 0.01 counter++ if (counter <= 100) { window.requestAnimationFrame(panAndZoom) } } panAndZoom() }) [1]: https://i.stack.imgur.com/b9DR7.pngBien, entonces encontré una solución. En lugar de disminuir el tamaño de la ventana gráfica para cada redibujado, debería haber aumentado el tamaño de la escala.
let scaleX = viewportWidth * 0.005 let scaleY = viewportHeight * 0.005 [...] ctx.drawImage( offscreenCanvas, viewportPositionX + scaleX * 0.5, viewportPositionY + scaleY * 0.5, viewportWidth - scaleX, viewportHeight - scaleY, 0, 0, window.innerWidth, window.innerHeight) scaleX += viewportWidth * 0.005 scaleY += viewportHeight * 0.005