I'm trying to zoom at mouse position, like say on google maps. It kind of works but it shifts the point i want to zoom in on wherever it matches up with the original.Then when i zoom at that point it works fine. I think I need to translate the point back to the mouse, but I'm not sure how to do it exactly.
This is the code before i draw:
translate(zoomLocation.x, zoomLocation.y);
scale(zoom);
translate(-zoomLocation.x, -zoomLocation.y);
drawGrid();
And this is when I zoom:
event.preventDefault();
zoomLocation = {
x: zoomLocation.x + (mouseX - zoomLocation.x) / zoom,
y: zoomLocation.y + (mouseY - zoomLocation.y) / zoom
};
zoom -= zoomSensitivity * event.delta;
let colors = {
background: 0,
gridLines: "white"
};
let nVariables = 4;
let zoom = 1;
let zoomLocation = {
x: 0,
y: 0
};
let zoomSensitivity = 0.0002;
function draw() {
translate(zoomLocation.x, zoomLocation.y);
scale(zoom);
translate(-zoomLocation.x, -zoomLocation.y);
drawGrid();
stroke("blue");
ellipse(zoomLocation.x + (mouseX - zoomLocation.x) / zoom, zoomLocation.y + (mouseY - zoomLocation.y) / zoom, 10, 10);
stroke("red");
ellipse(zoomLocation.x, zoomLocation.y, 10, 10);
}
function setup() {
zoomLocation = {
x: 0,
y: windowHeight / 2
}
createCanvas(windowWidth, windowHeight);
}
function mouseWheel(event) {
event.preventDefault();
let oldZoom = zoom;
zoomLocation = {
x: zoomLocation.x + (mouseX - zoomLocation.x) / zoom,
y: zoomLocation.y + (mouseY - zoomLocation.y) / zoom
};
zoom -= zoomSensitivity * event.delta;
}
function drawGrid() {
let nCells = 2 ** nVariables;
if (nCells > 2048) {
if (!window.confirm(`You are about to create ${nCells} cells. This might lag your browser. Are you sure?`)) {
return;
}
}
background(colors.background);
let gridWidth = windowWidth - 2;
let gridHeight = min(gridWidth / nCells, windowHeight / 2 - 2);
let gridY = windowHeight / 2;
stroke(colors.gridLines);
line(0, gridY, gridWidth, gridY);
line(0, gridY + gridHeight, gridWidth, gridY + gridHeight);
for (let i = 0; i < nCells + 1; i++) {
line(i * (gridWidth / nCells), gridY, i * (gridWidth / nCells), gridY + gridHeight)
}
let curveHeight = 2;
let drawVariable = (n) => {
let p1 = {
x: 1 / (2 ** (n + 1)) * gridWidth,
y: gridY
};
let c1 = {
x: p1.x,
y: p1.y + gridWidth / (2 ** n) * curveHeight
};
let p2 = {
y: p1.y
};
let c2 = {
y: c1.y
};;
noFill();
stroke("red");
if (n == 0) {
p2.x = gridWidth;
c2.x = p2.x;
c1.y = c2.y = p1.y + gridWidth / 2 * curveHeight;
curve(c1.x, c1.y, p1.x, p1.y, p2.x, p2.y, c2.x, c2.y);
return;
}
for (let i = 3; i < 2 ** (n + 1); i += 2) {
p2.x = i / (2 ** (n + 1)) * gridWidth
c2.x = p2.x;
if ((i - 3) % 4 == 0) {
curve(c1.x, c1.y, p1.x, p1.y, p2.x, p2.y, c2.x, c2.y);
} else {
p1.x = p2.x;
c1.x = c2.x;
}
}
};
for (let i = 0; i < nVariables; i++) {
drawVariable(i);
}
}
body {
margin: 0
}
button {
outline: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/addons/p5.dom.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
What you're looking for is an application of Affine Transformation. Here's an example where I'm applying transformations incrementally to transform + scale at the mouse pointer location for a Google Maps type zoom effect: Zoom Effect in p5.js Web Editor.
This is a good medium article that explains why this works: Zooming at the Mouse Coordinates with Affine Transformations
This is another good article that has some mathematical explanations on how it achieves the effects: Affine Transformations — Pan, Zoom, Skew
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With