davidfig / pixi-viewport

A highly configurable viewport/2D camera designed to work with pixi.js
https://davidfig.github.io/pixi-viewport/
MIT License
1.04k stars 174 forks source link

"clicked" event failed to be triggered #482

Open HanYuanHsu opened 5 months ago

HanYuanHsu commented 5 months ago

I was trying to implement the effect that when I click on the viewport, a circle will be drawn at the position I clicked. See the viewport.on('clicked', ... part below:

import * as PIXI from 'pixi.js'
import { Viewport } from 'pixi-viewport'
import {useRef, useEffect} from 'react'
import { Graphics, PixiComponent } from '@pixi/react'

export default function RawViewport() {
    const pixiContainer = useRef(null)

    useEffect(() => {
        const app = new PIXI.Application({
            backgroundColor: 0xeef1f5
        })
        pixiContainer.current.appendChild(app.view)

        const viewport = new Viewport({
            screenWidth: window.innerWidth,
            screenHeight: window.innerHeight,
            worldWidth: 1000,
            worldHeight: 1000,

            events: app.renderer.events, // the interaction module is important for wheel to work properly when renderer.view is placed or scaled
            //interaction: app.renderer.plugins.interaction,
        })

        // add the viewport to the stage
        app.stage.addChild(viewport)

        // activate plugins
        viewport
            .drag()
            .pinch()
            .wheel()

        // only activate viewport when ctrl key is pressed and held
        viewport.pause = true;

        const enableViewport = (e) => {
            if (e.ctrlKey) {
                viewport.pause = false;
            }
        }
        const disableViewport = (e) => {
            viewport.pause = true;
        }
        window.addEventListener('keydown', enableViewport)
        window.addEventListener('keyup', disableViewport)

        viewport.on('clicked', (event) => {
            console.log('Viewport was clicked', e.screen, e.world);
            const circle = new PIXI.Graphics();
            circle.beginFill('black');
            circle.drawCircle(event.world.x, event.world.y, 10);
            circle.endFill();
            viewport.addChild(circle);
        });

        // cleanup function when this RawViewport component is unmounted
        return () => {
            pixiContainer.current.removeChild(app.view)
            // Destroy the PIXI application
            app.destroy(true, { children: true, texture: true, baseTexture: true })

            window.removeEventListener('keydown', enableViewport)
            window.removeEventListener('keyup', disableViewport)
        }
    }, []) // Empty dependency array means this effect runs only once.
           // Of course, we only want mounting to be done once.

    return <div ref={pixiContainer}></div>
}

However, it does not work. I believe the event callback is never called because the console doesn't even log message. But if I change the part to

viewport.addEventListener('click', addDot)
const addDot = (e) => {
    if (!viewport.pause) return

    //console.log('Viewport was clicked', e.screen, e.world);

    const dot = new PIXI.Graphics()
    dot.beginFill('black')
    dot.drawCircle(e.data.global.x, e.global.y, 10)
    dot.endFill()

    viewport.addChild(dot)
}

then the circles will be shown successfully, even though the positions are not relative to the viewport (after I drag the viewport, the position will be off).