gpt4 book ai didi

javascript/canvas, map 样式点缩放

转载 作者:行者123 更新时间:2023-11-30 15:07:29 25 4
gpt4 key购买 nike

我有一个带有一堆对象的 Canvas 。我有一个缩放函数,它增加了一个 zoom 变量,每个坐标都乘以该变量。

我希望能够指向坐标并朝该坐标缩放,类似于在线 map 的操作方式。

我已经设置了一个演示 here ,我的代码的当前状态。

最佳答案

坐标缩放

如果给定具有缩放内容的屏幕坐标,您需要以与缩放匹配的量将原点移向或远离该点。

如果放大,原点会移向鼠标的位置。并缩小。

所以用鼠标获取 x,y 位置并根据滚轮方向放大或缩小的量

// e is the mouse wheel event
const x = e.offsetX;
const y = e.offsetY;
const amount = e.wheelDelta > 0 ? 1.1 : 1 / 1.1;

然后将其应用于当前比例并移动原点以匹配

scale *= amount;  // the new scale
// move the origin
origin.x = x - (x - origin.x) * amount;
origin.y = y - (y - origin.y) * amount;

然后您可以设置 2D 位置和比例

ctx.setTransform(scale, 0, 0, scale, origin.x, origin.y);

例子

下面是一个简单的 View 示例,使用了您的 fiddle 中的一些代码。

对象 view 跟踪当前 View 并维护可应用于 Canvas 的矩阵。

const ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
const rand = (min, max = min + (min = 0)) => Math.random() * (max - min) + min;

const objects = [];
for (let i = 0; i < 100; i++) {
objects.push({
x: rand(canvas.width),
y: rand(canvas.height),
w: rand(40),
h: rand(40),
col: `rgb(${randI(255)},${randI(255)},${randI(255)})`,
});
}
canvas.addEventListener("mousewheel", onmousewheel, false);
canvas.addEventListener("DOMMouseScroll", onmousewheel, false);
requestAnimationFrame(drawCanvas); // this will call drawcanvas after all other code has run

const view = (() => {
const matrix = [1, 0, 0, 1, 0, 0]; // current view transform
var m = matrix; // alias for clear code
var scale = 1; // current scale
var ctx; // reference to the 2D context
const pos = { x: 0, y: 0 }; // current position of origin
var dirty = true;
const API = {
setContext(_ctx) { ctx = _ctx; dirty = true },
apply() {
if (dirty) { this.update() }
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5])
},
getScale() { return scale },
getPosition() { return pos },
isDirty() { return dirty },
update() {
dirty = false;
m[3] = m[0] = scale;
m[2] = m[1] = 0;
m[4] = pos.x;
m[5] = pos.y;
},
scaleAt(at, amount) { // at in screen coords
if (dirty) { this.update() }
scale *= amount;
pos.x = at.x - (at.x - pos.x) * amount;
pos.y = at.y - (at.y - pos.y) * amount;
dirty = true;
},
};
return API;
})();
view.setContext(ctx);

function drawCanvas() {
if (view.isDirty()) { // has the view changed, then draw all
ctx.setTransform(1, 0, 0, 1, 0, 0); // default transform for clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
view.apply(); // set the 2D context transform to the view
for (i = 0; i < objects.length; i++) {
var obj = objects[i];
ctx.fillStyle = obj.col;
ctx.fillRect(obj.x, obj.y, obj.h, obj.h);
}
}

requestAnimationFrame(drawCanvas);
}

function onmousewheel(event) {
var e = window.event || event;
var x = e.offsetX;
var y = e.offsetY;
const delta = e.type === "mousewheel" ? e.wheelDelta : -e.detail;
if (delta > 0) { view.scaleAt({x, y}, 1.1) }
else { view.scaleAt({x, y}, 1 / 1.1) }
e.preventDefault();
}
#canvas {
border: 2px solid;
}
<canvas id="canvas"></canvas>

关于javascript/canvas, map 样式点缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45528111/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com