javascript /画布,地图样式点缩放 [英] javascript/canvas, map style point zooming
问题描述
我有一个带有一堆物体的画布。我有一个缩放功能,可以使 zoom
变量变大,每个坐标乘以该变量。
I have a canvas with a bunch of objects. I have a zoom function that bumps up a zoom
variable by which every coordinate is multiplied.
我想成为能够指向坐标并放大该坐标,类似于在线地图。
I want to be able to point at a coordinate and zoom towards that, similar to how online maps do it.
我已经设置了一个演示此处,为我的代码的当前状态。
I have setup a demo here, of the current state of my code.
推荐答案
在坐标上缩放
如果给定屏幕坐标已缩放内容,则需要以与缩放相匹配的量将原点移向或移离该点。
Scale at coordinate
If given a screen coordinate that has scaled content you need to move the origin towards or away from that point at an amount that matches the zoom.
如果放大,则原点将移向鼠标的位置。
If you zoom in the origin moves towards the position of the mouse. and zoom out away.
因此,用鼠标获得x,y位置,并根据方向盘放大或缩小量。
So with the mouse get the x,y position and depending on the wheel direction the amount to zoom in or out
// e is the mouse wheel event
const x = e.offsetX;
const y = e.offsetY;
const amount = e.wheelDelta > 0 ? 1.1 : 1 / 1.1;
然后将其应用到当前比例并将原点移动以匹配
Then you apply that to the current scale and move the origin to match
scale *= amount; // the new scale
// move the origin
origin.x = x - (x - origin.x) * amount;
origin.y = y - (y - origin.y) * amount;
然后您可以设置二维位置和缩放比例,
You can then set the 2D position and scale with
ctx.setTransform(scale, 0, 0, scale, origin.x, origin.y);
示例
下面是一个简单的视图
Example
Below is a simple view example using bits of the code from your fiddle.
对象 view
会跟踪当前视图并维护一个
The object view
keeps track of the current view and maintains a matrix that can be applied to the 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 /画布,地图样式点缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!