Reputation: 295
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
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
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