繁体   English   中英

我将如何在画布上的缩放上实现移动原点?

[英]How would I go about implementing a moving origin on zoom on a canvas?

我在实现自定义缩放时遇到了一些问题。

我的大部分缩放功能都在工作,但是,它“围绕”原点缩放,在这种情况下,是网格的左上角。 相反,我希望它围绕光标放大。

画布和窗口一样大(我将在画布顶部添加 UI,有点像 photoshop),我正在画布上绘制一个宽度 x 高度像素大的网格,“放大”一个PIXEL_SIZE 的因素。

重要的部分,这个事件处理程序就在这里

const WIDTH = 32;
const HEIGHT = 24;
const PIXEL_SIZE = 10;
...
// controls how big the grid is
let scale = 1.5;

// controls where the grid is drawn, 
// starts exactly in the middle of the screen
let originX = canvas.width / 2 - (WIDTH * PIXEL_SIZE * scale) / 2;
let originY = canvas.height / 2 - (HEIGHT * PIXEL_SIZE * scale) / 2;

function zoom(event) {
  event.preventDefault();

  const wheel = event.deltaY < 0 ? 1 : -1;
  const z = Math.exp(wheel * 0.05);

  scale *= z;

  // this adjusts the scale just fine-ish
  // however, the origin needs to move in relation
  // to the cursor position
}

window.addEventListener("wheel", zoom, { passive: false });

我已经尝试了一些东西,但由于某种原因,我的大脑目前无法进行数学运算。 我试过使用ctx.translatectx.scale ,但它们似乎都没有做我想做的事情(尽管我可能用错了它们)。

这是一个JSFiddle ,里面有我到目前为止的内容。 如果有人能看一眼,那就太棒了。

很酷的代码。 放大特定点可能很棘手,可以通过多种方式完成。 主要问题是在接近最大变焦时,您究竟想放大到什么地方以及以什么比例/多快。

我建议从定义偏移量开始

...
// starts exactly in the middle of the screen
let originX = canvas.width / 2 - (WIDTH * PIXEL_SIZE * scale) / 2;
let originY = canvas.height / 2 - (HEIGHT * PIXEL_SIZE * scale) / 2;

let offsetX = originX;
let offsetY = originY;
...

然后在zoom回调中使用MouseEvent event.xevent.y计算偏移量,类似于:

  function zoom(event) {
      ...

      // event.x and event.y returns the position relative to ...something
      // To properly scale the values, you could get the relative position
      // and size of the canvas and find your offset, for example
      // (viwportsizeX - canvasSizeX) + event.X / (scaleX) and the same for Y 
      // when the position is realtive to the viewport
      offsetX = event.x;
      offsetY = event.y;
  }

当然,还要更新动画主循环中的偏移量:

function animate() {
    requestAnimationFrame(animate);
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    bufferCtx.putImageData(data, 0, 0);

    ctx.drawImage(
        bufferCanvas,
        originX - offsetX,
        originY - offsetY,
        WIDTH * PIXEL_SIZE * scale,
        HEIGHT * PIXEL_SIZE * scale
    );
 }

通过计算相对于被放大的画布元素的偏移量,可以准确地放大光标点。

JSFiddle

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM