Zooming + Scrolling in a Procedural Drawing Application need some help finishing off

Hi guys, I made a post a long while ago working on the zoom interface for this drawing app Ive been working on, Ive got it closish to what I want but am having issues with figuring out how to make the zoom focus on the mouse pointer.

The problem is im not that great at math, and Im pretty sure theres something Im missing in algebra here.
The scale is only working to the top left corner of the canvas, Im trying to figure out how to make it zoom in to where the mouse is pointing.

Also, how would I go about limiting the whole canvas zoom, so the image doesnt become too small in the window and leave glitches if you zoom out too far… or maybe have somesort of a non drawable background that is constantly refreshed? (Im literally thinking of just making the layer canvases larger and putting in a grey rectangle around them or something that cant be drawn on)

Currently, the zoom works like this: Mid MouseScroll wheel to zoom in and out, and left shift + scroll wheel to move side to side or ctrl+mousewheel scroll to move up and down.

Ive still yet to figure out how to add scroll bars

Muchly appreciated, a lot of artists have been wanting to use this app and I feel im really close to a more or less usable demo of it!

Code:

float speed;
float pos;
float c0, c1, c2, c3;
boolean auto;

void settings() {
  size(400, 400);
}



boolean isShifting = false; //is the canvas being moved

float offsetX =0;
float offsetY =0;

PGraphics layer_1; //mid layer onto which things will be onto and will be merged with c_1
PGraphics layer_2;


boolean shiftPressed = false;

boolean ctrlPressed = false;



int l1_T = 255; //transparency for the layers
int l2_T = 255; //transparency for the layers

float distThresh = 200;
ArrayList points = new ArrayList();

float locY =0;
float locX=0;

float scalar = 1;


//UI

boolean uI = false;



void setup() {




  size(500, 500); //c_0 size smaller than main canvases
  background(255); //c_0 background

  noStroke();



  //UI END


  layer_1 = createGraphics(1000, 1000, JAVA2D); // the canvases are larger than the draw area
  layer_2 = createGraphics(1000, 1000);  // the canvases are larger than the draw area
}

void draw() {



  noCursor();

  pushMatrix();
  scale(scalar);
  offsetX = mouseX /scalar - locX ;
  offsetY = mouseY /scalar - locY;

  layer_1.beginDraw();
  layer_1.background(128);

  layer_1.tint(255, l1_T);
  layer_1.image(layer_2, 0, 0);




  layer_1.endDraw();



  if (mousePressed && (mouseButton == LEFT)) {    

    sketcher(layer_2, points, 200);
  }

  image(layer_1, locX, locY); // 0 0

  popMatrix();

  rect(0, 0, 210, 210); //viewfinder frame


  noFill();
  stroke(0, 40);
  ellipse(mouseX, mouseY, distThresh/10, distThresh/10);
}

//Sketcher Code itself

void sketcher(PGraphics layer, ArrayList pointsList, int threshHold) {
  layer.beginDraw();
  layer.smooth();
  PVector mouseCord = new PVector(offsetX, offsetY);
  pointsList.add(mouseCord);
  for (int  index = 0; index < points.size(); index++) {
    PVector v = (PVector) pointsList.get(index);
    float joinchance = mouseCord.dist(v) / threshHold;
    if (joinchance < 0.1) {
      float dx = mouseCord.x - v.x;
      float dy = mouseCord.y - v.y;
      float angle = atan2(dy, dx);
      float pad = mouseCord.dist(v)/4;
      layer.stroke(0, 0, 0, 255);
      layer.line(mouseCord.x - (pad * cos(angle)), mouseCord.y - (pad * sin(angle)), v.x + (pad * cos(angle)), v.y + (pad * sin(angle)) );
    }
  }

  layer.endDraw();
}


//MouseWheel and MouseEvents

void mouseWheel(MouseEvent event) {

  float e = event.getCount();

  if (shiftPressed == false && ctrlPressed == false) {
    scalar += (e*.1);
    distThresh += (e/1);
    println(scalar, distThresh);
  }

  if (shiftPressed == true) {
    locX += (e*10);
  } 

  if (ctrlPressed == true) {
    locY += (e*10);
  }

  if (locX>0) {
    locX = 0;
  }
  if (locY>0) {
    locY = 0;
  }
  if (locX < -500) {
    locX = -500;
  }
  if (locY < -500) {
    locY = -500;
  }
}

//Keys and KeyCodes


void keyPressed() {


  if (key == CODED) {
    if (keyCode == SHIFT) {
      shiftPressed = true;
    }

    if (keyCode == CONTROL) {
      ctrlPressed = true;
    }
  }
  println(locX, locY);
}


void keyReleased() {
  if (key == CODED) {
    if (keyCode == SHIFT) {
      shiftPressed = false;
    }

    if (keyCode == CONTROL) {
      ctrlPressed = false;
    }
  }
}

I use this in my sketch.
See https://github.com/cameyo42/layers

//*********************************
// zoom canvas
// draw zoom window at mouse cursor
void showZoom(float zoomFactor)
{
  // draw zoom window at mouse cursor
  int x = mouseX;
  int y = mouseY;
  int u, v;
  int xsize = 250;
  int ysize = 250;
  canvasIMG = get(0,0,width,height);
  for (int vd = - ysize; vd < ysize; vd++)
  {
    for (int ud = - xsize; ud < xsize; ud++)
    {
        u = floor(ud/zoomFactor) + mouseX;
        v = floor(vd/zoomFactor) + mouseY;
        if (u >= 0 && u < canvasIMG.width && v >= 0 && v < canvasIMG.height)
          { set(ud + x, vd + y, canvasIMG.get(u, v)); }
    }
  }
  // draw zoom window border
  noFill();
  stroke(255,30,30,100);
  rectMode(CENTER);
  rect(mouseX,mouseY,2*xsize,2*ysize);
  rectMode(CORNER);
}
1 Like

Hi Cameyo, really sorry for such a delayed reply! Your drawing program is literally what Ive been trying to create over the last 2 years haha. Ive been digging around in your code and would just like to ask if you have figure out a way to make the canvas bigger? Id honestly pay you a comission just to complete that last part of your program - Im a visual artist and have been working through processing and would honestly love to comission you for that feature, as I would then be able to make high res work on it. If you are interested can you pass me your email, or just shoot me a message on fyodor.krasniy@gmail.com
-F

I sent an email to you.
cameyo