p5.js
p5.js copied to clipboard
preloading with loadFont does not work in instance mode
Hi there!
Most appropriate sub-area of p5.js?
- [x] Build tools and processes
- [x] Core/Environment/Rendering
- [x] DOM
Details about the bug:
- p5.js version: 1.3.1
- Web browser and version: Any
- Operating System: MacOS 11.3
- Steps to reproduce this:
Loading a font in instance mode the "preload" is not consistently called and executed before the setup. Only reloading the browser (without hard refresh) the fonts load.
WIth: Separate html with container, loading library and sketch.js included at foot of html:
This DOES NOT work. The sketch will run before the font has loaded.
var s = function(p) {
var font = null;
p.preload = function () {
console.log("preload")
font = p.loadFont('assets/fonts/test.ttf')
}
p.setup = function() {
console.log("setup", font)
}
}
new p5(s);
This will print to console:
- setup null
- preload
This DOES work, but uses "global" mode. The sketch will preload the font, then run.
new p5();
var font = null;
function preload() {
console.log("preload")
font = loadFont('assets/fonts/test.ttf')
}
function setup() {
console.log("setup", font)
}
This will print to console:
- setup null (not sure why this gets called once?)
- preload
- setup Object { parent: {…}, cache: {}, font: {…} }
Is there something one needs to take into account when trying to get preload to work with instance mode?
Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.
I was not able to recreate this either in the editor, or after downloading the sketch and running it from the local filesystem (see my test here). Can you list the exact steps to recreate?
I can't reproduce either - also note that manually calling new p5(); will instantiate p5.js twice so I don't think it's a good idea (and that's why you get the setup message twice)
I think calling the p5() was in the tutorial to make "global mode" happen "after the fact". This is really a weird issue. I've tried @dhowe 's code and that works standalone, and imo I've reduced my code those bits, but there still no consistent pointer what's going wrong. I'm investigating some more and report back.
Okay, I've managed to reduce it to a reproducible case for Mac OS 11.3 Firefox 88.0.1 — and this is ... ethereal.
With this in sketch.js and that font file existing (and the png existing):
var s = function(p) {
var font;
p.preload = function() {
console.log('preload', typeof font);
font = p.loadFont('Resagokr.otf');
console.log('preload.done', typeof font);
};
p.setup = function() {
console.log('setup', typeof font);
p.createCanvas(400, 400);
};
p.draw = function() {
console.log('draw', typeof font);
p.background(255);
p.textFont(font, 100);
p.text('hello', 100,200);
p.noLoop();
};
};
new p5(s);
This will work:
<!doctype html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/addons/p5.sound.min.js"></script>
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
And this will fail with a Uncaught Error: null font passed to textFont when hard refreshing (cmd + shift + r):
<!doctype html>
<html lang="en">
<head>
<style type="text/css">
body {
background: url("some.png");
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/addons/p5.sound.min.js"></script>
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
The CSS does not need to be inline; including a CSS with a url resource seems to be enough to throw off the preload requirement detection — p5 just goes ahead and runs the setup, only to run (I think) the preload sequence "late" after the url resource/CSS has fully loaded.
If I change the content of sketch.js from the "instance" mode to "global" notation like so:
var font;
function preload () {
console.log('preload', typeof font);
font = loadFont('AbrilFatface-Regular.otf');
console.log('preload.done', typeof font);
};
function setup () {
console.log('setup', typeof font);
createCanvas(400, 400);
};
function draw () {
console.log('draw', typeof font);
background(255);
textFont(font, 100);
text('foo', 100, 200);
noLoop();
};
… the url in the CSS don't seem to matter and I get no more errors.
So in effect, using "instance mode" with any CSS that loads resources will break the preload (of fonts, at least).
@dhowe @micuat can either of you reproduce this?
Please review the tags after trying to reproduce.
@kontur could you set up the example which causes the error on p5.js web editor so others can test it easily?
I was having similar issues while trying to load in images and I found that calling new p5() with window.onload got preload to work.
var p5sk;
window.onload = () => {
p5sk = new p5(s);
};
Hi, I have the same issue.
I tried the code by @dhowe (https://editor.p5js.org/rednoyz/sketches/EjxQSJyVj) and I get this error:
index.html:1 Access to XMLHttpRequest at 'file:///home/cocconat/Documents/web/debris/vodkalaterra/sunny.otf' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, brave, chrome-untrusted, https.
I verified that the font is actually in the directory by clicking on the link and downloading it.
This is the full log:
preload undefined
main.js:89 preload.done object
index.html:1 Access to XMLHttpRequest at 'file:///home/cocconat/Documents/web/debris/vodkalaterra/sunny.otf' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, brave, chrome-untrusted, https.
p5.min.js:3 Font could not be loaded sunny.otf
(anonymous) @ p5.min.js:3
(anonymous) @ p5.min.js:3
Dr.r.onerror @ p5.min.js:3
error (async)
Dr @ p5.min.js:3
M.load @ p5.min.js:3
f.default.loadFont @ p5.min.js:3
(anonymous) @ p5.min.js:3
p.preload @ main.js:88
_start @ p5.min.js:3
load (async)
_ @ p5.min.js:3
(anonymous) @ main.js:106
p5.min.js:3 GET file:///home/cocconat/Documents/web/debris/vodkalaterra/sunny.otf net::ERR_FAILED
@aquaresima Loading external files including fonts will require running a server. Loading files will not work locally over the file:// protocol usually seen when running the html file directly instead of through a server. You can read more here.
Thanks, I was reading indeed! Let's say that I can put this on the web-server that I use to share my content online. When I refer to point to that link
I get this other error:
'Access-Control-Allow-Origin' header
WTH?
If your sketch and the web server hosting the resource is not on the same domain, the server hosting the resource will need to include the 'Access-Control-Allow-Origin' header with the right value in order for any other site to use the resource. It is generally called CORS headers. More here.
If you are trying to develop a sketch locally, you should prefer using local servers as per the link I shared in the previous comment. If you are trying to share the sketch online on your own website, you will need to either host everything from the same domain or be able to modify how your server serves the resources (by adding the 'Access-Control-Allow-Origin' header).