如何缩放到画布中心,而不是上下文中心

问题描述 投票:0回答:2

我有一个画布,尺寸为 400 x 400。在上面,我绘制了一个地图区域,200 x 200。 我已将其翻译到画布的中心。我可以放大和缩小,一切都很好。但是,当我平移时,它会从地图区域的中心缩放。我希望它始终从画布中心缩放,无论地图区域在哪里。我想我需要以某种方式否定平移坐标,但我无法弄清楚。 这是我的代码:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var canvas1 = document.getElementById("canvasX");
var ctxX = canvas1.getContext("2d");

var cw = canvas.width;
var ch = canvas.height;
var mapW = 200;
var mapH = 200;
var panX=0;
var panY=0;
var scaleFactor=1.00;

drawTranslated();

function zoomIn(){
    scaleFactor*=1.1; 
    drawTranslated(); 
}

function zoomOut(){
    scaleFactor/=1.1; 
    drawTranslated(); 
}

function panUp(){
    panY-=25; 
    drawTranslated(); 
}

function panDown(){
    panY+=25; 
    drawTranslated();
}

function panLeft(){
    panX-=25; 
    drawTranslated(); 
}

function panRight(){
    panX+=25; 
    drawTranslated(); 
}

function drawTranslated(){
    // canvas
    ctx.clearRect(0,0,cw,ch);
    ctx.save();
    ctx.translate(cw/2, ch/2);
    ctx.translate(panX,panY);
    ctx.scale(scaleFactor, scaleFactor);
    ctx.fillStyle = "Green";
    ctx.fillRect(mapW/-2, mapH/-2, mapW, mapH);
    ctx.restore();

    // canvasX
    ctxX.clearRect(0,0,cw,ch);
    ctxX.save();
    ctxX.translate(cw/2, ch/2);             
    ctxX.beginPath();
        
    ctxX.moveTo(0, 25);
    ctxX.lineTo(0, -25);
    ctxX.moveTo(-25, 0);
    ctxX.lineTo(25, 0);
        
    ctxX.closePath();
    ctxX.lineWidth = 1;
    ctxX.strokeStyle = 'Black';
    ctxX.stroke();
    ctxX.restore();
}
#wrapper {position: relative;}
canvas {position: absolute; border: 1px solid Black;}
<!DOCTYPE html>
<html>
<body>
    <div id="wrapper">
    <button id="zoomin" class="nav" title="Zoom In" onclick="zoomIn()">&#43;</button>
    <button id="zoomout" class="nav" title="Zoom Out" onclick="zoomOut()">&#8722;</button>
    <button id="panup" class="nav" title="Up" onclick="panUp()">&#8679;</button>
    <button id="pandown" class="nav" title="Down" onclick="panDown()">&#8681;</button>
    <button id="panleft" class="nav" title="Left" onclick="panLeft()">&#8678;</button>
    <button id="panright" class="nav" title="Right" onclick="panRight()">&#8680;</button>
    </div>
    <div id="wrapper">
    <canvas id="myCanvas" width="400" height="400"></canvas>
    <canvas id="canvasX" width="400" height="400"></canvas>
    </div>
</body>
</html>

javascript canvas zooming centering pan
2个回答
4
投票

经过一段时间尝试找到一些方程来解决这个问题,我想我已经找到了解决方案。

ctx.translate(panX,panY);
ctx.scale(scaleFactor, scaleFactor);

通过先平移,然后缩放,它将从上下文的中心(在本例中为绿色方块)进行缩放。但是,只需将其更改为:

ctx.scale(scaleFactor, scaleFactor);
ctx.translate(panX,panY);

它将从画布中心缩放。 它似乎做了我想做的事,所以除非我弄错了,否则我相信这就是答案。

我添加了另一个片段。唯一的变化是这两行,但我认为这对人们能够看到它所产生的差异会有帮助。

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas1 = document.getElementById("canvasX");
var ctxX = canvas1.getContext("2d");

var cw = canvas.width;
var ch = canvas.height;
var mapW = 200;
var mapH = 200;
var panX = 0;
var panY = 0;
var scaleFactor = 1.00;

    drawTranslated();

    function zoomIn() {
        document.getElementById("zoomin").click(); {
	        scaleFactor *= 1.1;
	        drawTranslated();
        };
    };

	function zoomOut() {
	  document.getElementById("zoomout").click(); {
	    scaleFactor /= 1.1;
	    drawTranslated();
	  };
	};

	function panUp() {
	  document.getElementById("panup").click(); {
	    panY -= 25;
	    drawTranslated();
	  };
	};

	function panDown() {
	  document.getElementById("pandown").click(); {
	    panY += 25;
	    drawTranslated();
	  };
	};

	function panLeft() {
	  document.getElementById("panleft").click(); {
	    panX -= 25;
	    drawTranslated();
	  };
	};

	function panRight() {
	  document.getElementById("panright").click(); {
	    panX += 25;
	    drawTranslated();
	  };
	};

	function drawTranslated() {

	  // canvas
	  ctx.clearRect(0, 0, cw, ch);
	  ctx.save();
	  ctx.translate(cw / 2, ch / 2);
	  ctx.scale(scaleFactor, scaleFactor);
	  ctx.translate(panX, panY);
	  ctx.fillStyle = "Green";
	  ctx.fillRect(mapW / -2, mapH / -2, mapW, mapH);
	  ctx.restore();

	  // canvasX
	  ctxX.clearRect(0, 0, cw, ch);
	  ctxX.save();
	  ctxX.translate(cw / 2, ch / 2);
	  ctxX.beginPath();

	  ctxX.moveTo(0, 25);
	  ctxX.lineTo(0, -25);
	  ctxX.moveTo(-25, 0);
	  ctxX.lineTo(25, 0);

	  ctxX.closePath();
	  ctxX.lineWidth = 1;
	  ctxX.strokeStyle = 'Black';
	  ctxX.stroke();
	  ctxX.restore();
	};
#wrapper {
  position: relative;
}
canvas {
  position: absolute;
  border: 1px solid Black;
}
<div id="wrapper">
  <button id="zoomin" class="nav" title="Zoom In" onclick="zoomIn()">&#43;</button>
  <button id="zoomout" class="nav" title="Zoom Out" onclick="zoomOut()">&#8722;</button>
  <button id="panup" class="nav" title="Up" onclick="panUp()">&#8679;</button>
  <button id="pandown" class="nav" title="Down" onclick="panDown()">&#8681;</button>
  <button id="panleft" class="nav" title="Left" onclick="panLeft()">&#8678;</button>
  <button id="panright" class="nav" title="Right" onclick="panRight()">&#8680;</button>
</div>
<div id="wrapper">
  <canvas id="canvas" width="400" height="400"></canvas>
  <canvas id="canvasX" width="400" height="400"></canvas>
</div>


1
投票

肯定有更好的方法,但在 Fabric.js 中你可以做到

canvas.zoomToPoint(new fabric.Point(canvas.width / 2, canvas.height / 2), canvas.getZoom() / ZOOM_PERCENT);

在此处查看更多画布

为了更纯粹的解决方案,您还可以尝试使用

将上下文平移画布大小的一半
ctx.translate()

一个可能有帮助的小提琴

http://jsfiddle.net/m1erickson/QEuw4/

© www.soinside.com 2019 - 2024. All rights reserved.