p5.flex is a tool that creates a container to hold your p5 canvas and ensures the canvas fits the container, similar to CSS object-fit.
It offers modes like CONTAIN, COVER, FILL, NONE, and SCALE_DOWN to specify how the canvas should fit the container.
Using p5.flex can make your p5 canvas responsive while maintaining correct mouse positions ( you can still use mouseX and mouseY ! ).
Make sure to include p5 first:
<script src="https://cdn.jsdelivr.net/npm/p5@1.9.0/lib/p5.min.js"></script>Next, include p5.flex after p5. Choose one of those versions that suits your needs:
<script src="https://cdn.jsdelivr.net/npm/p5.flex@0.2.0/src/p5.flex.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5.flex@0.2.0/src/p5.flex.min.js"></script>Here's a example of using flex() to make your p5 canvas responsive:
function setup() {
createCanvas(512, 256)
// p5.flex!
// Call flex() after createCanvas()
flex()
pixelDensity(2)
background("#00647f")
}
function draw() {
fill(noise(frameCount) * 500)
circle(mouseX, mouseY, 25)
}If you're uncertain about the order of script inclusion or encounter a 'flex is not defined' error, use mountFlex() before setup() to mount p5.flex onto p5.
mountFlex(p5)
function setup() {
createCanvas(...canvasSize)
flex()
// ...
}
// ...For using the ES6 module version of p5.flex:
import { mountFlex } from "https://cdn.jsdelivr.net/npm/p5.flex@0.2.0/src/p5.flex.mjs"
// import { mountFlex } from "https://cdn.jsdelivr.net/npm/p5.flex@0.2.0/src/p5.flex.min.mjs" /* minify */
mountFlex(p5)
const sketch = (p) => {
p.setup = () => {
p.createCanvas(...canvasSize)
p.flex()
// ...
}
// ...
}
// ...To install p5.flex using npm, you can run:
npm i p5.flexExample:
import p5 from "p5"
import { mountFlex } from "p5.flex"
mountFlex(p5)
const sketch = (p) => {
p.setup = () => {
p.createCanvas(512, 256)
// p5.flex!
p.flex()
p.pixelDensity(2)
p.background("#00647f")
}
p.draw = () => {
p.fill(p.noise(p.frameCount) * 500)
p.circle(p.mouseX, p.mouseY, 25)
}
}
new p5(sketch)Adjust the following default parameters as needed:
flex({
container: {
id: undefined, // string, id for container
parent: undefined, // HTMLElement<'div'>, Parent node to which the container will be mounted
width: "100%", // string, CSS width & max-width for the container
height: "100%", // string, CSS height & max-height for the container
margin: "0", // string, CSS margin
padding: "0", // string, CSS padding, cannot use percentage
border: "0", // string, CSS border
customBoxModel: false, // boolean, Whether to use a custom box model
},
canvas: {
scale: 1, // number, Scale of the canvas (0 to 1)
fit: CONTAIN, // string, Fit mode: CONTAIN | COVER | FILL | NONE | SCALE_DOWN
},
stylePage: true, // boolean, Whether to style the HTML and body elements
})To style the container, you can use the class p5-flex-container. For the canvas, utilize the class p5-flex-canvas. Here's an example:
.p5-flex-container {
background: cyan;
}
.p5-flex-canvas {
box-shadow: 0px 0px 15px black;
}You can also set an ID for the container and use it in your CSS stylesheet. In flex():
flex({
container: {
id: "myContainer",
},
})And in your CSS:
#myContainer {
background: cyan;
}Please note that p5.flex uses inline CSS, so some CSS properties cannot be directly overwritten by a stylesheet.
If you want a custom box model for .p5-flex-container using a stylesheet, set customBoxModel to true.
.p5-flex-canvas does not provide overwrite capabilities for the box model via a stylesheet.
.p5-flex-container and .p5-flex-canvas.
p5.flex also provides some additional features:
getCanvas(): get the canvas element.getContainer(): get the container element.getParent(): get the parent element.containerBg(style: string): set the container element background.containerBgColor(...args: any[]): set the container element background color.parentBg(style: string): set the parent element background.parentBgColor(...args: any[]): set the parent element background color.NONE: a constant with the value "none".SCALE_DOWN: a constant with the value "scale_down".
p5.flex utilizes CSS to implement responsiveness. p5.flex does not use CSS object-fit. Instead, it employs CSS properties like width, height, max-width, max-height, etc. The switch between width and height values occurs only when the aspect ratio of the container and canvas differs from the previous result. This switch happens only in CONTAIN and COVER modes. If the HTML element structure is too complex and involves frequent resizing, it may incur a performance cost.
CSS object-fit can lead to incorrect mouse positions, so I choose not to use it for implementation. However, the naming of fit modes is indeed inspired by the object-fit modes.
Please refer to the MIT license for detailed licensing information.
