JS Canvas Увеличение и уменьшение масштаба не переводят в центр - PullRequest
0 голосов
/ 27 января 2019

Я работаю над своим собственным проектом выдвижного ящика и просто застрял в функции увеличения / уменьшения.В моем проекте я использую масштабирование и перевод для увеличения, так как я хочу, чтобы все полотно и его элементы были в центре.После небольшого наброска (не математического гения) мне удалось нарисовать следующую формулу для использования в процессе перевода, так что холст будет оставаться в середине порта просмотра после масштабирования: Старая ширина и высота / 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; */
}

Может кто-нибудь подсказать причину?Что мне здесь не хватает?

1 Ответ

0 голосов
/ 29 января 2019

OK!Так что мне удалось вывести правильную формулу после поиска в сети и тестирования нескольких вариантов.Я использовал:

 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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...