Created
April 7, 2017 19:27
-
-
Save jmfirth/a7face42d237a0e226efc467c3c6cfc0 to your computer and use it in GitHub Desktop.
React and Pixi.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import Stage from './Stage'; | |
import DraggableSquare from './DraggableSquare'; | |
interface State { | |
x: number; | |
y: number; | |
width: number; | |
height: number; | |
color: number; | |
} | |
export default class App extends React.Component<null, State> { | |
state: State = { | |
x: 10, | |
y: 10, | |
width: 100, | |
height: 100, | |
color: 0x00FF00, | |
}; | |
rafHandle?: number; | |
square = new DraggableSquare({ | |
onMouseOver: () => this.setState({ color: 0xFF0000 }), | |
onMouseOut: () => this.setState({ color: 0x00FF00 }), | |
onDrag: (x, y) => this.setState({ x, y }), | |
}); | |
componentDidMount() { | |
this.update(0); | |
} | |
componentWillUnmount() { | |
if (this.rafHandle) { | |
cancelAnimationFrame(this.rafHandle); | |
} | |
} | |
update(tick: number) { | |
this.rafHandle = requestAnimationFrame(this.update.bind(this)); | |
} | |
render() { | |
const { x, y, width, color } = this.state; | |
return ( | |
<div className="App"> | |
<h1>Drag me!</h1> | |
<Stage | |
width={400} | |
height={400} | |
displayObjects={[ | |
this.square.draw(x, y, width, color) | |
]} | |
/> | |
</div> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"react/index.d.ts":"https://unpkg.com/@types/react/index.d.ts","react-dom/index.d.ts":"https://unpkg.com/@types/react-dom/index.d.ts","pixi.js/index.d.ts":"https://unpkg.com/@types/pixi.js/index.d.ts"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as PIXI from 'pixi.js'; | |
interface Position { | |
x: number; | |
y: number; | |
} | |
type DraggableSquareDragFn = (x: number, y: number) => void; | |
interface DraggableSquareOptions { | |
onMouseOver?: () => void; | |
onMouseOut?: () => void; | |
onDrag?: DraggableSquareDragFn; | |
} | |
export default class DraggableSquare { | |
graphics = new PIXI.Graphics; | |
x = 0; | |
y = 0; | |
onDrag?: DraggableSquareDragFn; | |
initialShapePosition: Position | null = null; | |
initialClickPosition: Position | null = null; | |
constructor({ onMouseOver, onMouseOut, onDrag }: DraggableSquareOptions = {}) { | |
this.onDrag = onDrag; | |
this.graphics.interactive = true; | |
if (onMouseOver) { this.graphics.on('mouseover', onMouseOver); } | |
if (onMouseOut) { this.graphics.on('mouseout', onMouseOut); } | |
if (onDrag) { | |
this.graphics.on('pointerdown', this.handlePointerDown.bind(this)); | |
this.graphics.on('pointerup', this.handlePointerUp.bind(this)); | |
this.graphics.on('pointermove', this.handlePointerMove.bind(this)); | |
} | |
} | |
handlePointerDown(e: PIXI.interaction.InteractionEvent) { | |
this.initialShapePosition = { x: this.x, y: this.y }; | |
this.initialClickPosition = { | |
x: (e.data.originalEvent as PointerEvent).clientX, | |
y: (e.data.originalEvent as PointerEvent).clientY | |
}; | |
} | |
handlePointerUp = () => { this.initialShapePosition = null; }; | |
handlePointerMove(e: PIXI.interaction.InteractionEvent) { | |
if (this.onDrag && this.initialShapePosition && this.initialClickPosition) { | |
const currentClickPosition = { | |
x: (e.data.originalEvent as PointerEvent).clientX, | |
y: (e.data.originalEvent as PointerEvent).clientY | |
}; | |
this.onDrag( | |
this.initialShapePosition.x + currentClickPosition.x - this.initialClickPosition.x, | |
this.initialShapePosition.y + currentClickPosition.y - this.initialClickPosition.y, | |
); | |
} | |
} | |
draw(x: number, y: number, size: number, color: number): PIXI.Graphics { | |
this.x = x; | |
this.y = y; | |
this.graphics.clear(); | |
this.graphics.beginFill(color); | |
this.graphics.drawRect(x, y, size, size); | |
this.graphics.endFill(); | |
return this.graphics; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="root" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import { render } from 'react-dom'; | |
import App from './App'; | |
render(<App />, document.getElementById('root')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"react":"15.4.2","react-dom":"15.4.2","pixi.js":"latest"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import * as PIXI from 'pixi.js'; | |
// import * as stageParser from './stageParser'; | |
interface Props { | |
width?: number | string; | |
height?: number | string; | |
renderer?: PIXI.WebGLRenderer | PIXI.CanvasRenderer; | |
stage?: PIXI.Container; | |
onCreated?: (renderer: PIXI.WebGLRenderer | PIXI.CanvasRenderer, stage: PIXI.Container) => void; | |
displayObjects?: PIXI.DisplayObject[]; | |
} | |
export default class Stage extends React.Component<Props, void> { | |
renderer: PIXI.WebGLRenderer | PIXI.CanvasRenderer; | |
stage: PIXI.Container; | |
container: HTMLDivElement; | |
componentDidMount() { | |
const { renderer, stage, onCreated } = this.props; | |
const { clientWidth: width, clientHeight: height } = this.container; | |
if (renderer) { | |
this.renderer = renderer; | |
} else { | |
this.renderer = PIXI.autoDetectRenderer(width, height); | |
this.renderer.clearBeforeRender = true; | |
this.renderer.autoResize = true; | |
} | |
this.container.appendChild(this.renderer.view); | |
this.stage = stage || new PIXI.Container(); | |
if (onCreated) { | |
onCreated(this.renderer, this.stage); | |
} | |
this.update(); | |
} | |
componentWillUnmount() { | |
this.renderer.destroy(); | |
} | |
componentWillReceiveProps(next: Props) { | |
if (next === this.props) { return; } | |
if (next.width !== this.props.width || next.height !== this.props.height) { | |
this.resize(); | |
} | |
this.update(); | |
} | |
resize() { | |
const { clientWidth: width, clientHeight: height } = this.container; | |
this.renderer.resize(width, height); | |
} | |
clear() { | |
this.stage.children.forEach(child => this.stage.removeChild(child)); | |
} | |
draw() { | |
const { displayObjects = [] } = this.props; | |
// this.clear(); | |
displayObjects.map(displayObject => this.stage.addChild(displayObject)); | |
} | |
update() { | |
this.draw(); | |
this.renderer.render(this.stage); | |
} | |
render() { | |
const { width, height } = this.props; | |
return ( | |
<div | |
style={{ width, height }} | |
ref={container => { this.container = container; }} | |
/> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
View this in the TypeScript Playground.