最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create Zoom effect with p5.js - Stack Overflow

programmeradmin8浏览0评论

I know this question has been asked several times, but none of the answers I found worked for me. I need to allow the user to scale the image which works so far, it's simply a scale(factor) call but now I want to scale by the mouse pointer. This proves more difficult as I can create the zoom in on the pointer effect but when the mouse moves, so does the image. as can be seen in this demo:

I figured i would multiply the second translation's coordinates by the scale factor but that also doesn't seem to do anything. What am I missing?

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=".js/0.9.0/p5.js"></script>

I know this question has been asked several times, but none of the answers I found worked for me. I need to allow the user to scale the image which works so far, it's simply a scale(factor) call but now I want to scale by the mouse pointer. This proves more difficult as I can create the zoom in on the pointer effect but when the mouse moves, so does the image. as can be seen in this demo:

https://editor.p5js/J-Cake/sketches/1r1wmWO60

I figured i would multiply the second translation's coordinates by the scale factor but that also doesn't seem to do anything. What am I missing?

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./ajax/libs/p5.js/0.9.0/p5.js"></script>

Share Improve this question edited Jul 21, 2019 at 17:08 Rabbid76 211k30 gold badges157 silver badges200 bronze badges asked Jul 21, 2019 at 8:55 J-CakeJ-Cake 1,6381 gold badge19 silver badges38 bronze badges 3
  • This might help you stackoverflow./questions/49245168/… – Nenad Vracar Commented Jul 21, 2019 at 9:03
  • @Rabbid76 the example I provided allows you to scale the image, if you move the mouse while it is scaled, the whole thing moves. – J-Cake Commented Jul 21, 2019 at 9:04
  • the wheel change causes the scale to update. p5 takes care of the updating. – J-Cake Commented Jul 21, 2019 at 9:10
Add a ment  | 

1 Answer 1

Reset to default 10

The issue is that you've to apply the scale incrementally.

A single scale (s1) from a center point (x1, y1) can be calculated by:

model = translate(x1, y1) * scale(s1) * translate(-x1, -y1) 

But if you want to apply an new scale (s2) around the center (x2, y2), then this is:

model = translate(x2, y2) * scale(s2) * translate(-x2, -y2) * currentMode;

where currentMode is the previous (scale) transformation.
This is not the same as:

model = translate(x1+x2, y1+y2) * scale(s1*s2) * translate(-(x1+x2), -(y1+y2))

A single scale (sf) from the center (mx, my) can be calcualted by:

let tx = mx - sf * mx;
let ty = my - sf * my;
translate(tx, ty);
scale(sf);

To do more of this operations consecutively, I remend to implement a 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;
}

The scale from the center can be expressed by the following 3x3 matrix:

m = [ sf, 0,  0, 
      0,  sf, 0,
      tx, ty, 1];

This leads to the following mouse wheel event:

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];
} );

In this case this can be simplified:

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;
} );

See the example. The rectangle can be scaled from the mouse cursor position either by the mouse wheel or the +/- keys:

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./ajax/libs/p5.js/0.9.0/p5.js"></script>

发布评论

评论列表(0)

  1. 暂无评论