Arun
Arun

Reputation: 295

The createSlider() function creates the slider outside of the canvas. How to position the slider inside the canvas?

I'm trying to implement a slider in a canvas using p5.js. If there are no HTML elements in the body of the webpage, then the canvas and the slider are on the top-left corner of the webpage.

However, when I change the position of the canvas, the slider does not stay inside the canvas. The position method sets the position of the slider ABSOLUTE with respect to the webpage.

How do I set the position of the slider inside the canvas?

This is the bare-minimum code to replicate the issue.

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>p5.js example</title>
    <style> body {padding: 0; margin: 0;} </style>
    <script src="../p5.min.js"></script>
    <script src="../addons/p5.dom.min.js"></script>
    <script src="../addons/p5.sound.min.js"></script>
    <script src="sketch.js"></script>
  </head>
  <body>
      <div>
          <p><object width="150" height="150" vspace="100"></object> 
            This is some text. This is some text. This is some text.</p>
      </div>
  </body>
</html>

The sketch.js file is:

var slider;
function setup() {
  slider = createSlider(0, 255, 100);
  slider.position(10, 10);
  slider.style('width', '80px');
}

function draw() {
  var val = slider.value();
  background(val);
}

Upvotes: 3

Views: 2603

Answers (2)

Serge Kozko
Serge Kozko

Reputation: 11

Please, check this: CSlider - Canvas Slider for p5.js with scale() support, mostly supported standard p5 slider calls: https://editor.p5js.org/Comissar/sketches/IHUYuzjR

Upvotes: 1

George Profenza
George Profenza

Reputation: 51837

p5.js' createSlider() function creates an <input /> range HTML element which is different from the <canvas/> element it uses to render the other methods.

You could use absolute positioning in tandem with z-index to have the canvas with a lower z-index and the slider with a higher z-index (on top of the canvas), both with the absolute positions you need.

If you really do want the slider rendered inside the canvas element you could roll your own slider class using the p5.js drawing functions and mouse/touch events, but it wouldn't be as CPU efficient as using an <input /> range HTML element.

Here is the Processing > Examples > Topics > GUI > Scrollbar example ported to p5.js:

/**
 * Scrollbar. 
 * 
 * Move the scrollbars left and right to change the positions of the images. 
 */

let slider;

function setup() {
  createCanvas(640, 360);
  noStroke();
  
  slider = new HScrollbar(0, height/2-8, width, 16, 16);
}

function draw() {
  background(255);
  
  fill(0);
  text("slider position: " + slider.getPos().toFixed(2),width/2,height/3);
  
  slider.update();
  slider.display();
}


class HScrollbar {
  constructor(xp, yp, sw, sh, l) {
    this.swidth = sw;
    this.sheight = sh;
    let widthtoheight = sw - sh;
    this.ratio = sw / widthtoheight;
    this.xpos = xp;
    this.ypos = yp-this.sheight/2;
    this.spos = this.xpos + this.swidth/2 - this.sheight/2;
    this.newspos = this.spos;
    this.sposMin = this.xpos;
    this.sposMax = this.xpos + this.swidth - this.sheight;
    this.loose = l;
    this.over = false;
    this.locked = false;
  }

  update() {
    if (this.overEvent()) {
      this.over = true;
    } else {
      this.over = false;
    }
    if (mouseIsPressed && this.over) {
      this.locked = true;
    }
    if (!mouseIsPressed) {
      this.locked = false;
    }
    if (this.locked) {
      this.newspos = constrain(mouseX-this.sheight/2, this.sposMin, this.sposMax);
    }
    if (abs(this.newspos - this.spos) > 1) {
      this.spos = this.spos + (this.newspos-this.spos)/this.loose;
    }
  }

  overEvent() {
    if (mouseX > this.xpos && mouseX < this.xpos+this.swidth &&
       mouseY > this.ypos && mouseY < this.ypos+this.sheight) {
      return true;
    } else {
      return false;
    }
  }

  display() {
    noStroke();
    fill(204);
    rect(this.xpos, this.ypos, this.swidth, this.sheight);
    if (this.over || this.locked) {
      fill(0, 0, 0);
    } else {
      fill(102, 102, 102);
    }
    rect(this.spos, this.ypos, this.sheight, this.sheight);
  }

  getPos() {
    // Convert spos to be values between
    // 0 and the total width of the scrollbar
    return this.spos * this.ratio;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>

Upvotes: 3

Related Questions