首页 > 解决方案 > 相对于鼠标坐标缩放画布

问题描述

我有一个非常简单的应用程序,我在画布上完美地绘制了图像。我正在通过 image.width/2、image.height/2 翻译上下文,并将目标点设置为 -image.width/2、-image.height/2。

        function draw() {
        window.canvas = document.getElementById('canvas');
        window.ctx = canvas.getContext('2d');
        window.image = document.createElement("img");
        image.onload = function() {
            canvas.width = image.width;
            canvas.height = image.height;
            ctx.clearRect(0,0,canvas.width,canvas.height);
            ctx.translate(image.width/2,image.height/2);
            ctx.drawImage(image,-image.width/2,-image.height/2);
        };
        image.src = 'rec.JPG';
    }

这是按应有的方式显示图像。所以考虑到这个概念,如果我想在画布中心制作图像的中心点,我应该像上面那样做。现在,我希望用户单击画布,我正在获取鼠标坐标。然后我想缩放这个图像并重新绘制画布,这样用户就会在中心看到图像的那部分(缩放版本)。代码如下:

        function zoom(evt) {
        var x = getMousePos(canvas, evt).x;
        var y = getMousePos(canvas, evt).y;
        canvas.width = image.width;
        canvas.height = image.height;
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.translate(x,y);
        ctx.scale(1.5, 1.5);
        ctx.drawImage(image,-x,-y);
    }

    function getMousePos(canvas, evt) {
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };
    }

但不知何故,我没有得到正确的结果。我想查看用户单击的区域,然后再次单击以缩小,仅此而已。我可以轻松完成后面的部分,但在缩放完美区域时遇到问题。我在 stackoverflow 上看到了类似的问题,但它们不符合我的要求。这是我的 html 和 css:

    <style>
    .container {
        height: 500px;
    }
    .container .image-container {
        height: 500px;
        width: 50%;
        overflow: auto;
        position: absolute;
        border: 1px solid;
    }

    img {
        display: none;
    }

    canvas {
        width: 100%;
    }
</style>
<body onload="draw()">
    <div class="container">
        <div class="image-container">
    <canvas
            id="canvas"
            onclick="zoom(event)"
    >
    </canvas>
   </div>
   </div>
</body>

PS:我不想平移。只需点击放大和缩小。你可以玩这个片段。

        function draw() {
            window.canvas = document.getElementById('canvas');
            window.ctx = canvas.getContext('2d');
            window.image = document.createElement("img");
            window.isZoom = false;
            image.onload = function() {
                canvas.width = image.width;
                canvas.height = image.height;
                ctx.clearRect(0,0,canvas.width,canvas.height);
                ctx.translate(image.width/2,image.height/2);
                ctx.drawImage(image,-image.width/2,-image.height/2);
            };
            image.src = 'https://d85ecz8votkqa.cloudfront.net/support/help_center/Print_Payment_Receipt.JPG';
        }

        function zoom(evt) {
            if(!isZoom) {
                var x = getMousePos(canvas, evt).x;
                var y = getMousePos(canvas, evt).y;
                canvas.width = image.width;
                canvas.height = image.height;
                ctx.clearRect(0,0,canvas.width,canvas.height);
                ctx.translate(x,y);
                ctx.scale(2, 2);
                ctx.drawImage(image,-x,-y);
                canvas.style.cursor = 'zoom-out';
                isZoom = true;
            } else {
                canvas.width = image.width;
                canvas.height = image.height;
                ctx.clearRect(0,0,canvas.width,canvas.height);
                ctx.translate(image.width/2,image.height/2);
                ctx.drawImage(image,-image.width/2,-image.height/2);
                isZoom=false;
                canvas.style.cursor = 'zoom-in';
            }
        }

        function getMousePos(canvas, evt) {
            var rect = canvas.getBoundingClientRect();
            return {
                x: evt.clientX - rect.left,
                y: evt.clientY - rect.top
            };
        }
    <style>
        .container {
            height: 500px;
        }
        .container .image-container {
            height: 500px;
            width: 50%;
            overflow: auto;
            position: absolute;
            border: 1px solid;
        }

        img {
            display: none;
        }

        canvas {
            width: 100%;
            cursor: zoom-in;
        }
    </style>
<body onload="draw()">
<div class="container">
    <div class="image-container">
        <canvas
                id="canvas"
                onclick="zoom(event)"
        >
        </canvas>
    </div>
</div>
</body>

标签: javascripthtmlcsscanvashtml5-canvas

解决方案


你真的很近,只需将比例混合到你的图像中

function draw() {
  window.canvas = document.getElementById('canvas');
  window.ctx = canvas.getContext('2d');
  window.image = document.createElement("img");
  window.isZoom = false;
  image.onload = function() {
    canvas.width = image.width;
    canvas.height = image.height;
    ctx.drawImage(image, 0,0);
  };
  image.src = 'https://d85ecz8votkqa.cloudfront.net/support/help_center/Print_Payment_Receipt.JPG';
}

function zoom(evt) {
  canvas.width = image.width;
  canvas.height = image.height;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  var scale = 2
  if (!isZoom) {
    var pos = getMousePos(canvas, evt);    
    ctx.scale(scale, scale);
    ctx.drawImage(image, -pos.x*scale*scale, -pos.y*scale*scale);
    canvas.style.cursor = 'zoom-out';
  } else {
    ctx.drawImage(image, 0, 0);
    canvas.style.cursor = 'zoom-in';
  }
  isZoom = !isZoom
}

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}
.container {
  height: 500px;
}

.container .image-container {
  height: 500px;
  width: 50%;
  overflow: auto;
  position: absolute;
  border: 1px solid;
}

img {
  display: none;
}

canvas {
  width: 100%;
  cursor: zoom-in;
}
<body onload="draw()">
  <div class="container">
    <div class="image-container">
      <canvas id="canvas" onclick="zoom(event)">
        </canvas>
    </div>
  </div>
</body>

除了添加var scale我对您的代码进行了一些清理之外:

var x = getMousePos(canvas, evt).x;
var y = getMousePos(canvas, evt).y;

对 getMousePos 的双重调用有点浪费


推荐阅读