Hi,
I would like to use an existing canvas with p5js. It seems not possible in a simple way.
The reason I want to do that is: I don’t want p5js to insert a canvas and make my already displayed page to suddenly extend. This will generally not happen because the script will start quickly, but I have no guarantee this won’t happen to someone whose browser takes too much time to download the p5j library. I hate it when a page extends itself when I am browsing it, and I think such behavior should not exist.
How would you solve this problem?
Thanks for your answer.
I couldn’t find a way to connect an existing canvas to p5js drawings, but if your concern is the page shifting due to late loading of the library, you can specify a parent HTML element of the p5js canvas. Say, create an empty div
the same size as the p5js canvas first:
here is a simple example I made:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js"></script>
<style>
#container {
width: 400px;
height: 400px;
border: 1px solid green
}
</style>
</head>
<body>
<div id='container'></div>
<script>
let sketch = p => {
p.setup = () => {
p.createCanvas(400, 400)
p.background(220)
}
}
// simulate a delayed loading of the sketch
setTimeout(() => {
new p5(sketch, document.querySelector('#container'))
}, 2000)
</script>
</body>
</html>
Thank you, this works well. I like the delayed loading simulation part.
Previously I tried something similar for the container, but instead of using a fixed width and height, I tried width: 100%
and padding-bottom: 56.25%
, to create a container with ratio 16:9 filling its parent (and therefore automatic width and height). It worked for the container, but failed when the canvas was inserted (because the container grew).
I guess I’ll use fixed width and height as in your example, now that I know it works, but do you know why the following give a strange result? (e.g. the container grows after the canvas insertion):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js"></script>
<style>
#container {
width: 100%;
padding-bottom: 56.25%;
border: 1px solid green
}
</style>
</head>
<body>
<div id='container'></div>
<script>
let container = document.querySelector('#container')
let sketch = p => {
p.setup = () => {
p.createCanvas(container.clientWidth, container.clientHeight)
p.background(220)
}
}
// simulate a delayed loading of the sketch
setTimeout(() => {
new p5(sketch, container)
}, 2000)
</script>
</body>
</html>
Sorry I found the problem. I should remove the container padding before inserting.
container.style.paddingBottom = '0'
I shouldn’t copy paste code I don’t understand from the internet.
No worries.
The parent padding trick is an interesting one to use to keep the same aspect ratio,
and for this to work, it needs a few more lines of CSS.
I think this will solve the immediate issue of resizing the p5 canvas, but I also see some potential issues such as the canvas getting too large and heavy.
It might be better to keep the canvas size fixed to 16:9, say, 960x540 and just scale it up and down without increasing the pixel count.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js"></script>
<style>
#container {
width: 100%;
padding-bottom: 56.25%;
border: 1px solid green;
position: relative;
}
#container>canvas {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
</head>
<body>
<div id='container'></div>
<script>
let container = document.querySelector('#container')
let sketch = p => {
p.setup = () => {
p.createCanvas(container.clientWidth, container.clientHeight)
}
p.draw = () => {
p.background(220)
p.ellipse(p.width / 2, p.height / 2, 200, 200)
}
p.windowResized = () => {
p.resizeCanvas(container.clientWidth, container.clientHeight)
}
}
// simulate a delayed loading of the sketch
setTimeout(() => {
new p5(sketch, container)
}, 1000)
</script>
</body>
</html>
Ok I got it.
thank you very much.