使用 p5.js 创建缩放效果
Create Zoom effect with p5.js
我知道这个问题已经被问过好几次了,但是 none 我找到的答案对我有用。我需要允许用户缩放目前有效的图像,这只是一个 scale(factor)
调用,但现在我想通过鼠标指针进行缩放。这证明更加困难,因为我可以创建放大指针效果,但是当鼠标移动时,图像也会移动。如本演示所示:
https://editor.p5js.org/J-Cake/sketches/1r1wmWO60
我想我会将第二个翻译的坐标乘以比例因子,但这似乎也没有做任何事情。我错过了什么?
let sf = 1; // scaleFactor
let x = 0; // pan X
let y = 0; // pan Y
let mx, my; // mouse coords;
function setup() {
createCanvas(400, 400);
}
function draw() {
mx = mouseX;
my = mouseY;
background(255);
translate(mx, my);
scale(sf);
translate(-mx, -my);
translate();
rect(100, 100, 100, 100);
if (mouseIsPressed) {
x -= pmouseX - mouseX;
y -= pmouseY - mouseY;
}
}
window.addEventListener("wheel", function(e) {
if (e.deltaY > 0)
sf *= 1.05;
else
sf *= 0.95;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
问题是您必须逐步应用缩放。
从中心点(x1
、y1
)开始的单个比例尺(s1
)可以通过以下方式计算:
model = translate(x1, y1) * scale(s1) * translate(-x1, -y1)
但是如果你想在中心(x2
、y2
)周围应用一个新的比例尺(s2
),那么这是:
model = translate(x2, y2) * scale(s2) * translate(-x2, -y2) * currentMode;
其中 currentMode
是之前的(缩放)变换。
这 与 不同:
model = translate(x1+x2, y1+y2) * scale(s1*s2) * translate(-(x1+x2), -(y1+y2))
距离中心(mx
、my
)的单个刻度(sf
)可以通过以下方式计算:
let tx = mx - sf * mx;
let ty = my - sf * my;
translate(tx, ty);
scale(sf);
要连续执行更多此类操作,我建议实施 3x3 Matrix multiplication:
function matMult3x3(A, B) {
C = [0, 0, 0, 0, 0, 0];
for (let k = 0; k < 3; ++ k) {
for (let j = 0; j < 3; ++ j) {
C[k*3+j] = A[0*3+j] * B[k*3+0] + A[1*3+j] * B[k*3+1] + A[2*3+j] * B[k*3+2];
}
}
return C;
}
距离中心的比例可以用下面的 3x3 矩阵表示:
m = [ sf, 0, 0,
0, sf, 0,
tx, ty, 1];
这会导致以下鼠标滚轮事件:
window.addEventListener("wheel", function(e) {
let mx = mouseX;
let my = mouseY;
let s = e.deltaY > 0 ? 1.05 : 0.95;
let x = mx - s * mx;
let y = my - s * my;
m = matMult3x3([s,0,0, 0,s,0, x,y,1], [sf,0,0, 0,sf,0, tx,ty,1]);
sf = m[0];
tx = m[6];
ty = m[7];
} );
在这种情况下,这可以简化:
window.addEventListener("wheel", function(e) {
let mx = mouseX;
let my = mouseY;
let s = e.deltaY > 0 ? 1.05 : 0.95;
sf = sf * s;
tx = mx - s * mx + s * tx;
ty = my - s * my + s * ty;
} );
参见示例。可以通过鼠标滚轮或 +/- 键从鼠标光标位置缩放矩形:
let sf = 1, tx = 0, ty = 0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(127);
translate(tx, ty);
scale(sf);
rect(100, 100, 100, 100);
}
function applyScale(s) {
sf = sf * s;
tx = mouseX * (1-s) + tx * s;
ty = mouseY * (1-s) + ty * s;
}
window.addEventListener("wheel", function(e) {
applyScale(e.deltaY > 0 ? 1.05 : 0.95);
} );
function keyPressed() {
if (key == '-') {
applyScale(0.95);
} else if (key == '+') {
applyScale(1.05);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
我知道这个问题已经被问过好几次了,但是 none 我找到的答案对我有用。我需要允许用户缩放目前有效的图像,这只是一个 scale(factor)
调用,但现在我想通过鼠标指针进行缩放。这证明更加困难,因为我可以创建放大指针效果,但是当鼠标移动时,图像也会移动。如本演示所示:
https://editor.p5js.org/J-Cake/sketches/1r1wmWO60
我想我会将第二个翻译的坐标乘以比例因子,但这似乎也没有做任何事情。我错过了什么?
let sf = 1; // scaleFactor
let x = 0; // pan X
let y = 0; // pan Y
let mx, my; // mouse coords;
function setup() {
createCanvas(400, 400);
}
function draw() {
mx = mouseX;
my = mouseY;
background(255);
translate(mx, my);
scale(sf);
translate(-mx, -my);
translate();
rect(100, 100, 100, 100);
if (mouseIsPressed) {
x -= pmouseX - mouseX;
y -= pmouseY - mouseY;
}
}
window.addEventListener("wheel", function(e) {
if (e.deltaY > 0)
sf *= 1.05;
else
sf *= 0.95;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
问题是您必须逐步应用缩放。
从中心点(x1
、y1
)开始的单个比例尺(s1
)可以通过以下方式计算:
model = translate(x1, y1) * scale(s1) * translate(-x1, -y1)
但是如果你想在中心(x2
、y2
)周围应用一个新的比例尺(s2
),那么这是:
model = translate(x2, y2) * scale(s2) * translate(-x2, -y2) * currentMode;
其中 currentMode
是之前的(缩放)变换。
这 与 不同:
model = translate(x1+x2, y1+y2) * scale(s1*s2) * translate(-(x1+x2), -(y1+y2))
距离中心(mx
、my
)的单个刻度(sf
)可以通过以下方式计算:
let tx = mx - sf * mx;
let ty = my - sf * my;
translate(tx, ty);
scale(sf);
要连续执行更多此类操作,我建议实施 3x3 Matrix multiplication:
function matMult3x3(A, B) {
C = [0, 0, 0, 0, 0, 0];
for (let k = 0; k < 3; ++ k) {
for (let j = 0; j < 3; ++ j) {
C[k*3+j] = A[0*3+j] * B[k*3+0] + A[1*3+j] * B[k*3+1] + A[2*3+j] * B[k*3+2];
}
}
return C;
}
距离中心的比例可以用下面的 3x3 矩阵表示:
m = [ sf, 0, 0,
0, sf, 0,
tx, ty, 1];
这会导致以下鼠标滚轮事件:
window.addEventListener("wheel", function(e) {
let mx = mouseX;
let my = mouseY;
let s = e.deltaY > 0 ? 1.05 : 0.95;
let x = mx - s * mx;
let y = my - s * my;
m = matMult3x3([s,0,0, 0,s,0, x,y,1], [sf,0,0, 0,sf,0, tx,ty,1]);
sf = m[0];
tx = m[6];
ty = m[7];
} );
在这种情况下,这可以简化:
window.addEventListener("wheel", function(e) {
let mx = mouseX;
let my = mouseY;
let s = e.deltaY > 0 ? 1.05 : 0.95;
sf = sf * s;
tx = mx - s * mx + s * tx;
ty = my - s * my + s * ty;
} );
参见示例。可以通过鼠标滚轮或 +/- 键从鼠标光标位置缩放矩形:
let sf = 1, tx = 0, ty = 0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(127);
translate(tx, ty);
scale(sf);
rect(100, 100, 100, 100);
}
function applyScale(s) {
sf = sf * s;
tx = mouseX * (1-s) + tx * s;
ty = mouseY * (1-s) + ty * s;
}
window.addEventListener("wheel", function(e) {
applyScale(e.deltaY > 0 ? 1.05 : 0.95);
} );
function keyPressed() {
if (key == '-') {
applyScale(0.95);
} else if (key == '+') {
applyScale(1.05);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>