├── LICENSE
├── README.md
├── example
├── example.html
├── lib
│ ├── p5.clickable.js
│ └── p5.min.js
├── logo.png
└── sketch.js
├── images
└── logo.png
└── library
├── p5.clickable.js
└── p5.clickable.min.js
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Martín del Río
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Welcome! This is **p5.clickable**, a [p5.js](http://p5js.org) library that lets you create and customize **buttons** and assign event-based behaviours to them. With **p5.clickable** you can create buttons and define what happens when the user *hovers over*, *clicks*, *releases* or *moves* the cursor *outside* of them.
9 |
10 | Can't wait? Check [this **live example**](https://lartu.github.io/p5.clickable/example/example.html) to see some of the things this library can do. Its source code is available in the [example](example) folder of this repository.
11 |
12 | >:warning: **Attention Contributors!** It seems that in one poorly checked pull request some of the newly contributes features were deleted. Sorry! I will add them again in the next release alongside all new features.
13 |
14 | ## :telescope: Code Example
15 | With **p5.clickable** you can get a button up and running with just a few lines of code. For example, to create a plain white button at (20, 20) that when pressed changes color and shows an alert message you do:
16 |
17 | ```javascript
18 | myButton = new Clickable(); //Create button
19 | myButton.locate(20, 20); //Position Button
20 | myButton.onPress = function(){ //When myButton is pressed
21 | this.color = "#AAAAFF"; //Change button color
22 | alert("Yay!"); //Show an alert message
23 | }
24 | ```
25 | Easy as pie!
26 |
27 | ## :microscope: Documentation
28 |
29 | ### Including the p5.clickable Library
30 |
31 | To include the **p5.clickable** library into your p5.js project, copy the [p5.clickable.js](library/p5.clickable.js) file into
32 | your project directory and then add the line
33 |
34 | ```html
35 |
36 | ```
37 |
38 | to the HTML file that includes your p5.js script **after** the line that imports the p5 library, but **before** all of your personal code or the line that imports your personal code. Check the [example project HTML file](p5.clickable/example/example.html) for more information.
39 |
40 | ### Creating a Clickable
41 |
42 | **p5.clickable** provides the `Clickable` class (a *Clickable* is just a button). To create a button just instantiate a new Clickable, like this:
43 |
44 | ```javascript
45 | myButton = new Clickable();
46 | ```
47 |
48 | The starting position of a Clickable defaults to (0, 0) and its size to (100, 50).
49 |
50 | ~~You can also create it at a different location:~~
51 |
52 | >:warning: Sorry, this isn't working at the moment. It will be re-added in the next release.
53 |
54 | ```javascript
55 | myButton = new Clickable(200,300);
56 | ```
57 |
58 | ### Displaying a Clickable
59 |
60 | To **display** a Clickable, you have to call its `draw` method inside the `draw` function of your p5.js script.
61 |
62 | ```javascript
63 | function draw(){ // This is the p5.js draw function.
64 | //...
65 | myButton.draw(); // <- Draw the 'myButton' Clickable
66 | //...
67 | }
68 | ```
69 |
70 | This is very important! If you don't call this method your button will not be shown and it also **won't respond
71 | to any events**!
72 |
73 | ### Moving a Clickable
74 |
75 | To move a Clickable you can change its `x` and `y` properties. You can also use this properties to read the current
76 | location of a Clickable.
77 |
78 | ```javascript
79 | myButton.x = 100;
80 | myButton.y = 200;
81 | ```
82 |
83 | You can also use the `locate` method to change the location of a Clickable.
84 |
85 | ```javascript
86 | myButton.locate(100, 200);
87 | ```
88 |
89 | ### Resizing a Clickable
90 |
91 | To resize a Clickable you can modify its `width` and `height` properties. You can also use this properties to read the current size of a Clickable.
92 |
93 | ```javascript
94 | myButton.width = 250;
95 | myButton.height = 100;
96 | ```
97 |
98 | You can also use the `resize` method to change the size of a Clickable.
99 |
100 | ```javascript
101 | myButton.resize(250, 100);
102 | ```
103 |
104 | ### Altering the Appearance of a Clickable
105 |
106 | Clickables contain properties that can be changed to alter their appearance:
107 |
108 | ```javascript
109 | myButton.color = "#FFFFFF"; //Background color of the clickable (hex number as a string)
110 | myButton.cornerRadius = 10; //Corner radius of the clickable (float)
111 | myButton.strokeWeight = 2; //Stroke width of the clickable (float)
112 | myButton.stroke = "#000000"; //Border color of the clickable (hex number as a string)
113 | myButton.text = "Press Me"; //Text of the clickable (string)
114 | myButton.textColor = "#000000"; //Color of the text (hex number as a string)
115 | myButton.textSize = 12; //Size of the text (integer)
116 | myButton.textFont = "sans-serif"; //Font of the text (string)
117 | myButton.textScaled = false; //Whether to scale the text with the clickable (boolean)
118 | ```
119 |
120 | ### Clickable Events
121 |
122 | The Clickable class provide four methods that are called when the user interacts with a Clickable: `onOutside`, `onHover`, `onPress` and `onRelease`.
123 |
124 | `onOutside` is called whenever the cursor is not hovering over the Clickable.
125 |
126 | ```javascript
127 | myButton.onOutside = function(){
128 | console.log("Hey! Press me!");
129 | }
130 | ```
131 |
132 | `onHover` is called whenever the cursor is hovering over a Clickable, but it is not being pressed.
133 |
134 | ```javascript
135 | myButton.onHover = function(){
136 | console.log("The cursor is over me!");
137 | }
138 | ```
139 |
140 | `onPress` is called when the user presses the Clickable.
141 |
142 | ```javascript
143 | myButton.onPress = function(){
144 | console.log("I have been pressed!");
145 | }
146 | ```
147 |
148 | `onRelease` is called when the user clicks a Clickable and then releases the click while within the area of the Clickable.
149 |
150 | ```javascript
151 | myButton.onRelease = function(){
152 | console.log("I have been released!");
153 | }
154 | ```
155 |
156 | ### Images in a Clickable
157 |
158 | You can add an image to a clickable like this:
159 |
160 | ```javascript
161 | myButton.image = myImage; // myImage is an image loaded from p5's loadImage()
162 | ```
163 |
164 | By default the image will stretch to fill the button, but you can disable the stretching with the `fitImage` property.
165 |
166 | ```javascript
167 | myButton.fitImage = true; // fits the image inside the button with the image's original aspect ratio
168 | ```
169 |
170 | You can also scale the image with the `imageScale` property.
171 |
172 | ```javascript
173 | myButton.imageScale = 1.2; // useful if your image has some extra transparent padding
174 | ```
175 |
176 | ## :beers: Contributing
177 | If there's a missing feature you'd like to see on p5.clickable, feel free to write it and submit a pull request. Something broke? Please try to fix it! Also feel free to submit issues, bug reports and requests for future features.
178 |
179 | ## :scroll: Licensing
180 | The **p5.clickable** library is licensed under the MIT License. You can find a copy of the MIT License on this repository.
181 |
182 | This repository also includes code from the [p5.js](https://github.com/processing/p5.js) library, that is licensed under the LGPL 2.1 license.
183 |
--------------------------------------------------------------------------------
/example/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | p5.js example
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/lib/p5.clickable.js:
--------------------------------------------------------------------------------
1 | //Determines if the mouse was pressed on the previous frame
2 | var cl_mouseWasPressed = false;
3 | //Last hovered button
4 | var cl_lastHovered = null;
5 | //Last pressed button
6 | var cl_lastClicked = null;
7 | //All created buttons
8 | var cl_clickables = [];
9 |
10 | //This function is what makes the magic happen and should be ran after
11 | //each draw cycle.
12 | p5.prototype.runGUI = function () {
13 | for (i = 0; i < cl_clickables.length; ++i) {
14 | if (cl_lastHovered != cl_clickables[i])
15 | cl_clickables[i].onOutside();
16 | }
17 | if (cl_lastHovered != null) {
18 | if (cl_lastClicked != cl_lastHovered) {
19 | cl_lastHovered.onHover();
20 | }
21 | }
22 | if (!cl_mouseWasPressed && cl_lastClicked != null) {
23 | cl_lastClicked.onPress();
24 | }
25 | if (cl_mouseWasPressed && !mouseIsPressed && cl_lastClicked != null) {
26 | if (cl_lastClicked == cl_lastHovered) {
27 | cl_lastClicked.onRelease();
28 | }
29 | cl_lastClicked = null;
30 | }
31 | cl_lastHovered = null;
32 | cl_mouseWasPressed = mouseIsPressed;
33 | }
34 |
35 | p5.prototype.registerMethod('post', p5.prototype.runGUI);
36 |
37 | //This function is used to get the bounding size of a
38 | //string of text for use in the 'textScaled' property
39 | function getTextBounds(m, font, size) {
40 | let txt = document.createElement("span");
41 | document.body.appendChild(txt);
42 |
43 | txt.style.font = font;
44 | txt.style.fontSize = size + "px";
45 | txt.style.height = 'auto';
46 | txt.style.width = 'auto';
47 | txt.style.position = 'absolute';
48 | txt.style.whiteSpace = 'no-wrap';
49 | txt.innerHTML = m;
50 |
51 | let width = Math.ceil(txt.clientWidth);
52 | let height = Math.ceil(txt.clientHeight);
53 | document.body.removeChild(txt);
54 | return [width, height];
55 | }
56 |
57 | //Button Class
58 | function Clickable() {
59 | this.x = 0; //X position of the clickable
60 | this.y = 0; //Y position of the clickable
61 | this.width = 100; //Width of the clickable
62 | this.height = 50; //Height of the clickable
63 | this.color = "#FFFFFF"; //Background color of the clickable
64 | this.cornerRadius = 10; //Corner radius of the clickable
65 | this.strokeWeight = 2; //Stroke width of the clickable
66 | this.stroke = "#000000"; //Border color of the clickable
67 | this.text = "Press Me"; //Text of the clickable
68 | this.textColor = "#000000"; //Color for the text shown
69 | this.textSize = 12; //Size for the text shown
70 | this.textFont = "sans-serif"; //Font for the text shown
71 | this.textScaled = false; //Scale the text with the size of the clickable
72 |
73 | // image options
74 | this.image = null; // image object from p5loadimage()
75 | this.fitImage = false; // when true, image will stretch to fill button
76 | this.imageScale = 1.0;
77 | this.tint = null; // tint image using color
78 | this.noTint = true; // default to disable tinting
79 | this.filter = null; // filter effect
80 |
81 | this.updateTextSize = function () {
82 | if (this.textScaled) {
83 | for (let i = this.height; i > 0; i--) {
84 | if (getTextBounds(this.text, this.textFont, i)[0] <= this.width
85 | && getTextBounds(this.text, this.textFont, i)[1] <= this.height) {
86 | console.log("textbounds: " + getTextBounds(this.text, this.font, i));
87 | console.log("boxsize: " + this.width + ", " + this.height);
88 | this.textSize = i / 2;
89 | break;
90 | }
91 | }
92 | }
93 | }
94 | this.updateTextSize();
95 |
96 | this.onHover = function () {
97 | //This function is ran when the clickable is hovered but not
98 | //pressed.
99 | }
100 |
101 | this.onOutside = function () {
102 | //This function is ran when the clickable is NOT hovered.
103 | }
104 |
105 | this.onPress = function () {
106 | //This function is ran when the clickable is pressed.
107 | }
108 |
109 | this.onRelease = function () {
110 | //This function is ran when the cursor was pressed and then
111 | //released inside the clickable. If it was pressed inside and
112 | //then released outside this won't run.
113 | }
114 |
115 | this.locate = function (x, y) {
116 | this.x = x;
117 | this.y = y;
118 | }
119 |
120 | this.resize = function (w, h) {
121 | this.width = w;
122 | this.height = h;
123 | this.updateTextSize();
124 | }
125 |
126 | this.drawImage = function(){
127 | push();
128 | imageMode(CENTER);
129 | let centerX = this.x + this.width / 2;
130 | let centerY = this.y + this.height / 2;
131 | let imgWidth = this.width;
132 | let imgHeight = this.height;
133 | if(this.fitImage){
134 | let imageAspect = this.image.width / this.image.height;
135 | let buttonAspect = this.width / this.height;
136 | if(imageAspect > buttonAspect){ // image is wider than button
137 | imgWidth = this.width;
138 | imgHeight = this.height * (buttonAspect / imageAspect);
139 | }
140 | else{
141 | imgWidth = this.width * (imageAspect / buttonAspect);
142 | imgHeight = this.height;
143 | }
144 | }
145 |
146 | image(this.image, centerX, centerY, imgWidth * this.imageScale, imgHeight * this.imageScale);
147 |
148 | if(this.tint && !this.noTint){
149 | tint(this.tint)
150 | } else {
151 | noTint();
152 | }
153 | if(this.filter){
154 | filter(this.filter);
155 | }
156 | pop();
157 | }
158 |
159 | this.draw = function () {
160 | push();
161 | fill(this.color);
162 | stroke(this.stroke);
163 | strokeWeight(this.strokeWeight);
164 | rect(this.x, this.y, this.width, this.height, this.cornerRadius);
165 | fill(this.textColor);
166 | noStroke();
167 | if(this.image){
168 | this.drawImage();
169 | }
170 | textAlign(CENTER, CENTER);
171 | textSize(this.textSize);
172 | textFont(this.textFont);
173 | text(this.text, this.x + this.width / 2, this.y + this.height / 2);
174 | if (mouseX >= this.x && mouseY >= this.y
175 | && mouseX < this.x + this.width && mouseY < this.y + this.height) {
176 | cl_lastHovered = this;
177 | if (mouseIsPressed && !cl_mouseWasPressed)
178 | cl_lastClicked = this;
179 | }
180 | pop();
181 | }
182 |
183 | cl_clickables.push(this);
184 | }
--------------------------------------------------------------------------------
/example/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lartu/p5.clickable/2ba6079ec79d6de7100f5141ed0cc1cfa7fc5121/example/logo.png
--------------------------------------------------------------------------------
/example/sketch.js:
--------------------------------------------------------------------------------
1 | var canvas;
2 | var click1;
3 | var click2;
4 | var click3;
5 | var clickImg;
6 |
7 | function preload(){
8 | clickImg = loadImage('./logo.png');
9 | }
10 | function setup() {
11 | createCanvas(400, 400);
12 |
13 | //Create, style and resize clickables.
14 | click1 = new Clickable();
15 | click1.locate(20, 20);
16 | //This function is ran when the clickable is hovered but not pressed.
17 | click1.onHover = function () {
18 | this.color = "#AAAAFF";
19 | this.textColor = "#FFFFFF";
20 | this.text = "Yay!";
21 | }
22 | //This function is ran when the clickable is NOT hovered.
23 | click1.onOutside = function () {
24 | this.color = "#EEEEEE";
25 | this.text = "Hello there!";
26 | this.textColor = "#000000";
27 | }
28 | //This function is ran when the clickable is pressed.
29 | click1.onPress = function () {
30 | this.stroke = "#FF0000";
31 | }
32 | //This funcion is ran when the cursor was pressed and then
33 | //rleased inside the clickable. If it was pressed inside and
34 | //then released outside this won't work.
35 | click1.onRelease = function () {
36 | this.x += 50;
37 | }
38 |
39 | click2 = new Clickable();
40 | click2.cornerRadius = 0;
41 | click2.textScaled = true;
42 | click2.text = "hello";
43 | click2.locate(60, 60);
44 | click2.resize(250, 100);
45 | click2.onOutside = function () {
46 | this.color = "#FFFFFF";
47 | }
48 | click2.onHover = function () {
49 | this.color = "#AA33AA";
50 | }
51 | click2.onPress = function () {
52 | alert("Hi there!");
53 | }
54 |
55 | click3 = new Clickable();
56 | click3.image = clickImg;
57 | click3.locate(280,250);
58 | click3.resize(100,100);
59 | click3.text = "";
60 | click3.onHover = function () {
61 | this.color = "#AA33AA";
62 | this.noTint = false;
63 | this.tint = "#FF0000";
64 | }
65 | click3.onOutside = function () {
66 | this.color = "#FFFFFF";
67 | this.noTint = true;
68 | }
69 |
70 | // image will stretch to fill button by default
71 | click4 = new Clickable();
72 | click4.image = clickImg;
73 | click4.imageScale = 1;
74 | click4.text = "";
75 | click4.locate(10, 200);
76 | click4.resize(120, 90);
77 | click4.onHover = function () {
78 | click4.imageScale = 1.1;
79 | }
80 | click4.onOutside = function () {
81 | click4.imageScale = 1;
82 | }
83 |
84 | // centered and fitted
85 | click5 = new Clickable();
86 | click5.image = clickImg;
87 | click5.fitImage = true; // no stretching!
88 | click5.imageScale = 1;
89 | click5.text = "";
90 | click5.locate(140, 200);
91 | click5.resize(120, 90);
92 | click5.onHover = function () {
93 | click5.imageScale = 1.1;
94 | }
95 | click5.onOutside = function () {
96 | click5.imageScale = 1;
97 | }
98 | }
99 |
100 | function draw() {
101 | background(255);
102 | click1.draw();
103 | click2.draw();
104 | click3.draw();
105 | click4.draw();
106 | click5.draw();
107 | }
108 |
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lartu/p5.clickable/2ba6079ec79d6de7100f5141ed0cc1cfa7fc5121/images/logo.png
--------------------------------------------------------------------------------
/library/p5.clickable.js:
--------------------------------------------------------------------------------
1 | //Determines if the mouse was pressed on the previous frame
2 | var cl_mouseWasPressed = false;
3 | //Last hovered button
4 | var cl_lastHovered = null;
5 | //Last pressed button
6 | var cl_lastClicked = null;
7 | //All created buttons
8 | var cl_clickables = [];
9 |
10 | //This function is what makes the magic happen and should be ran after
11 | //each draw cycle.
12 | p5.prototype.runGUI = function () {
13 | for (i = 0; i < cl_clickables.length; ++i) {
14 | if (cl_lastHovered != cl_clickables[i])
15 | cl_clickables[i].onOutside();
16 | }
17 | if (cl_lastHovered != null) {
18 | if (cl_lastClicked != cl_lastHovered) {
19 | cl_lastHovered.onHover();
20 | }
21 | }
22 | if (!cl_mouseWasPressed && cl_lastClicked != null) {
23 | cl_lastClicked.onPress();
24 | }
25 | if (cl_mouseWasPressed && !mouseIsPressed && cl_lastClicked != null) {
26 | if (cl_lastClicked == cl_lastHovered) {
27 | cl_lastClicked.onRelease();
28 | }
29 | cl_lastClicked = null;
30 | }
31 | cl_lastHovered = null;
32 | cl_mouseWasPressed = mouseIsPressed;
33 | }
34 |
35 | p5.prototype.registerMethod('post', p5.prototype.runGUI);
36 |
37 | //This function is used to get the bounding size of a
38 | //string of text for use in the 'textScaled' property
39 | function getTextBounds(m, font, size) {
40 | let txt = document.createElement("span");
41 | document.body.appendChild(txt);
42 |
43 | txt.style.font = font;
44 | txt.style.fontSize = size + "px";
45 | txt.style.height = 'auto';
46 | txt.style.width = 'auto';
47 | txt.style.position = 'absolute';
48 | txt.style.whiteSpace = 'no-wrap';
49 | txt.innerHTML = m;
50 |
51 | let width = Math.ceil(txt.clientWidth);
52 | let height = Math.ceil(txt.clientHeight);
53 | document.body.removeChild(txt);
54 | return [width, height];
55 | }
56 |
57 | //Button Class
58 | function Clickable(x,y) {
59 | this.x = x; //X position of the clickable
60 | this.y = y; //Y position of the clickable
61 | this.width = 100; //Width of the clickable
62 | this.height = 50; //Height of the clickable
63 | this.color = "#FFFFFF"; //Background color of the clickable
64 | this.cornerRadius = 10; //Corner radius of the clickable
65 | this.strokeWeight = 2; //Stroke width of the clickable
66 | this.stroke = "#000000"; //Border color of the clickable
67 | this.text = "Press Me"; //Text of the clickable
68 | this.textColor = "#000000"; //Color for the text shown
69 | this.textSize = 12; //Size for the text shown
70 | this.textFont = "sans-serif"; //Font for the text shown
71 | this.textScaled = false; //Scale the text with the size of the clickable
72 |
73 | // image options
74 | this.image = null; // image object from p5loadimage()
75 | this.fitImage = false; // when true, image will stretch to fill button
76 | this.imageScale = 1.0;
77 | this.tint = null; // tint image using color
78 | this.noTint = true; // default to disable tinting
79 | this.filter = null; // filter effect
80 |
81 | this.updateTextSize = function () {
82 | if (this.textScaled) {
83 | for (let i = this.height; i > 0; i--) {
84 | if (getTextBounds(this.text, this.textFont, i)[0] <= this.width
85 | && getTextBounds(this.text, this.textFont, i)[1] <= this.height) {
86 | console.log("textbounds: " + getTextBounds(this.text, this.font, i));
87 | console.log("boxsize: " + this.width + ", " + this.height);
88 | this.textSize = i / 2;
89 | break;
90 | }
91 | }
92 | }
93 | }
94 | this.updateTextSize();
95 |
96 | this.onHover = function () {
97 | //This function is ran when the clickable is hovered but not
98 | //pressed.
99 | }
100 |
101 | this.onOutside = function () {
102 | //This function is ran when the clickable is NOT hovered.
103 | }
104 |
105 | this.onPress = function () {
106 | //This function is ran when the clickable is pressed.
107 | }
108 |
109 | this.onRelease = function () {
110 | //This function is ran when the cursor was pressed and then
111 | //released inside the clickable. If it was pressed inside and
112 | //then released outside this won't run.
113 | }
114 |
115 | this.locate = function (x, y) {
116 | this.x = x;
117 | this.y = y;
118 | }
119 |
120 | this.resize = function (w, h) {
121 | this.width = w;
122 | this.height = h;
123 | this.updateTextSize();
124 | }
125 |
126 | this.drawImage = function(){
127 | push();
128 | imageMode(CENTER);
129 | let centerX = this.x + this.width / 2;
130 | let centerY = this.y + this.height / 2;
131 | let imgWidth = this.width;
132 | let imgHeight = this.height;
133 | if(this.fitImage){
134 | let imageAspect = this.image.width / this.image.height;
135 | let buttonAspect = this.width / this.height;
136 | if(imageAspect > buttonAspect){ // image is wider than button
137 | imgWidth = this.width;
138 | imgHeight = this.height * (buttonAspect / imageAspect);
139 | }
140 | else{
141 | imgWidth = this.width * (imageAspect / buttonAspect);
142 | imgHeight = this.height;
143 | }
144 | }
145 |
146 | image(this.image, centerX, centerY, imgWidth * this.imageScale, imgHeight * this.imageScale);
147 |
148 | if(this.tint && !this.noTint){
149 | tint(this.tint)
150 | } else {
151 | noTint();
152 | }
153 | if(this.filter){
154 | filter(this.filter);
155 | }
156 | pop();
157 | }
158 |
159 | this.draw = function () {
160 | push();
161 | fill(this.color);
162 | stroke(this.stroke);
163 | strokeWeight(this.strokeWeight);
164 | rect(this.x, this.y, this.width, this.height, this.cornerRadius);
165 | fill(this.textColor);
166 | noStroke();
167 | if(this.image){
168 | this.drawImage();
169 | }
170 | textAlign(CENTER, CENTER);
171 | textSize(this.textSize);
172 | textFont(this.textFont);
173 | text(this.text, this.x + this.width / 2, this.y + this.height / 2);
174 | if (mouseX >= this.x && mouseY >= this.y
175 | && mouseX < this.x + this.width && mouseY < this.y + this.height) {
176 | cl_lastHovered = this;
177 | if (mouseIsPressed && !cl_mouseWasPressed)
178 | cl_lastClicked = this;
179 | }
180 | pop();
181 | }
182 |
183 | cl_clickables.push(this);
184 | }
185 |
--------------------------------------------------------------------------------
/library/p5.clickable.min.js:
--------------------------------------------------------------------------------
1 | var cl_mouseWasPressed=!1,cl_lastHovered=null,cl_lastClicked=null,cl_clickables=[];function getTextBounds(t,i,e){let s=document.createElement("span");document.body.appendChild(s),s.style.font=i,s.style.fontSize=e+"px",s.style.height="auto",s.style.width="auto",s.style.position="absolute",s.style.whiteSpace="no-wrap",s.innerHTML=t;let h=Math.ceil(s.clientWidth),l=Math.ceil(s.clientHeight);return document.body.removeChild(s),[h,l]}function Clickable(){this.x=0,this.y=0,this.width=100,this.height=50,this.color="#FFFFFF",this.cornerRadius=10,this.strokeWeight=2,this.stroke="#000000",this.text="Press Me",this.textColor="#000000",this.textSize=12,this.textFont="sans-serif",this.textScaled=!1,this.image=null,this.fitImage=!1,this.imageScale=1,this.tint=null,this.noTint=!0,this.filter=null,this.updateTextSize=function(){if(this.textScaled)for(let t=this.height;t>0;t--)if(getTextBounds(this.text,this.textFont,t)[0]<=this.width&&getTextBounds(this.text,this.textFont,t)[1]<=this.height){console.log("textbounds: "+getTextBounds(this.text,this.font,t)),console.log("boxsize: "+this.width+", "+this.height),this.textSize=t/2;break}},this.updateTextSize(),this.onHover=function(){},this.onOutside=function(){},this.onPress=function(){},this.onRelease=function(){},this.locate=function(t,i){this.x=t,this.y=i},this.resize=function(t,i){this.width=t,this.height=i,this.updateTextSize()},this.drawImage=function(){push(),imageMode(CENTER);let t=this.x+this.width/2,i=this.y+this.height/2,e=this.width,s=this.height;if(this.fitImage){let t=this.image.width/this.image.height,i=this.width/this.height;t>i?(e=this.width,s=this.height*(i/t)):(e=this.width*(t/i),s=this.height)}image(this.image,t,i,e*this.imageScale,s*this.imageScale),this.tint&&!this.noTint?tint(this.tint):noTint(),this.filter&&filter(this.filter),pop()},this.draw=function(){push(),fill(this.color),stroke(this.stroke),strokeWeight(this.strokeWeight),rect(this.x,this.y,this.width,this.height,this.cornerRadius),fill(this.textColor),noStroke(),this.image&&this.drawImage(),textAlign(CENTER,CENTER),textSize(this.textSize),textFont(this.textFont),text(this.text,this.x+this.width/2,this.y+this.height/2),mouseX>=this.x&&mouseY>=this.y&&mouseX