Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

200
Visualizações
Zoom In Canvas And Then Zooming Out in a different mouse position Breaks Background Display

I'm trying to implement a zoom function on my canvas keeping the mouse position relative to where it was before.

This function accomplishes it almost. And here is a full example: 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)



  }

I have an image set as the background of the canvas that gets drawn like this:

    ctx.drawImage(
      this.image,
      0,
      0
    )

The problem is that if I do something like the following:

  1. Place the mouse on center of screen.
  2. Zoom In (Works well)
  3. Move the mouse to another place.
  4. Keep Zooming In
  5. Zoom Out All the way to scale being 1

The zoom out eventually ends up translating the canvas in the wrong way and my canvas image appears "sliced" or incomplete due to incorrect translations or scales. This happens just before the scale becomes 1, then it fixes itself because I have a resetTransform() call when scale = 1.

I'm expecting that no matter how I move the mouse I eventually zoom out and end up with the original transform matrix (identity matrix).

Can anyone help me spot what I'm doing wrong with my transforms. I don't quite get why it works perfect if I don't move the mouse, but stops working if I move the mouse in a zoomed in state and then zoom out.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

You are looking to "understand why this mouse out algorithm is not working", I would not say it is not working as there are no errors, I tested the zoom on your codepen, and it feels fine to me...
Your zoom is relative to the position of the mouse, interacting with it feels intuitive and smooth.

I did some clean up to your code:
https://codepen.io/heldersepu/pen/LYjYEyL?editors=0010

The only issue I see is translating without considering that image could be out of the bounds,
see this code:

  context.translate(x, y);
  context.scale(zoom, zoom);
  context.translate(-x, -y);

That code will be fine in a world map where the image is really large and wraps, I believe that google maps uses a similar logic, and it's a perfect use case there, but you are not considering the limitation of your image.

Zooming in your image we are not going to see the problem because the image is always padded, but going out you can be moving out of the bounds of the image if we are on the edge.
Here is an example:

  • move the mouse to the bottom left
  • zoom in a few times
  • move the mouse to the bottom right
  • zoom out

the resulting canvas looks something like:

What to do on that case?
An option could be not to translate when we zoom out:

  if (wheel > 0) context.translate(x, y);
  context.scale(zoom, zoom);
  if (wheel > 0) context.translate(-x, -y);

Or you could conditionally translate on one axis and not the other depending on the mouse position, but the correct solution is for you to decide, you have to test and see what you like.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda