Как сделать так, чтобы scale приближал картинку к курсору в канвасе JS?
const image = {
object: new Image(),
x: 0,
y: 0,
scale: 1,
scaleMultiplier: 0.9
}
function draw() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.save();
ctx.translate(image.x, image.y);
ctx.scale(image.scale, image.scale);
const imageWidth = image.object.width;
const imageHeight = image.object.height;
const centerCoordsX = (canvasWidth - imageWidth) / 2;
const centerCoordsY = (canvasHeight - imageHeight) / 2;
const t1 = (centerCoordsX + image.x) / (image.scale * 2);
const t2 = (centerCoordsY + image.y) / (image.scale * 2);
ctx.drawImage(image.object, t1, t2, imageWidth, imageHeight);
ctx.fill();
ctx.restore();
}
canvas.onwheel = function(e) {
if (e.deltaY < 0)
image.scale /= image.scaleMultiplier;
else
image.scale *= image.scaleMultiplier;
draw();
};
При прокрутке колеса мыши сейчас картинка скейлится к верхнему левому углу, а как сделать так, чтобы она скейлилась к координатам курсора?
Ответы (1 шт):
Автор решения: dotagenius
→ Ссылка
Вот тут ответили на мой вопрос. Мне нужно было то же самое, но только с картинкой. Еще немного упростил код.
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext("2d");
const image = new Image();
image.src = 'https://picsum.photos/400';
requestAnimationFrame(drawCanvas);
let matrix = [1, 0, 0, 1, 0, 0];
let scale = 1;
const pos = { x: 0, y: 0 };
let dirty = true;
const mouse = {x: 0, y: 0, oldX: 0, oldY: 0, dragging: false};
canvas.addEventListener("mousemove", mouseEvent, {passive: true});
canvas.addEventListener("mousedown", mouseEvent, {passive: true});
canvas.addEventListener("mouseup", mouseEvent, {passive: true});
canvas.addEventListener("mouseout", mouseEvent, {passive: true});
canvas.addEventListener("wheel", mouseWheelEvent, {passive: false});
function apply() {
if (dirty)
update();
ctx.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
}
function update() {
dirty = false;
matrix[3] = matrix[0] = scale;
matrix[2] = matrix[1] = 0;
matrix[4] = pos.x;
matrix[5] = pos.y;
}
function pan(amount) {
if (dirty)
update();
pos.x += amount.x;
pos.y += amount.y;
dirty = true;
}
function scaleAt(at, amount) {
if (dirty)
update();
scale *= amount;
pos.x = at.x - (at.x - pos.x) * amount;
pos.y = at.y - (at.y - pos.y) * amount;
dirty = true;
}
function drawCanvas() {
if (dirty) {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
apply();
ctx.drawImage(image, 0, 0);
}
requestAnimationFrame(drawCanvas);
}
function mouseEvent(e) {
if (e.type === "mousedown")
mouse.dragging = true;
if (e.type === "mouseup" || e.type === "mouseout")
mouse.dragging = false;
mouse.oldX = mouse.x;
mouse.oldY = mouse.y;
mouse.x = e.offsetX;
mouse.y = e.offsetY
if (mouse.dragging)
pan({x: mouse.x - mouse.oldX, y: mouse.y - mouse.oldY});
}
function mouseWheelEvent(e) {
let x = e.offsetX;
let y = e.offsetY;
if (e.deltaY < 0)
scaleAt({x, y}, 1.1);
else
scaleAt({x, y}, 1 / 1.1);
e.preventDefault();
}
canvas {
width: 300px;
height: 300px;
}
<canvas id="canvas" width="300px" height="300px"></canvas>