How to use a Horizontal or Vertical scrollbar to display pixels of an image outside the window?

edited December 2017 in How To...

Hi Everyone,

I am currently making a mosaic for a Christmas prezzy. How can i use a scrollbar to display the pixels that are outside the window as i move the scrollbar across? A simple example is an image of 900px x 700px but the processing window in only 450px x 350px. The scrollbar will only be used to inspect the hidden portions of the image, to ensure that the effect works as it should across the whole image. I got the idea from The Coding Train Youtube channel. Link is Any help would be greatly appreciated.

Tagged:

Answers

  • edited December 2017

    There are heavy duty options like the unfoldingmaps library.

    The simplest possible way of doing this is to pass an argument to translate(x,y) at the beginning of your draw loop. You could set that offset with arrow key input, or just change the offset whenever the mouse is touching the edge of the screen.

    If you want to make an actual scrollbar, put your entire mosaic drawing (with the translate()) between a pushMatrix / popMatrix pair. Then draw your scrollbar.

    If you want to use a pre-made scrollbar class, consider a UI library like G4P.

  • edited December 2017

    Hey! I had this task when I was making this SAT test engine. The code for it is pretty long since you have to account for a rectangle that responds to mouse movements and have the image react accordingly. Try and see if these code snippets help :

    abstract class Button {
    
     // nColor = Normal color of button in a resting state
     // hColor = Highlighted color of button
    
     // isOver = If the mouse is over
     // isSelected = If the button is selected
     // isSelectable = If the button changes color when moused over
    
     PVector location, size;
     color nColor, hColor;
     boolean isSelected, isSelectable;
    
    
    
     Button(float locX_, float locY_, float sizeX_, float sizeY_, color nColor_) {
      location = new PVector(locX_, locY_);
      size = new PVector(sizeX_, sizeY_);
      nColor = nColor_;
      hColor = nColor + 100;
      isSelectable = true;
     }
    
     Button(float locX_, float locY_, float sizeX_, float sizeY_, color nColor_, boolean isSelectable_) {
      location = new PVector(locX_, locY_);
      size = new PVector(sizeX_, sizeY_);
      nColor = nColor_;
      hColor = nColor + 100;
      isSelectable = isSelectable_;
     }
    }
    
    class ScrollBar extends Button {
    
      boolean isActivated, isVertical;
      float mouseOffset, initialPos, previousPos, maxPos, startValue, endValue;
    
     ScrollBar(float locX_, float locY_, float sizeX, float sizeY, float startValue_, float endValue_, color nColor_, boolean isVertical_) {
      super(locX_, locY_, sizeX, sizeY, nColor_); 
      startValue = startValue_;
      endValue = endValue_;
      isVertical = isVertical_;
      if (isVertical) {
       initialPos = location.y;
       maxPos = height - (initialPos + size.y); 
      } else {
       initialPos = location.x;
       maxPos = width - (initialPos + size.x);
      }
     }
    
     void update() {
      if (clickedButton() && !isActivated) {
       isActivated = true;
       if (isVertical)
        mouseOffset = mouseY - location.y;
       else mouseOffset = mouseX - location.x;
      }
      if (isVertical)
       previousPos = location.y;
      else previousPos = location.x;
      if (isActivated && mousePressed)
       if (isVertical)
        location.y = lerp(location.y, mouseY - mouseOffset, .5);
       else location.x = lerp(location.x, mouseX - mouseOffset, .5);
      else isActivated = false;
      if (isVertical)
       location.y = constrain(location.y, initialPos, maxPos);
      else location.x = constrain(location.x, initialPos, maxPos);
     }
    
     void display() {
      if (!(overButton() || isActivated))
       fill(nColor);
      else fill(hColor); 
      rect(location.x, location.y, size.x, size.y);
     }
    
     float getScrollValue() {
      float scrollValue;
      if (isVertical)
       scrollValue = map(location.y, initialPos, maxPos, startValue, endValue); 
      else scrollValue = map(location.x, initialPos, maxPos, startValue, endValue); 
      return scrollValue;
     }
    
     void setLocation(float scrollValue) {
      float locationPos;
      if (isVertical) {
       locationPos = map(-scrollValue, startValue, endValue, initialPos, maxPos);
       location = new PVector(location.x, locationPos);
      } else {
       locationPos = map(scrollValue, startValue, endValue, initialPos, maxPos);
       location = new PVector(locationPos, location.y);    
      }
     }
    
     boolean overButton() {
       return (mouseX >= location.x && mouseX <= location.x + size.x &&
               mouseY >= location.y && mouseY <= location.y + size.y);
     }
    
     boolean clickedButton() {
       return overButton() && mousePressed; 
     }
    
     boolean wasMoved() {
      if (isVertical)
       return location.y != previousPos; 
      else return location.x != previousPos;
     }
    
    }
    

    So this is essentially the code to make a scroll bar that does respond to you when you click over it. Instead of using the example in my program, I'll have this simpler sketch that's more for your request.

  • edited December 2017

    Oh darn. Sorry about the duplicated comments :( I'll put the main sketch here as an example of how to use it :

    ScrollBar scrollBar;
    PImage cuteDog;
    
    void setup() {
      frameRate(500);
      size(545, 300);
      scrollBar = new ScrollBar(525, 0, 20, 70, -500, 500, color(100, 200, 200), true);
      cuteDog = loadImage("snow_dog.jpg");
    }
    
    void draw() {
      background(255);
      image(cuteDog, 0, scrollBar.getScrollValue());
      scrollBar.update();
      scrollBar.display();
    }
    

    Here's the dog image : https://d2pu2bk1b66iw6.cloudfront.net/photos/2015/02/03/6-91803-disappearing-corgi-1423002967.jpg

    In the constructor, the "startValue" and "endValue" stand for the values when the bar is as high and low as it can go, respectively. (It's been quite a while, this may be wrong :o)

    Hope this helps! Ask if you have any questions. I probably shouldn't just give you the code but making these took quite a while so I'd like to spare you the headache of it :)

  • Second comment duplicate. My bad.

Sign In or Register to comment.