Jump to content

[Sprite]Typescript Sprite.On Event Error


Teckniel
 Share

Recommended Posts

Hello,

I got allot further in my goal to make a ribbon like menubar.
But for some reason i had a error saying Sprite.On do not exist, so i had to edit the tsconfig file and add the line:  "allowSyntheticDefaultImports"true, to the compiler options
so after adding that i was able to use that methode.

But here comes the problem:
When i hit the Sprite Button -> it go's to the required function and print's in the console the message i provided,  
                                                   But when i want to acces the container from the UIMananger within the onButtonClick -> this.uiContainer i get error saying it's undifiend

Anyone have a clue how to fix this?

 

UI Manager Snippit (See: onButtonClick )

export class UiManager {
    private demoScene: Boolean = false;
    private uiContainer: Container = new Container;
    constructor(demo:Boolean) {
        this.demoScene = demo;
        this.uiContainer = this.GenerateMenuBar();
    }

    public getUI(): Container{
        return this.uiContainer;  //Return the ui Correctly
    }
  
   private onButtonClick() :void {
        console.log("clickt on button");
        let btnTest = this.createMenuButton(); // <<-- Error: this.createMenuButton is not a function
        console.log(this.uiContainer); // <<-- Error: Undefined this.uiContainer
        //Launch a event to show a sprite...
    }

    private GenerateMenuBar(): Container{
        this.uiContainer.addChild(
            this.createMenuBackground(),
            this.createMenuButton(),
            this.createWallsnWindow(),
        );
        return this.uiContainer;
    }
    private createMenuButton():Sprite{
        console.log("Create MenuButton")
        var tmpSrite = Sprite.from('./src/Engine/assets/ui/btn_NewScematic.png');
        tmpSrite.interactive = true;
        tmpSrite.buttonMode = true;
        tmpSrite.name = "menuButton";
        tmpSrite.position.x = 10; tmpSrite.y = 59;
        tmpSrite.hitArea = new Polygon([40,0, 100,0, 100,40,40,40]); //Setup Hitbox
        tmpSrite.on('pointertap', this.onButtonClick); //Interaction...
        return tmpSrite;
    }

   

 

Engine File -> Everything in here renders ok and uses the UIManager

export class Engine {
    public renderer: Renderer;
    public loader: Loader;
    public world: Container;
    public graphics: Graphics;
    public fpsMax: number;
    public canvas: HTMLElement;
    public uiManager: UiManager;
    private assetsLoaded:boolean;
    //
    // constructor
    constructor(options: IEngineOptions) {
        this.loader = Loader.shared;
        this.renderer = new Renderer(options);
        this.world = new Container();
        this.graphics = new Graphics();
        this.fpsMax = options.fpsMax;
        /// * UI Manager *
        this.uiManager = new UiManager(true);
        this.canvas = options.containerId ? document.getElementById(options.containerId) || document.body : document.body;
        this.canvas.appendChild(this.renderer.view);
        ///
        /// Loader Setup
        ///
        this.loader.onComplete.add(() =>  {
            this.assetsLoaded = true;
            console.log("Assets Loader State:" + this.assetsLoaded);
        })
        this.loader.load();
        this.render();

    }

    get view(): HTMLCanvasElement {
        return this.renderer.view;
    }
    
    public render(){
        while (this.assetsLoaded = false)
            return;        
        console.log(utils.TextureCache);
        let tmpWorld = new Container();
        this.world.addChild(
            this.uiManager.getUI(), <<-- Render Fine and returns the Ui Container
        );
    }
    
    
} // Engine

 

Edited by Teckniel
typo
Link to comment
Share on other sites

The scope of the event handler function is incorrect. You can either bind the function to be in the scope of the class or use an arrow function to get the same effect.

So doing the callback like:
 

   private onButtonClick = () :void => {
        console.log("clickt on button");
        let btnTest = this.createMenuButton(); // <<-- Error: this.createMenuButton is not a function
        console.log(this.uiContainer); // <<-- Error: Undefined this.uiContainer
        //Launch a event to show a sprite...
    }

    

Would fix it.

Link to comment
Share on other sites

2 hours ago, Exca said:

The scope of the event handler function is incorrect. You can either bind the function to be in the scope of the class or use an arrow function to get the same effect.

So doing the callback like:
 



   private onButtonClick = () :void => {
        console.log("clickt on button");
        let btnTest = this.createMenuButton(); // <<-- Error: this.createMenuButton is not a function
        console.log(this.uiContainer); // <<-- Error: Undefined this.uiContainer
        //Launch a event to show a sprite...
    }

    

Would fix it.

Thanks that fixed it. Now i use the arrow function to assign it to the local methode. // = () : void =>
What is the other option you describe.

Pretty new to javascript and pixi.
I'm primarly a .Net Developer gitting into typescript,but javascript is pain in the ass ;0

Thanks to provide a fix tho!

Edited by Teckniel
typo
Link to comment
Share on other sites

In javascript the scope of the function depends on how it's executed. For example if you have a class and you call it by myClass.foobar() then that is executed in the scope of the class. But if would do something like var func = myClass.foobar; func(); it would execute outside of the classes scope.

Basically same thing happens when the event handler is run as you pass the info about the function only and not the scope.

Old way of doing this was that you would do something like this:

var that = this;
function handler( ){
  that.foobar();
}
window.addEventListener("something", handler);

  More modern solution that came to be was to bind the function you give as parameter:

class Foo
{
  constructor(){
    window.addEventListener("something", this.handler.bind(this));
  }

  function handler {
    this.doSomething()
  }

}

And if you had to remove the listener at some point then first binding and assigning that to a variable and then passing that variable to listener would be way to go.

With typescript I use nowadays purely arrow functions when there's scoping involved. Though they also have their drawbacks.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...