Skip to content

Latest commit

Β 

History

History
356 lines (257 loc) Β· 8.91 KB

README.md

File metadata and controls

356 lines (257 loc) Β· 8.91 KB

React PIXI 🌈

CircleCI

Write PIXI applications using React declarative style πŸ‘Œ

logo

Install

yarn add @inlet/react-pixi

or

npm install @inlet/react-pixi --save

Usage

With ReactDOM

import { Stage, Sprite } from '@inlet/react-pixi'

const App = () => (
  <Stage>
    <Sprite image="./bunny.png" x={100} y={100} />
  </Stage>
)

This example will render a PIXI.Sprite object into a Root Container of a PIXI.Application on the page. The Stage object will create a valid <canvas /> element to render to.

Without ReactDOM

import { render, Text } from '@inlet/react-pixi'
import { Application } from 'pixi.js'

// Setup PIXI app
const app = new Application({
  width: 800,
  height: 600,
  backgroundColor: 0x10bb99,
  view: document.getElementById('container'),
})

// Use the custom renderer to render a valid PIXI object into a PIXI container.
render(<Text text="Hello World" x={200} y={200} />, app.stage)

Examples

Watch the collection on codepen.

Custom Components

Currently the following Components are implemented by default:

You can easily add new components to your project:

./components/Rectangle.js

import { Graphics } from 'pixi.js'
import { PixiComponent } from '@inlet/react-pixi'

export default PixiComponent('Rectangle', {
  create: props => {
    return new Graphics()
  },
  didMount: (instance, parent) => {
    // apply custom logic on mount
  },
  willUnmount: (instance, parent) => {
    // clean up before removal
  },
  applyProps: (instance, oldProps, newProps) => {
    const { fill, x, y, width, height } = newProps
    instance.clear()
    instance.beginFill(fill)
    instance.drawRect(x, y, width, height)
    instance.endFill()
  },
})

With ES6:

./components/Rectangle.mjs

import { Graphics } from 'pixi.js'
import { registerComponent } from '@inlet/react-pixi'

export class Rectangle {
  constructor() {
    
  }
  
  create = (props) => {
    return new Graphics()
  }
  
  didMount = (instance, parent) => {
    // apply custom logic on mount
  }
  
  willUnmount = (instance, parent) => {
    // clean up before removal
  }
    
  applyProps = (instance, oldProps, newProps) => {
    const { fill, x, y, width, height } = newProps
    instance.clear()
    instance.beginFill(fill)
    instance.drawRect(x, y, width, height)
    instance.endFill()
  }
}

registerComponent('Rectangle', this)

App.js

import { Stage } from '@inlet/react-pixi'
import Rectangle from './components/Rectangle'

export default () => (
  <Stage>
    <Rectangle x={100} y={100} width={500} height={300} fill={0xff0000} />
  </Stage>
)

Props helper

ReactPixi comes with a handy utility method applyDefaultProps that can help you applying props directly to a PIXI primitive instance handling events, PIXI props and point-like values.

Here's an example to pass through every other DisplayObject props and handle prop count separately:

import { Text } from 'pixi.js'
import { Stage, applyDefaultProps, PixiComponent } from '@inlet/react-pixi'

export default PixiComponent('Counter', {
  create: ({ count }) => {
    return new Text(count.toString())
  },
  applyProps: (instance, oldProps, newProps) => {
    const { count, ...oldP } = oldProps
    const { count, ...newP } = newProps
    
    // apply rest props to PIXI.Text
    applyDefaultProps(instance, oldP, newP)
    
    // set new count
    instance.text = count.toString()
  }
});

Access the PIXI.Application in child components

Consider this rotating bunny example:

./components/RotatingBunny.jsx

import { Sprite } from '@inlet/react-pixi'

class RotatingBunny extends React.Component {
  state = { rotation: 0 }

  componentDidMount() {
    this.props.app.ticker.add(this.tick)
  }

  componentWillUnmount() {
    this.props.app.ticker.remove(this.tick)
  }

  tick = delta => {
    this.setState(({ rotation }) => ({
      rotation: rotation + 0.1 * delta,
    }))
  }

  render() {
    return <Sprite image="./bunny.png" rotation={this.state.rotation} />
  }
}

There are 2 ways of accessing the PIXI.Application instance.

  1. Using AppConsumer and pass the instance via render props:

App.jsx

import { Stage, Container, AppConsumer } from '@inlet/react-pixi'
import { RotatingBunny } from './components/RotatingBunny'

export default () => (
  <Stage>
    <Container>
      <AppConsumer>{app => <RotatingBunny app={app} />}</AppConsumer>
    </Container>
  </Stage>
)
  1. Or use a Higher Order Component:

App.jsx

import { Stage, Container, withPixiApp } from '@inlet/react-pixi'
import { RotatingBunny } from './components/RotatingBunny'

const BunnyWithApp = withPixiApp(RotatingBunny)

export default () => (
  <Stage>
    <Container>
      <BunnyWithApp />
    </Container>
  </Stage>
)
  1. Use hooks API in Functional Components

RotatingBunny.jsx

import { useApp } from '@inlet/react-pixi'

function RotatingBunny(props) {
  const app = useApp()
  // app => PIXI.Application

  return (
    ...
  )
}

API

<Stage />

Renders Root Container of a PIXI.Application.

Props:

  • width the width of the renderers view, default 800
  • height the height of the renderers view, default 600
  • onMount a callback function for the created app instance
  • onUnMount a callback function when the Stage gets unmounted
  • raf use the internal PIXI ticker (requestAnimationFrame) to render the stage, default true
  • renderOnComponentChange render stage when the Stage component updates. This is ignored if raf is true.
  • options see PIXI.Application options

The Stage stores the created PIXI.Application instance to context, which can be accessed using a Provider or a Higher Order Component.

Components

Pass component options as props, example:

import { Sprite } from '@inlet/react-pixi'

const MyComponent = () => <Sprite image=".image.png" x={100} y={200} />

The image prop here is a short-hand for PIXI.Sprite.from():

import { Sprite } from '@inlet/react-pixi'

const texture = new PIXI.Sprite.fromImage('./image.png')

const MyComponent = () => <Sprite texture={texture} x={100} y={200} />

Scripts

# compile umd & es builds
yarn build

# compile dev builds
yarn build:dev

# compile production builds
yarn build:prod

# watch development builds
yarn build:watch

# lint code
yarn eslint

# fix linting issues
yarn eslint --fix

# test
yarn test

# watch tests
yarn test:watch

Donate

If this project help you reduce time to develop, you can buy me a cup of coffee.

πŸ™ Thanks!

paypal