My dear friend John, a.k.a introscopia has this amazing smooth zoom and pan code I really like, but he uses mostly SDL nowadays, so I asked him for help and made these two examples. One in Processing Java and the other for Python + py5. I hope you enjoy it as much as I did (I have many sketches that would benefit from this).
// A zoom strategy from John @introscopia https://introscopia.itch.io/
int zptX = 0;
int zptY = 0;
float zptScale = 1;
float zptAmount = 0;
int seed = 1;
void setup() {
size(500, 500);
noStroke();
}
void draw() {
pushMatrix();
translate(zptX, zptY);
scale(zptScale);
// Your drawing goes here
background(0);
randomSeed(seed);
int w = 500;
for (int i=0; i<10; i++) {
float x= random(-w/2, w + w/2);
float y = random(-w/2, w + w/2);
for (int d=w*2; d>0; d=d-10) {
fill(random(255), random(255), random(255), 50);
circle(x, y, d);
}
}
// end of the main drawing part
popMatrix();
// HUD (Head-Up Display, like if projected on the windscreen, unaffected by zoom & pan)
pushStyle();
int margin = 40;
noFill();
stroke(255);
rect(margin, margin, width - margin * 2, height - margin * 2);
fill(255);
textSize(margin / 3);
textAlign(LEFT, TOP);
text(String.format("{'x': %s, 'y': %s , 'scale': %s, 'amount': %s}", zptX, zptY, zptScale, zptAmount),
margin, height - margin / 2);
popStyle();
}
void mouseWheel(MouseEvent e) {
float xrd = (mouseX - zptX) / zptScale;
float yrd = (mouseY - zptY) / zptScale;
zptAmount -= e.getCount();
zptScale = pow(1.1, zptAmount);
zptX = int(mouseX - xrd * zptScale);
zptY = int(mouseY - yrd * zptScale);
}
void mouseDragged() {
zptX += mouseX - pmouseX;
zptY += mouseY - pmouseY;
}
void keyPressed() {
seed += 1;
}
And with py5:
# A zoom strategy from John @introscopia https://introscopia.itch.io/
import py5
zpt = {'x': 0, 'y': 0, 'scale': 1, 'amount': 0} # zoom & pan transformation values
seed = 1
def setup():
py5.size(500, 500)
py5.no_stroke()
def draw():
with py5.push_matrix():
py5.translate(zpt['x'], zpt['y'])
py5.scale(zpt['scale'])
# Your drawing goes here
py5.background(0)
py5.random_seed(seed)
w = 500
for _ in range(10):
x, y = py5.random(-w/2, w + w/2), py5.random(-w/2, w + w/2)
for d in range(w * 2, 0, -10):
py5.fill(py5.random(255),py5.random(255),py5.random(255), 50)
py5.circle(x, y, d)
# HUD (Head-Up Display, like if projected on the windscreen, unaffected by zoom & pan)
with py5.push_style():
margin = 40
py5.no_fill()
py5.stroke(255)
py5.rect(margin, margin, py5.width - margin * 2, py5.height - margin * 2)
py5.fill(255)
py5.text_size(margin / 3)
py5.text_align(py5.LEFT, py5.TOP)
py5.text(str(zpt), margin, py5.height - margin / 2)
def mouse_wheel(e):
xrd = (py5.mouse_x - zpt['x']) / zpt['scale']
yrd = (py5.mouse_y - zpt['y']) / zpt['scale']
zpt['amount'] -= e.get_count()
zpt['scale'] = 1.1 ** zpt['amount']
zpt['x'] = int(py5.mouse_x - xrd * zpt['scale'])
zpt['y'] = int(py5.mouse_y - yrd * zpt['scale'])
def mouse_dragged():
zpt['x'] += py5.mouse_x - py5.pmouse_x
zpt['y'] += py5.mouse_y - py5.pmouse_y
def key_pressed():
global seed
seed += 1
py5.run_sketch()