Estoy tratando de implementar una función de zoom en mi lienzo manteniendo la posición del mouse en relación con donde estaba antes.
Esta función lo logra casi. Y aquí hay un ejemplo completo: https://codepen.io/PJEstrada006/pen/dyRxVXE?editors=0011
public zoom_wheel_canvas_translate(event): void { // this is the illusionary point on UI that we wish to stay locked on let point = this.mouse_position; const wheel = event.deltaY < 0 ? 1 : -1; // Compute zoom factor. let zoomIntensity = 0.2; let zoom = Math.exp(wheel * zoomIntensity); this.scale = this.scale * zoom; if (this.scale <= 1) { this.canvas_ctx.setTransform(1, 0, 0, 1, 0, 0); this.scale = 1; return } if (this.scale >= 30) { this.scale = 30 } this.canvas_ctx.clearRect( 0, 0, this.canvas_elm.width, this.canvas_elm.height ); let transform = this.canvas_ctx.getTransform(); this.canvas_ctx.resetTransform(); this.canvas_ctx.translate(point.x, point.y); this.canvas_ctx.scale(zoom, zoom); this.canvas_ctx.translate(-point.x, -point.y); this.canvas_ctx.transform(transform.a, transform.b, transform.c, transform.d, transform.e, transform.f) let transform_new = this.canvas_ctx.getTransform(); console.log('a', transform.a, 'd', transform.d) console.log('e', transform.e, 'f', transform.f) }
Tengo una imagen establecida como fondo del lienzo que se dibuja así:
ctx.drawImage( this.image, 0, 0 )
El problema es que si hago algo como lo siguiente:
El alejamiento finalmente termina traduciendo el lienzo de manera incorrecta y la imagen de mi lienzo aparece "cortada" o incompleta debido a traducciones o escalas incorrectas. Esto sucede justo antes de que la escala se convierta en 1, luego se corrige solo porque tengo una llamada resetTransform() cuando la escala = 1.
Espero que, sin importar cómo mueva el mouse, eventualmente aleje el zoom y termine con la matriz de transformación original (matriz de identidad).
¿Alguien puede ayudarme a detectar qué estoy haciendo mal con mis transformaciones? No entiendo muy bien por qué funciona perfectamente si no muevo el mouse, pero deja de funcionar si muevo el mouse en un estado de zoom y luego lo alejo.
Está buscando "comprender por qué este algoritmo de mouse out no funciona", no diría que no funciona ya que no hay errores, probé el zoom en su codepen y me parece bien...
Su zoom es relativo a la posición del mouse, interactuar con él se siente intuitivo y fluido.
Hice algo de limpieza en tu código:
https://codepen.io/heldersepu/pen/LYjYEyL?editors=0010
El único problema que veo es traducir sin considerar que la imagen podría estar fuera de los límites,
ver este código:
context.translate(x, y); context.scale(zoom, zoom); context.translate(-x, -y);
Ese código estará bien en un mapa mundial donde la imagen es realmente grande y envolvente, creo que Google Maps usa una lógica similar, y es un caso de uso perfecto allí, pero no está considerando la limitación de su imagen.
Al hacer zoom en su imagen, no vamos a ver el problema porque la imagen siempre está rellena, pero al salir, puede estar saliendo de los límites de la imagen si estamos en el borde.
Aquí hay un ejemplo:
el lienzo resultante se parece a:
¿Qué hacer en ese caso?
Una opción podría ser no traducir cuando alejamos:
if (wheel > 0) context.translate(x, y); context.scale(zoom, zoom); if (wheel > 0) context.translate(-x, -y);
O podría traducir condicionalmente en un eje y no en el otro dependiendo de la posición del mouse, pero la solución correcta es para que usted decida, debe probar y ver lo que le gusta.