[英]JS Canvas Zoom in and Zoom out translate doesn't settle to center
我正在自己的畫布抽屜項目中工作,只是停留在縮放功能中。 在我的項目中,我要使用縮放和平移來進行縮放,因為我想將所有畫布及其元素保持在中心。 繪制了一點點(不是數學天才)后,我成功繪制了以下公式供翻譯過程中使用,因此,縮放后畫布將保留在其視口的中間:舊的寬度和高度/ 2-新的寬度和高度(舊的寬度和高度乘以比例尺,在我的情況下為1.1)/2。從邏輯上講,這應該使它起作用。 但是在嘗試了幾次放大和縮小之后,我可以清楚地看到畫布有一點偏移,並且沒有居中於視口的中間(所謂的視口,是指代表畫布的描邊正方形)。
我將代碼從項目中取出,放在小提琴中,就在這里:
https://jsfiddle.net/s82qambx/3/
的index.html
<div id="letse-canvas-container">
<canvas id="letse-canvas" width="300px" height="300px"></canvas>
<canvas id="letse-upper-canvas" width="300px" height="300px"></canvas>
</div>
<div id="buttons">
<button id="zoomin">
Zoom-in
</button>
<button id="zoomout">
Zoom-out
</button>
</div>
main.js
const canvas = {
canvas: document.getElementById('letse-canvas'),
upperCanvas: document.getElementById('letse-upper-canvas')
};
canvas.canvas.ctx = canvas.canvas.getContext('2d');
canvas.upperCanvas.ctx = canvas.upperCanvas.getContext('2d');
const CANVAS_STATE = {
canvas: {
zoom: 1,
width: 300,
height: 300
}
}
const Elements = [
{
x: 20,
y: 20,
width: 30,
height: 40
},
{
x:170,
y:30,
width: 100,
height: 100
}
];
const button = {
zoomin: document.getElementById('zoomin'),
zoomout: document.getElementById('zoomout')
}
button.zoomin.addEventListener('click', (e) => {
canvasZoomIn(e, canvas);
});
button.zoomout.addEventListener('click', (e) => {
canvasZoomOut(e, canvas);
});
function canvasZoomIn(e, canvas) {
const zoomData = getZoomData('in');
canvas.upperCanvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.upperCanvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.upperCanvas.ctx.clearRect(0, 0, 300, 300);
canvas.canvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.canvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.canvas.ctx.clearRect(0, 0, 300, 300);
Elements.forEach((element) => {
canvas.canvas.ctx.strokeRect(element.x, element.y, element.width, element.height);
});
CANVAS_STATE.canvas.zoom = zoomData.scale;
CANVAS_STATE.canvas.width = zoomData.docWidth;
CANVAS_STATE.canvas.height = zoomData.docHeight;
console.log(CANVAS_STATE.canvas.zoom, 'zoom');
console.log(CANVAS_STATE.canvas.width, 'width');
console.log(CANVAS_STATE.canvas.height, 'height');
canvas.canvas.ctx.strokeRect(0, 0, 300, 300);
canvas.canvas.ctx.beginPath();
canvas.canvas.ctx.moveTo(0, 150);
canvas.canvas.ctx.lineTo(300, 150);
canvas.canvas.ctx.stroke();
CANVAS_STATE.canvas.draggable = canvas.canvas.width < CANVAS_STATE.canvas.width || canvas.canvas.height < CANVAS_STATE.canvas.height;
}
function canvasZoomOut(e, canvas) {
const zoomData = getZoomData('out');
canvas.upperCanvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.upperCanvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.upperCanvas.ctx.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
canvas.canvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.canvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.canvas.ctx.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
Elements.forEach((element) => {
canvas.canvas.ctx.strokeRect(element.x, element.y, element.width, element.height);
});
CANVAS_STATE.canvas.zoom = zoomData.scale;
CANVAS_STATE.canvas.width = zoomData.docWidth;
CANVAS_STATE.canvas.height = zoomData.docHeight;
console.log(CANVAS_STATE.canvas.zoom, 'zoom');
console.log(CANVAS_STATE.canvas.width, 'width');
console.log(CANVAS_STATE.canvas.height, 'height');
canvas.canvas.ctx.strokeRect(0, 0, 300, 300);
canvas.canvas.ctx.beginPath();
canvas.canvas.ctx.moveTo(0, 150);
canvas.canvas.ctx.lineTo(300, 150);
canvas.canvas.ctx.stroke();
CANVAS_STATE.canvas.draggable = canvas.canvas.width < CANVAS_STATE.canvas.width || canvas.canvas.height < CANVAS_STATE.canvas.height;
}
function getZoomData(zoom) {
const zoomStep = zoom === 'in' ? 1.1 : 1 / 1.1;
const scale = CANVAS_STATE.canvas.zoom * zoomStep;
const docWidth = CANVAS_STATE.canvas.width * zoomStep;
const docHeight = CANVAS_STATE.canvas.height * zoomStep;
const translateX = CANVAS_STATE.canvas.width / 2 - docWidth / 2;
const translateY = CANVAS_STATE.canvas.height / 2 - docHeight / 2;
console.log(zoomStep);
console.log(scale, 'check');
console.log(docWidth);
console.log(docHeight);
console.log(translateX, 'check');
console.log(translateY, 'check');
return {
zoomStep,
scale,
docWidth,
docHeight,
translateX,
translateY
};
}
的main.css
#letse-canvas-container {
position: relative;
float: left;
}
#letse-canvas {
border: 1px solid rgb(0, 0, 0);
/* visibility: hidden; */
}
#letse-upper-canvas {
/* position: absolute; */
/* top: 0px; */
left: 0px;
border: 1px solid;
/* visibility: hidden; */
}
有人可以提出原因嗎? 我在這里想念什么?
好! 因此,在網上搜索並測試了很少的選擇之后,我設法得出了正確的公式。 我用了:
function getZoomData(zoom) {
const zoomStep = zoom === 'in' ? 1.1 : 1 / 1.1;
const oldZoom = CANVAS_STATE.canvas.zoom;
const newZoom = oldZoom * zoomStep;
const zoomDifference = newZoom - oldZoom;
const docWidth = CANVAS_STATE.canvas.width * newZoom;
const docHeight = CANVAS_STATE.canvas.height * newZoom;
const translateX = (-(canvas.canvas.width / 2 * zoomDifference / newZoom));
const translateY = (-(canvas.canvas.height / 2 * zoomDifference / newZoom));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.