Phaser problem: loading images imported from files as base64 data - base64

I have trouble loading image(s) as Base64 data. In the following code (partially borrowed from here), the 'loading' function this.textures.addBase64 is used:
import bgSrc from '../assets/img/back.png';
...
create() {
this.numToLoad = 1;
this.textures.on('addtexture', () => {
console.log('another image loaded')
this.numToLoad--;
if (this.numToLoad < 1) this.createNext();
})
this.textures.addBase64('background', bgSrc);
...
}
createNext() {
//...use the images
}
However, the 'addtexture' event never fires. And the image, loaded this way, never loads, no matter how long I wait.
But everything goes fine if I use direct Base64 code, like const bgSrc = 'data:image/png;base64, blablablah' instead of import bgSrc from '../assets/img/back.png'. So the problem is in importing the image.
I use phaser 3 webpack in this project. plus url-loader. Maybe the url-loader is incorrectly set up? I am not sure if the url-loader is even needed for performing npm run start.

Well, it was indeed an incorrect setup of the url-loader. (I used one more plugin in the webpack, and they didn't work well together.)
So, the code above is OK after all.

Related

Crypto.randomUUID() not working with Next.js v13

The Environment
Next.js v13 (stable, no ./app folder) is running with Node v18 in Ubuntu WSL.
As per de docs , the Crypto API has been around since Node v14~ish.
This has been indeed tested in Node, in my environment:
Node 18 importing and running crypto.randomUUID()
I also printed the whole object and it looks as the docs says it should.
The Problem
Imagine this simple component:
import crypto from 'crypto';
export default function Crypto() {
console.log(crypto);
return (
<p>
{crypto.randomUUID()}
</p>
);
}
Next.js says it "compiled client and server successfully in 397 ms". But after the UUID renders in the browser for a couple of milliseconds, Next.js throws a couple of errors revolving around randomUUID not being a function.
Next Runtime Error with crypto.randomUUID()
I see that Webpack is somewhat mingling in there; haven't tried Turbopack. It's beyond the scope of this issue.
After commenting out the method invocation within the paragraph, the console.log(crypto) runs and prints twice, as usual, in the devtools as follows:
crypto method printed
Notice how one comes from "react devetools backend" and the other one from webkpack. That leads me to believe the error gets thrown server-side as the console.loglog is invoked before the UUID method.
Server-side, despite the errors thrown in the browser, the object gets printed by the Next CLI and it contains the method: Next CLI prints crypto object and randomUUID is listed
Client-side, within the printed object, the method randomUUID() is nowhere to be found:
Inside printed crypto object in devtools
This confirms the error message. My code is not getting access to the method. Also, a couple of methods are missing, when compared to the Node docs.
And yet if one console.log(crypto) directly from the devTools, it has indeed the method within its prototype:
randomUUID directly from devtools
Furthermore, because of the structure, I'm inclined to believe the crypto object being printed is somehow coming from Node, as the structure of the Chrome V8 crypto object is completely different. But why in the hell are those methods missing?
I tried console.loging the object server-side, client-side, and in-between. Somehow the method gets lost in-between. Webpack might be the culprit. Worst of all, albeit being for the blink of an eye, I can see the string rendered before the errors get thrown; and dismissing the error cards throws a blank body. The string disappears.
EDIT
The reason one imports/requires crypto is so it can run in Node. Next is a SSR framework; in a nutshell it is intended to run first on the server, get rendered and delivered as HTML as much as it can to the client. If not imported, Node throws an error when Next tries to invoke Crypto server-side.
Now then, I tell that piece of code to only run if the Window object is available (i.e. I'm in the Browser) and it runs with the native chromium V8 Crypto object.
// import crypto from 'crypto';
export default function Crypto() {
if (typeof window !== 'undefined') {
console.log('CLIENT: ', crypto.randomUUID());
return (
<p>
{crypto.randomUUID()}
</p>
);
}
return (
<h1>SERVER SIDE</h1>
);
}
The only downside is that is somehow still runs twice bc of Next magic, once server side and one client-side, which means it's not bc of React 18. It tells me accurately that which is to be expected as an UUID function always returns a different result.
Browsers restrict access to some crypto APIs when not running in a secure context (as defined here).
Set it to state in a useEffect hook when page initially loads so it persist and then render it from state.
const Crypto = () => {
const [randomUUID, setRandomUUID] = useState();
useEffect((
if (typeof window !== 'undefined' && !randomUUID) {
setRandomUUID(crypto.randomUUID());
}
),[]);
if(!randomUUID) <>No UUID</>;
return <>{randomUUID}</>
}
export default Crypto;

Retrieve file contents during Gatsby build

I need to pull in the contents of a program source file for display in a page generated by Gatsby. I've got everything wired up to the point where I should be able to call
// my-fancy-template.tsx
import { readFileSync } from "fs";
// ...
const fileContents = readFileSync("./my/relative/file/path.cs");
However, on running either gatsby develop or gatsby build, I'm getting the following error
This dependency was not found:
⠀
* fs in ./src/templates/my-fancy-template.tsx
⠀
To install it, you can run: npm install --save fs
However, all the documentation would suggest that this module is native to Node unless it is being run on the browser. I'm not overly familiar with Node yet, but given that gatsby build also fails (this command does not even start a local server), I'd be a little surprised if this was the problem.
I even tried this from a new test site (gatsby new test) to the same effect.
I found this in the sidebar and gave that a shot, but it appears it just declared that fs was available; it didn't actually provide fs.
It then struck me that while Gatsby creates the pages at build-time, it may not render those pages until they're needed. This may be a faulty assessment, but it ultimately led to the solution I needed:
You'll need to add the file contents to a field on File (assuming you're using gatsby-source-filesystem) during exports.onCreateNode in gatsby-node.js. You can do this via the usual means:
if (node.internal.type === `File`) {
fs.readFile(node.absolutePath, undefined, (_err, buf) => {
createNodeField({ node, name: `contents`, value: buf.toString()});
});
}
You can then access this field in your query inside my-fancy-template.tsx:
{
allFile {
nodes {
fields { content }
}
}
}
From there, you're free to use fields.content inside each element of allFile.nodes. (This of course also applies to file query methods.)
Naturally, I'd be ecstatic if someone has a more elegant solution :-)

Convert <img src="phone.png"> to Base64 <img src="data:img/png;base64,...."> by compiling the app, to make the image load instantly with the app

This is a unique question: I don't want to use browser javascript to solve this, please read on...
I want to convert <img src="..."> to Base64 img tag by compiling the app (ng build or ng serve), to make the image load instantly - without further downloads other than the app itself, but also to make the image dynamicly changable while developing the app.
For example, here's a component - home.component.html:
code before compiling (notice the base64 directive, its just an idea though):
<img src="assets/images/phone.png" base64>
code wanted after compiling:
<img src="data:image/png;base64,iVBORw0......rest-of-base-64-goes-here">
Important: This should happen without running a front-end javascript operation by the user, or by calling the image file. (by means, the file phone.png will not even exist when compiling)
I still want to edit the local image phone.png while developing.
I know I can convert the file to base64 manually and update it in my component, but that's exactly what I don't want to do - I want it to happen automatically to save time.
That means the image will sit in the component itself, in one of the .js files that has been compiled, and therefore will load instantly with the app.
Idea: It would be nice and easy to have a directive that would take care of that.
something like <img src="phone.png base64>**
I assume it can be done using node/webpack in some way, but I have not idea how.
You need to use readAsDataUrl()
function getBase64(event) {
let me = this;
let file = event.target.files[0];
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
//me.modelvalue = reader.result;
console.log(reader.result);
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
Hope can help you..

Load images from local directory in Fabric

I am trying to load images from a local folder using fabric.js in node.
There seems to be very little up to date documentation on how to do this.
Most example use fabric.Image.fromURL(imageurl)
As far as I'm aware, this only works for web urls, not local paths.
Correct me if I'm wrong, but I have tried
fabric.Image.fromURL(imgpath, (img) => {
...
}
which throws the error Coul not load img: /image/path/img.jpg
Where
fs.readFile(imagepath, (err, i) => {
...
})
will successfully read the file, i will be a buffer.
What is the correct way to load a local image.
I know there is a fabric.Image.fromObject but I have no idea what type of object it wants.
I am currently loading the image into a 2d canvas object, converting it with canvas.toDataURL() and putting that url into fabric.Image.fromURL() which works but converting the image to a url is very slow due to large images. There must be a way to load the image directly and avoid this problem.
If you are using fabricjs 3+, that uses the new jsdom, you can use the file urls!
fabric.Image.fromURL(file://${__dirname}${filepath});
Check here on the fabricJS codebase how they handle reading files in browser and node for the visual test images
https://github.com/fabricjs/fabric.js/blob/master/test/lib/visualTestLoop.js#L139
try this one:
fabric.Image.fromURL(require("../../assets/mockup/100.png"), (img) => {...}

Running a js file with node is giving me an "HTMLDivElement" is not defined. Do i need to import it, or is that specific to browsers outside of Node?

I was trying to run some tests, but needed test data, so i created a generation file which created dummy html. When I attempt to run it though, it gives me a Reference Error: HTMLDivElement is not defined.
Is there something I need to import such that Node knows what HTMLDivElement is? I am not rendering anything, but just want correct data to pipe into follow on code.
I run my file through TSC, and then run it through node.
Sample Code:
const main = () => {
let root = new HTMLDivElement();
}
main();
Edit:
I was trying to just bypass it with: let root = document.createElement("div"); but node does not understand what document is, so I cant seem to get that running either as a fallback.
Indeed, Node.js doesn't come with a DOM implementation. If you want to run tests that use the DOM, you'll need to either load a Node.js-compatible DOM implementation such as jsdom, or if that doesn't meet your requirements, switch to a browser-based testing environment such as Selenium.

Resources