#javascript #canvas #html5-canvas
#javascript #холст #html5-холст
Вопрос:
У меня возникли некоторые проблемы с реализацией пользовательского масштабирования.
У меня работает большая часть функций масштабирования, однако она масштабирует «вокруг» начала координат, в данном случае верхнего левого угла сетки. Вместо этого я хочу, чтобы он увеличивал масштаб вокруг курсора.
Холст такой же большой, как окно (я добавлю пользовательский интерфейс поверх холста, вроде как 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.translate
и ctx.scale
, но ни один из них, похоже, не делает то, что я хочу сделать (хотя я мог бы использовать их неправильно).
Вот JSFiddle с тем, что у меня есть на данный момент. Если бы кто-нибудь мог взглянуть, это было бы потрясающе.
Ответ №1:
Довольно классный код. Масштабирование в определенной точке может быть сложным и может быть выполнено несколькими способами. Основная проблема заключается в том, где именно вы хотите увеличить масштаб и в каком масштабе / как быстро при приближении к максимальному масштабированию.
Я бы предложил начать с определения смещения
...
// 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;
...
А затем вычислить смещение с использованием event.x
и event.y
MouseEvent
в zoom
обратном вызове, аналогично:
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
);
}
Увеличение точно в точке курсора возможно путем вычисления смещений относительно элемента холста, на котором выполняется масштабирование.
Комментарии:
1. Ваш пример действует довольно хаотично.
2. @RokoC. Buljan Это подразумевается как пример, а не как полное решение. Однако вы можете улучшить его, я с радостью приму улучшения