Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.11 warning : Local data URIs are not supported: #3897

Closed
libertyAlone opened this issue Aug 7, 2018 · 12 comments
Closed

v3.11 warning : Local data URIs are not supported: #3897

libertyAlone opened this issue Aug 7, 2018 · 12 comments

Comments

@libertyAlone
Copy link

libertyAlone commented Aug 7, 2018

I use webpack & url-loader to handle png, like this:

import img from '../assets/cokecan.png'
...
preload() {
    this.load.image('cokecan', img)
}
create() {
    this.add.text(100, 100, 'hello phaser', { fill: '#0f0' })
    this.add.image(100, 200, 'cokecan')
}

the img variable is a base64 string, but it renders nothing and in console has a warning Local data URIs are not supported: cokecan,phaser version is 3.11.0, what should I do?

@photonstorm
Copy link
Collaborator

<preach>

Don't use base64 assets? It's a really bad idea for games and brings absolutely zero benefits to the table. Games are not websites. Don't package them or treat them in the same way.

</preach>

Solution: There will be no support for base64 assets loaded via the Loader, for the reason stated above, however you can add them directly into the Texture Manager:

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: {
        create: create
    }
};

var game = new Phaser.Game(config);

var imageData = 'data:image/png;base64,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';

function create ()
{
    this.textures.once('addtexture', function () {

        this.add.image(400, 300, 'brain');

    }, this);

    this.textures.addBase64('brain', imageData);
}

You'll have to wait for every single texture added in this way to dispatch an 'addtexture' event before you can use it with a Game Object.

In short, don't use base64.

@shubhamseth2527
Copy link

shubhamseth2527 commented Aug 22, 2018

#3966 . @photonstorm
In this issue what is addtexture and where the brain(key) is defined and where brain . please check my code once

var config = {
type: Phaser.AUTO,
width: 640 ,
height: 960,
scene: {
preload: preload,
create: create,
update: update,
}

};
var game = new Phaser.Game(config);

var imageData = 'data:image/png;base64, anyBASE64IMAGEKEY';
/** Preload function **/
function preload() {
// Preload
this.load.image("bg", "assets/images/gamelayerbackground.png"); // BACKGROUND GAME IMAGE
};

/** Create Function **/
function create() {
this.textures.once('addtexture', function () {

    this.add.image(400, 300, 'bg');

}, this);

this.textures.addBase64('bg', imageData);  

}

function update() {

}

@alvarotuso
Copy link

@photonstorm sorry for the throwback, but could you please elaborate on why it's a bad idea for small images? I stumbled upon this issue because I was embedding a game in a react app (and the react default script uses webpack, which is automatically configured to url encode small images)
I was able to disable that behavior but I'm wondering why it's a valid optimization for websites but not for games

@photonstorm
Copy link
Collaborator

It's not really a very sensible optimization for websites either. The moment you base64 a file, several things happen:

  1. The total size is now larger than the original binary file. The size gain is, roughly, around 1.4 times the original file size.

  2. The browser now has to base64 decode the URI data into a binary format. Once in this format, it can then decode the image data. This is an extra step and more work for the CPU. It's not excessive, as browsers are used to doing this kind of thing, but it's not free.

  3. One of the benefits of base64ing for web sites is the reduction in http requests, but with http/2 being common-place this is a null benefit. http/2 can send multiple requests in parallel over a single tcp connection. It's fast. Very fast.

  4. It's nice to offer a load progress bar for your games, which you can't accurately do if the image data is embedded into the source files already.

I'm aware this is a common practice for web sites, but games aren't web sites and shouldn't be treated in the same way.

@alvarotuso
Copy link

Thanks for the details!

@MichaelJCole
Copy link

I've been spending hours trying to work around this bug to use phaser as a library in another webpack project.

It's ironic that an HTML game framework can't work with the most common HTML tooling - webpack.

Here are some workarounds

@calebfrancis5991
Copy link

I ran into an issue including phaser 3 into my react app. By default, the webpack config was loading in small images differently that were not compatible with phaser. To solve this in a react app, you can override the webpack config environment variable react uses by setting the variable as shown below in your react .env file. By default, the react webpack config has it at 10,000.

IMAGE_INLINE_SIZE_LIMIT=1

@steveja42
Copy link

@photonstorm
What about the case where the app is generating images on the fly? That is what I'm doing.

@photonstorm
Copy link
Collaborator

@steveja42
Copy link

Yes, that is what I am using but it was more involved- had to create a promise and a listener and await the promise to make sure the textures are loaded.

@benrosen
Copy link

benrosen commented Mar 7, 2022

Here is an asynchronous function to load base64 image data in Phaser. I am using it successfully alongside the create-react-app TypeScript template.

⚠️ Please read this comment before considering the following approach!

import { Scene, Textures } from "phaser";

const loadBase64Image = (props: {
  data: any;
  key: string;
  scene: Scene;
}) => {
  return new Promise<void>((resolve) => {
    props.scene.textures.once(Textures.Events.ADD, () => {
      resolve();
    });
    props.scene.textures.addBase64(props.key, props.data);
  });
};

You can use it like so:

import tileset from "./tileset.png";

new Game({
  scene: {
    create: async function (this: Scene) {
      await loadBase64Image({
        data: tileset,
        key: "tileset",
        scene: this,
      });
      this.add.image("tileset");
    },
  },
});

This example assumes that you have a file called tileset.png colocated with your TypeScript file in your project's src directory.

@chris35469
Copy link

If you are using react, adding the function below to handle image loading addressed this issue for me.

loadImage:function(id, img) {
        return img.split(":")[0] == "data" ? this.textures.addBase64(id, img) :  this.load.image(id, img);
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants