Dragging with PIXI + react + ts does not work properly when the cursor moves quickly

76 views Asked by At

I want to make a drag and drop like it is was done here

Main code:

import {FC} from 'react'
import styles from './DrawPage.module.scss'
import {Stage} from "@pixi/react";
import Block from "./bench/Block";

const DrawPage: FC = () => {
    return (
        <div className={styles.draw} id='canvas'>
            <Stage options={{backgroundColor: 0xf8f8f8}} width={parent.innerWidth} height={parent.innerHeight}>
                <Block/>
            </Stage>
        </div>
    )
}

export default DrawPage

Block code:

import {useRef, useState} from "react";
import {Sprite} from "@pixi/react";
import * as PIXI from "pixi.js";
import '@pixi/events'

const Block = () => {

    const isDragging = useRef(false);
    const offset = useRef({x: 0, y: 0});
    const [position, setPosition] = useState({x: 100, y: 100})
    const [alpha, setAlpha] = useState(1);

    const onStart = (e) => {
        isDragging.current = true;
        offset.current = {
            x: e.data.global.x - position.x,
            y: e.data.global.y - position.y
        };
        setAlpha(0.5);
    }

    const onEnd = (e) => {
        isDragging.current = false;
        setAlpha(1);
    }

    const onMove = (e) => {
        console.log("move")
        if (isDragging.current) {
            setPosition({
                x: e.data.global.x - offset.current.x,
                y: e.data.global.y - offset.current.y,
            })
        }
    }

    return (
        <Sprite
            eventMode={"dynamic"}
            position={position}
            pointerdown={onStart}
            pointerup={onEnd}
            pointerupoutside={onEnd}
            pointermove={onMove}
            //globalpointermove={onMove}
            globalmousemove={onMove}
            alpha={alpha}
            texture={PIXI.Texture.WHITE}
            tint={0x00ff00}
            width={200}
            height={200}
        />
    )
}

export default Block

package.json

"dependencies": {
    "@pixi/events": "^7.3.3",
    "@pixi/react": "^7.1.1",
    "classnames": "^2.5.1",
    "pixi.js": "^7.3.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.49.3",
    "react-router-dom": "^6.21.2",
    "yarn": "^1.22.21"
  }

It works when the cursor moves slowly but pointermove stops calling onMove function outside the block. pointerup event works properly. In the example I added console.log to the onMove function and saw logs regardless of where the cursor moved. I tried to change event mode without result. globalpointermove from the documentation also doesn’t work. How to fix this issue?

Probably I should change eventFeatures.globalMove to true but I don't know the default value and how to do it

1

There are 1 answers

1
Steellemm On

I have come up with this solution but it looks very dirty

import {useCallback, useRef, useState} from "react";
import {Container, PixiComponent} from "@pixi/react";
import {Graphics} from "pixi.js";

interface RectangleProps {
    x: number;
    y: number;
}

const Block = (props: RectangleProps) => {

    const isDragging = useRef(false);
    const offset = useRef({x: 0, y: 0});
    const [position, setPosition] = useState({x: props.x, y: props.y})
    const [alpha, setAlpha] = useState(1);

    const onStart = (e) => {
        isDragging.current = true;
        offset.current = {
            x: e.data.global.x - position.x,
            y: e.data.global.y - position.y
        };
        setAlpha(0.5);
    }

    const onEnd = (e) => {
        isDragging.current = false;
        setAlpha(1);
    }

    const onMove = (e) => {
        if (isDragging.current) {
            setPosition({
                x: e.data.global.x - offset.current.x,
                y: e.data.global.y - offset.current.y,
            })
        }
    }

    const Rectangle = PixiComponent<any, Graphics>('Rectangle', {
        create: () => new Graphics(),
        applyProps: (ins: Graphics, _) => {
            ins.beginFill(0xffffff)
            ins.lineStyle(1, '0xAFAFAF')
            ins.drawRoundedRect(0, 0, 150, 150, 10)
            ins.endFill()
            ins.eventMode = "static"
            ins.on("globalpointermove", onMove)
        },
    })


    return (
        <Container
            eventMode={"static"}
            position={position}
            pointerdown={onStart}
            pointerup={onEnd}
            pointerupoutside={onEnd}
            alpha={alpha}
        >
            <Rectangle/>
        </Container>
    )
}

export default Block