| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
🆕 Teachers' Guide to p5.js v2: p5.js v2 Transition Guide for Middle School and High School Educators
The p5.js v2 library is now the default version on our website and in the editor. Although p5.js v1 remains available (reference at [hv1.p5js.org/][https://v1.p5js.org/]), it will not be maintained.
Between v1 and v2, there are many additions, and some breaking changes. Most sketches work in v2 directly. When sketches do not work, you can either update them (read p5.js v2 Transition Guide for Middle School and High School Educators for most common updates, or the rest of this README for the full list), or use one of the compatibility add-on libraries. These libraries make v1 features available in v2.
These add-on libraries are available in the p5.js Editor in the Settings > Library Management modal:
These changes affect authoring of p5.js sketches. Read on for more information on how to transition, or how to use relevant compatibility addons.
If you’re interested in the history of async read on here!
To play around, check out the example from the p5.js 1.x preload() reference, but get a very big file instead of bricks.jpg.
| p5.js 1.x | p5.js 2.x |
|---|---|
| Blank “Loading…” screen, then image shown | Red background while image loads |
let img;
function preload() {
img = loadImage('bricks.jpg');
}
function setup() {
createCanvas(100, 100);
// Red backgorund is ignored
background(255, 0, 0);
// Draw the image.
image(img, 0, 0);
describe('A red brick wall.');
} |
let img;
async function setup() {
createCanvas(100, 100);
// Red background while asset loads
background(255, 0, 0);
// Wait for the image to load
img = await loadImage('bricks.jpg');
// Draw the image.
image(img, 0, 0);
describe('A red brick wall.');
} |
If it takes a while to load the image, the sketch will be "paused" on the line img = await loadImage('/assets/bricks.jpg'); - once the image is loaded, it will resume.
Laslty, some loader functions have been updated:
All of the above usages in p5.js 1.x remain available with the preload.js compatibility add-on library.
Important notes for developers of p5.js add-on libraries who want to support both p5.js v1 and p5.js v2Under the hood, returns a Promise from each loadImage, loadSound, and similar functions. Promises are widely used in JavaScript, so it is possible to use a callback in p5.js 1.x to create a Promise, but p5.js 1.x doesn't expect promises to be used, so you have to ensure yourself that, for example, your draw function doesn't start running before loading is done. For an example of a Promise using a callback, check out the example below that makes p5.sound.js compatible with both 1.x and 2.0:
If your add-on library built with p5.js 1.x uses registerPreloadMethod such as in this example from p5.sound.js:
p5.prototype.registerPreloadMethod('loadSound', p5.prototype);Then to make your add-on library compatible with both p5.js 1.x (preload) and p5.js 2.0 (promises), this this line can be removed (the method loadSound, in this example, does not need to be registered) and the method can be updated as follows:
function loadSound (path) {
if(self._incrementPreload && self._decrementPreload){
// tTis is the check to determine if preload() is being used, as with
// p5.js 1.x or with the preload compatibility add-on library. The function
// returns the soundfile.
self._incrementPreload();
let player = new p5.SoundFile(
path,
function () {
// The callback indicates to preload() that the file is done loading
self._decrementPreload();
}
);
return player;
}else{
// Otherwise, async/await is being used, so the function returns a promise,
// which loads the soundfile asynchronously.
return new Promise((resolve) => {
let player = new p5.SoundFile(
path,
function () {
// The callback resolves the promise when the file is done loading
resolve(player);
}
);
});
}
}And that's it! You can check this example of making an add-on library backwards-compatible and work with p5.js 2.0 here: the p5.sound.js example
If you use `vertex` and `bezierVertex` is the p5.js v1 code, here are the changes your code will need.The below code is based on the custom shapes tutorial:
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
function draw() {
translate(width/2, height/2);
// Draw the curved star shape - use one of the snippets below, depending on p5.js version
describe("A white star on a gray background in the middle of the canvas")
}| p5.js 1.x | p5.js 2.x |
|---|---|
// Draw the curved star shape.
beginShape();
// Original anchor at top.
vertex(0, -100);
// Top-right curve.
bezierVertex(0, -50, 50, 0, 100, 0);
// Bottom-right curve.
bezierVertex(50, 0, 0, 50, 0, 100);
// Bottom-left curve.
bezierVertex(0, 50, -50, 0, -100, 0);
// Top-left curve.
bezierVertex(-50, 0, 0,-50, 0,-100);
endShape(); |
// Draw the curved star shape.
beginShape();
// The default value is 3,
bezierOrder(3);
// Original anchor at top.
bezierVertex(0, -100);
// Top-right curve.
bezierVertex(0, -50);
bezierVertex(50, 0);
bezierVertex(100, 0);
// Bottom-right curve.
bezierVertex(50, 0);
bezierVertex(0, 50);
bezierVertex(0, 100);
// Bottom-left curve.
bezierVertex(0, 50);
bezierVertex(-50, 0);
bezierVertex(-100, 0);
// Top-left curve.
bezierVertex(-50, 0);
bezierVertex(0, -50);
bezierVertex(0,-100);
endShape(); |
| p5.js 1.x | p5.js 2.x |
|---|---|
// https://p5js.org/reference/p5/quadraticVertex/
function setup() {
createCanvas(100, 100);
background(200);
// Start drawing the shape.
beginShape();
// Add the curved segments.
vertex(20, 20);
quadraticVertex(80, 20, 50, 50);
quadraticVertex(20, 80, 80, 80);
// Add the straight segments.
vertex(80, 10);
vertex(20, 10);
vertex(20, 20);
// Stop drawing the shape.
endShape();
describe('White puzzle piece on gray background.');
} |
// Achieve the same curve with bezierOrder(2)
function setup() {
createCanvas(100, 100);
background(200);
// Start drawing the shape.
beginShape();
bezierOrder(2);
// Add the curved segments.
bezierVertex(20, 20);
bezierVertex(80, 20);
bezierVertex(50, 50);
bezierVertex(20, 80);
bezierVertex(80, 80);
// Add the straight segments.
vertex(80, 10);
vertex(20, 10);
vertex(20, 20);
// Stop drawing the shape.
endShape();
describe('White puzzle piece on gray background.');
} |
The custom shapes tutorial has a bit more detail on this, but Bézier curves need multiple points. In p5.js 1.x, they use three control points. In p5.js 2.0, that number is set by bezierOrder. Then, in p5.js 1.x each bezierVertex(...) was actually a set of three points describing a smooth curve. In p5.js 2.0, each bezierVertext(x, y) is just one point; you need the first point to anchor, and each curve after that needs 3 points.
Additional shanges to shapes in p5.js 1.x, compared to p5.js 2.0, are as follows:
Finally, the behavior of endShape allows creating different shapes.
| p5.js 1.x | p5.js 2.x |
|---|---|
function setup() {
createCanvas(100, 100);
background(200);
beginShape();
// Add the first control point.
curveVertex(32, 91);
curveVertex(32, 91);
// Add the anchor points.
curveVertex(21, 17);
curveVertex(68, 19);
// Add the second control point.
curveVertex(84, 91);
curveVertex(84, 91);
// Stop drawing the shape.
endShape(CLOSE);
} |
function setup() {
createCanvas(100, 100);
background(200);
beginShape();
// Control points not needed
// if the goal is a smooth close
// splineVertex(32, 91);
splineVertex(32, 91);
// Add the anchor points.
splineVertex(21, 17);
splineVertex(68, 19);
// Second control point also excluded
// splineVertex(82, 91);
splineVertex(82, 91);
endShape(CLOSE);
} |
All of the above usages in p5.js 1.x remain available with the shapes.js compatibility add-on library.
In p5.js 2.x, there are two ways to measure text: [fontWidth(...)](https://p5js.org/reference/p5/fontwidth/) and [textWidth(...)](https://p5js.org/reference/p5/textwidth/). In 2.x, `textWidth()` calculates the text's tight bounding box, which is what p5.js 1.x `fontWidth()` does.| p5.js 1.x | p5.js 2.x |
|---|---|
function setup() {
createCanvas(100, 100);
let s = " Hello ";
console.log(textWidth(s));
// Measurement that includes the spaces
} |
function setup() {
createCanvas(100, 100);
let s = " Hello ";
console.log(fontWidth(s));
// Measurement that includes the spaces
} |
|
No equivalent |
function setup() {
createCanvas(100, 100);
let s = " Hello ";
console.log(textWidth(s));
// Measurement does not include
// leading/trailing spaces
} |
These were originally in p5.js v1 because, historically, they were also in Processing. However, p5.js is a JavaScript library, and JavaScript objects and key-value maps can be used instead of these functions:
Instead of the above functions, we would recommend using built-in JavaScript Objects
The below functions are also better supported in JavaScript itself:
All of the above usages in p5.js 1.x remain available with the data.js compatibility add-on library.
In v1, where the `mouseButton` was a single variable that could have values `left`, `right` and `center`, we cannot detect if the `left` and `right` button have been pressed together. In v2, the `mouseButton` is now an object with properties: `left`, `right` and `center`, which are booleans indicating whether each button has been pressed respectively. This means that we can now detect if multiple buttons are pressed together (like if the `left` and `right` button are pressed together).function setup() {
createCanvas(100, 100);
describe(
"A gray square. Different shapes appear at its center depending on the mouse button that's pressed."
);
}| p5.js 1.x | p5.js 2.x |
|---|---|
function draw() {
background(200);
fill(255, 50);
if (mouseIsPressed === true) {
if (mouseButton === LEFT) {
circle(50, 50, 50);
}
if (mouseButton === RIGHT) {
square(25, 25, 50);
}
if (mouseButton === CENTER) {
triangle(23, 75, 50, 20, 78, 75);
}
}
} |
function draw() {
background(200);
fill(255, 50);
if (mouseIsPressed === true) {
if (mouseButton.left) {
circle(50, 50, 50);
}
if (mouseButton.right) {
square(25, 25, 50);
}
if (mouseButton.center) {
triangle(23, 75, 50, 20, 78, 75);
}
}
} |
Notice that when you press multiple buttons at the same time, multiple shapes can be obtained.
Finally, touch and mouse event handling has been combined to improve sketch consistency across devices. In p5.js 2.0, instead of having separate methods for mouse and touch, we now use the browser's pointer API to handle both simultaneously. Try defining mouse functions as usual and accessing the global touches array to see what pointers are active for multitouch support!
| p5.js 1.x | p5.js 2.x |
|---|---|
|
// On a touchscreen device, touch the canvas using one or more fingers
// at the same time.
function setup() {
createCanvas(100, 100);
describe(
'A gray square. White circles appear where the user touches the square.'
);
}
function draw() {
background(200);
// Draw a circle at each touch point.
for (let touch of touches) {
circle(touch.x, touch.y, 40);
}
} |
let x = 50;
let y = 50;
function setup() {
createCanvas(100, 100);
background(200);
describe(
'A gray square with a black circle at its center. The circle moves when the user presses an arrow key. It leaves a trail as it moves.'
);
}
function draw() {
// Update x and y when arrow keys are pressed
// Using keyIsDown() will work in all version of p5.js
if (keyIsPressed) {
if (keyIsDown(UP_ARROW)) {
y -= 1;
} else if (keyIsDown(DOWN_ARROW)) {
y += 1;
} else if (keyIsDown(LEFT_ARROW)) {
x -= 1;
} else if (keyIsDown(RIGHT_ARROW)) {
x += 1;
}
}
// Style the circle.
fill(0);
// Draw the circle at (x, y).
circle(x, y, 5);
}Although keyIsDown() can be used with system-level constants like UP_ARROW in all versions, the below shows a bit of what has changed behind the scenes - so if you use key or code in your sketch, you may need to update your code:
| p5.js 1.x | p5.js 2.x |
|---|---|
function draw() {
// Update x and y when arrow keys are pressed
if (keyIsPressed === true) {
if (keyCode === UP_ARROW) {
y -= 1;
} else if (keyCode === DOWN_ARROW) {
y += 1;
} else if (keyCode === LEFT_ARROW) {
x -= 1;
} else if (keyCode === RIGHT_ARROW) {
x += 1;
}
}
// Style the circle.
fill(0);
// Draw the circle at (x, y).
circle(x, y, 5);
} |
function draw() {
// Update x and y when arrow keys are pressed
if (code === UP_ARROW) {
y -= 1;
} else if (code === DOWN_ARROW) {
y += 1;
} else if (code === LEFT_ARROW) {
x -= 1;
} else if (code === RIGHT_ARROW) {
x += 1;
}
// Style the circle.
fill(0);
// Draw the circle at (x, y).
circle(x, y, 5);
} |
keyCode is still a Number system variable in 2.x.
if (keyCode === 13) {
// Code to run if the enter key was pressed.
}In 1.x system variables could be used using keyCode
if (keyCode === "ENTER") {
// Code to run if the enter key was pressed.
}Instead, in 2.x you can use the key or code function to directly compare the key value.
Using key:
if (key === 'Enter') {
// Code to run if the Enter key was pressed.
}Using code:
if (code === 'KeyA') {
// Code to run if the 'A' key was pressed.
}Both numeric and string key codes can be found at keycode.info.
The new p5.sound.js includes some breaking changes. Many of these changes include the removal of classes that we deemed redundant when considering the existence of [Tone.js](https://tonejs.github.io/). You can read more about this decision here: [Announcing the New p5.sound.js Library](https://medium.com/processing-foundation/announcing-the-new-p5-sound-js-library-42efc154bed0).If you want to use any of the deprecated classes or features, you may find the original p5.sound library in the editor (with any of the v1 versions) and the original reference docs here: https://v1.p5js.org/reference/p5.sound/
A collection of examples using the 2.0 library can be found in the following places.
Most things are the same between p5.sound.js 1.x and 2.0, but there are some big differences: For starters, p5.sound.js 2.0 has fewer classes than the original library. There is also a more streamlined API (fewer redundancies, etc...). If you need access to some of the deprecated classes such as p5.MonoSynth() for example, use Tone.js. For more information on these changes read the announcement for the new p5.sound.js library here.
One of the biggest changes in the new p5.sound.js library is how we handle loading sound files. Instead of loading a sound file in the preload() function, the loadSound(...) function returns a promise in an async/await in setup() (or with callbacks) (to revert to 1.x use, include preload.js)
For example:
let sound;
async function setup() {
sound = await loadSound('path/to/soundFile');
createCanvas(100, 100);
describe(
'A gray square with text that reads "click to play the sound".');
textWrap(WORD)
textAlign(CENTER)
}
function draw() {
background(200);
text('click to play the sound', 0, 20, width);
}
function mousePressed() {
sound.play();
}When using a deprecated class such as MonoSynth, EQ, Convolver, Distortion, OnsetDetect, Filter, Effect, Compressor, AudioVoice, Part, Phrase, PolySynth, Pulse, Score, SoundLoop you will see an alert that tells you that the class 'is deprecated' and to 'Try using the equivalent Tone.js class'.
To combine p5.sound.js and Tone.js nodes, you will have to pass the p5.sound.js AudioContext to Tone.js. You can do this like so:
<!-- include Tone.js after the p5.sound.js library-->
<script src="p5.sound.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tone@15.0.2/build/Tone.js"></script>let sound_location = 0
let panner, synthy
function setup() {
createCanvas(400, 400)
// Tone.js is loaded from its own script tag. Hand it p5.sound's audio
// context before making any Tone.js object, and the two libraries build on
// one context, so their nodes can be connected to each other.
Tone.setContext(getAudioContext())
synthy = new Tone.MonoSynth()
panner = new p5.Panner()
// connect a Tone.js audio node to a p5 sound effect
panner.setInput(synthy)
describe('A grey sketch that plays a Tone.js synth through a p5.sound panner. Click to play a note at a random stereo position.')
}
function draw() {
background(220)
text("sound is here", ((sound_location + 1) * 0.5 ) * width, height/2)
}
function mousePressed() {
sound_location = random(-1,1)
panner.pan(sound_location)
synthy.triggerAttackRelease("D#5", (1.5))
}Here is the spreadsheet that lists the deprecated clases and methods.
In most cases, nothing needs to change! However, if your sketch relied on p5 automatically turning off a shader, you may need to manually scope your shader between a `push` and `pop`.For example, if you had a shader that did not use p5's lighting system, in 1.x, it would stop applying once you turn on lighting:
shader(myShaderWithoutLighting);
sphere(100); // Draws with your shader
translate(100, 0);
lights();
sphere(100); // Draws without your shaderIn 2.x, you would need to manually contain the shader to the first shape:
push();
shader(myShaderWithoutLighting);
sphere(100);
pop(); // Resets the shader
translate(100, 0);
lights();
sphere(100);Alternatively, you can use resetShader:
shader(myShaderWithoutLighting);
sphere(100);
resetShader(); // Resets the shader
translate(100, 0);
lights();
sphere(100);| Back | FazBrowse Home | New Git URL |