HTML Canvas - 使用鼠标滚轮精确放大和缩小鼠标指针 - 检查codepen示例
HTML Canvas - Zooming in and out in exactly on the mouse pointer using the mouse wheel - Check codepen example
我只想能够使用鼠标滚轮精确地放大和缩小鼠标光标。它应该像在 google 地图中实现的那样工作!
我在codepen上做了一个例子来突出我的问题。请测试它以查看问题。 只需将鼠标指针指向图像中的左眼即可。缩小很多,然后将鼠标指针移到右眼并再次放大。您会看到它没有精确缩放鼠标位置。
有问题的动画:
问题是我正在使用 ctx.scale 缩放图像,并使用 ctx.translate 使 canvas 恢复到原始状态。这是一个非常快速的解决方案,但它并没有那么精确地工作。有人可以帮我解决这个问题吗?
目标:
能够在图像的不同点缩小和放大,就像使用鼠标滚轮在 google 地图上所做的一样。
下面是我的代码示例的link,以帮助突出问题。任何解决方案将不胜感激!
[https://codepen.io/MKTechStation/pen/abEyBJm?editors=1111][2]
非常感谢您!
好的,我可以找到解决方案。
它基本上包括跟踪所有转换并将其保存为倒置矩阵。
所以,现在鼠标真正正确的位置是根据变换计算出来的。
请在此处查看解决方案。
window.onload = function () {
const img = document.querySelector("img");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
trackTransforms(ctx);
let zoom = 1;
let mousePos = {
x: 0,
y: 0
};
draw();
document.body.addEventListener("mousemove", (e) => {
const canvas = document.querySelector("canvas");
const rect = canvas.getBoundingClientRect();
mousePos.x = e.clientX - rect.left;
mousePos.y = e.clientY - rect.top;
});
document.getElementById("canvas").addEventListener("wheel", (e) => {
e.preventDefault();
zoom = e.deltaY < 0 ? 1.1 : 0.9;
scaleDraw();
draw();
});
function draw() {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
function scaleDraw() {
const pt = ctx.transformedPoint(mousePos.x, mousePos.y);
console.log("PT: " + `${pt.x}, ${pt.y}`);
console.log("MOUSEPOINTER: " + `${mousePos.x}, ${mousePos.y}`);
ctx.translate(pt.x, pt.y);
ctx.scale(zoom, zoom);
ctx.translate(-pt.x, -pt.y);
}
};
function trackTransforms(ctx) {
debugger;
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
let xform = svg.createSVGMatrix();
const savedTransforms = [];
let save = ctx.save;
ctx.save = () => {
savedTransforms.push(xform.translate(0, 0));
return save.call(ctx);
};
let restore = ctx.restore;
ctx.restore = () => {
xform = savedTransforms.pop();
return restore.call(ctx);
};
let scale = ctx.scale;
ctx.scale = (sx, sy) => {
xform = xform.scaleNonUniform(sx, sy);
return scale.call(ctx, sx, sy);
};
let translate = ctx.translate;
ctx.translate = function (dx, dy) {
xform = xform.translate(dx, dy);
return translate.call(ctx, dx, dy);
};
let pt = svg.createSVGPoint();
ctx.transformedPoint = (x, y) => {
pt.x = x;
pt.y = y;
return pt.matrixTransform(xform.inverse());
};
}
https://codepen.io/MKTechStation/pen/pobbKOj
希望对大家有所帮助。我仍然愿意接受任何其他更好的解决方案!!
我只想能够使用鼠标滚轮精确地放大和缩小鼠标光标。它应该像在 google 地图中实现的那样工作!
我在codepen上做了一个例子来突出我的问题。请测试它以查看问题。 只需将鼠标指针指向图像中的左眼即可。缩小很多,然后将鼠标指针移到右眼并再次放大。您会看到它没有精确缩放鼠标位置。
有问题的动画:
问题是我正在使用 ctx.scale 缩放图像,并使用 ctx.translate 使 canvas 恢复到原始状态。这是一个非常快速的解决方案,但它并没有那么精确地工作。有人可以帮我解决这个问题吗?
目标: 能够在图像的不同点缩小和放大,就像使用鼠标滚轮在 google 地图上所做的一样。
下面是我的代码示例的link,以帮助突出问题。任何解决方案将不胜感激!
[https://codepen.io/MKTechStation/pen/abEyBJm?editors=1111][2]
非常感谢您!
好的,我可以找到解决方案。 它基本上包括跟踪所有转换并将其保存为倒置矩阵。 所以,现在鼠标真正正确的位置是根据变换计算出来的。 请在此处查看解决方案。
window.onload = function () {
const img = document.querySelector("img");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
trackTransforms(ctx);
let zoom = 1;
let mousePos = {
x: 0,
y: 0
};
draw();
document.body.addEventListener("mousemove", (e) => {
const canvas = document.querySelector("canvas");
const rect = canvas.getBoundingClientRect();
mousePos.x = e.clientX - rect.left;
mousePos.y = e.clientY - rect.top;
});
document.getElementById("canvas").addEventListener("wheel", (e) => {
e.preventDefault();
zoom = e.deltaY < 0 ? 1.1 : 0.9;
scaleDraw();
draw();
});
function draw() {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
function scaleDraw() {
const pt = ctx.transformedPoint(mousePos.x, mousePos.y);
console.log("PT: " + `${pt.x}, ${pt.y}`);
console.log("MOUSEPOINTER: " + `${mousePos.x}, ${mousePos.y}`);
ctx.translate(pt.x, pt.y);
ctx.scale(zoom, zoom);
ctx.translate(-pt.x, -pt.y);
}
};
function trackTransforms(ctx) {
debugger;
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
let xform = svg.createSVGMatrix();
const savedTransforms = [];
let save = ctx.save;
ctx.save = () => {
savedTransforms.push(xform.translate(0, 0));
return save.call(ctx);
};
let restore = ctx.restore;
ctx.restore = () => {
xform = savedTransforms.pop();
return restore.call(ctx);
};
let scale = ctx.scale;
ctx.scale = (sx, sy) => {
xform = xform.scaleNonUniform(sx, sy);
return scale.call(ctx, sx, sy);
};
let translate = ctx.translate;
ctx.translate = function (dx, dy) {
xform = xform.translate(dx, dy);
return translate.call(ctx, dx, dy);
};
let pt = svg.createSVGPoint();
ctx.transformedPoint = (x, y) => {
pt.x = x;
pt.y = y;
return pt.matrixTransform(xform.inverse());
};
}
https://codepen.io/MKTechStation/pen/pobbKOj
希望对大家有所帮助。我仍然愿意接受任何其他更好的解决方案!!