xxxxxxxxxx
176
let scroll;
function setup() {
createCanvas(400, 400);
scroll = new ScrollArea(100, 100, 200, 200, 400, 400, (g) => {
fill(255);
for(let i = 0; i < 400; i += 20) {
for(let j = 0; j < 400; j += 20) {
fill(i, j, 0);
rect(i, j, 20, 20);
}
}
});
}
function draw() {
background(220);
scroll.render();
}
function mousePressed() {
scroll.mouseDown();
}
function mouseDragged() {
scroll.drag();
}
function mouseReleased() {
scroll.mouseUp();
}
class ScrollArea {
constructor(x, y, w, h, cw, ch, render) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.cw = cw;
this.ch = ch;
this.renderInternal = render;
this.xEnabled = cw > w;
this.yEnabled = ch > h;
this.xOff = 0;
this.yOff = 0;
this.dragX = false;
this.dragY = false;
this.dragMain = false;
this.dragOffX = 0;
this.dragOffY = 0;
this.barWidth = 10;
}
render() {
push();
translate(this.x - this.xOff, this.y - this.yOff);
this.renderInternal();
pop();
clip(this.x, this.y, this.w, this.h);
this.renderSideBar();
this.renderBottomBar();
}
renderSideBar() {
if(!this.yEnabled) {
return;
}
fill(100);
rect(this.x + this.w, this.y, this.barWidth, this.h);
const barLength = this.h/this.ch * this.h;
const barOffset = this.yOff/this.ch * this.h;
fill(255);
rect(this.x + this.w, this.y + barOffset, this.barWidth, barLength);
}
renderBottomBar() {
if(!this.xEnabled) {
return;
}
fill(100);
rect(this.x, this.y + this.h, this.w, this.barWidth);
const barLength = this.w/this.cw * this.w;
const barOffset = this.xOff/this.cw * this.w;
fill(255);
rect(this.x + barOffset, this.y + this.h, barLength, this.barWidth);
}
mouseDown() {
if(mouseInBox(this.x, this.y, this.w, this.h)) {
this.dragMain = true;
} else {
if(this.xEnabled) {
const barLength = this.w/this.cw * this.w;
const barOffset = this.xOff/this.cw * this.w;
if(mouseInBox(this.x + barOffset, this.y + this.h, barLength, this.barWidth)) {
this.dragX = true;
this.dragOffX = mouseX - (this.x + barOffset);
}
}
if(this.yEnabled) {
const barLength = this.h/this.ch * this.h;
const barOffset = this.yOff/this.ch * this.h;
if(mouseInBox(this.x + this.w, this.y + barOffset, this.barWidth, barLength)) {
this.dragY = true;
this.dragOffY = mouseY - (this.y + barOffset);
}
}
}
}
drag() {
if(!this.dragX && !this.dragY && !this.dragMain) {
return;
}
let x = mouseX - pmouseX
let y = mouseY - pmouseY
if(this.dragX) {
y = 0;
x *= -this.cw/this.w;
}
if(this.dragY) {
x = 0;
y *= -this.ch/this.h;
}
this.move(-x, -y);
}
mouseUp() {
this.dragX = false;
this.dragY = false;
}
move(x, y) {
this.xOff += x;
this.yOff += y;
this.xOff = constrain(this.xOff, 0, this.cw - this.w);
this.yOff = constrain(this.yOff, 0, this.ch - this.h);
}
}
function mouseInBox(x, y, w, h) {
return mouseX > x && mouseX <= x + w && mouseY > y && mouseY <= y + h;
}
function clip(x, y, w, h) {
push();
blendMode(REMOVE);
fill(255, 0, 0);
noStroke();
rect(0, 0, width, y);
rect(0, y + h, width, height);
rect(0, y, x, h);
rect(x + w, y, width, h);
blendMode(BLEND);
pop();
}