From 17517b9f1995fb26776c5ca9c5b8b6d2c1d3819c Mon Sep 17 00:00:00 2001 From: Alexander Kachkaev Date: Tue, 6 Sep 2016 15:59:31 +0100 Subject: [PATCH] Refactor ExampleBrowser - navigate between examples with react-router (each example has got a slug) - extract ExampleViewer into a separate component, determine its size using react-sizeme - make ExampleBrowser component functional (i.e. pure) --- assets/index.html | 1 + package.json | 2 + src/examples/ExampleBrowser.js | 111 +++++++++------------------------ src/examples/ExampleViewer.js | 37 +++++++++++ src/index.js | 8 ++- 5 files changed, 77 insertions(+), 82 deletions(-) create mode 100644 src/examples/ExampleViewer.js diff --git a/assets/index.html b/assets/index.html index ee7f7c8..bbcb609 100644 --- a/assets/index.html +++ b/assets/index.html @@ -61,6 +61,7 @@ #panel #content .link { color: #2194CE; + display: block; text-decoration: none; cursor: pointer; } diff --git a/package.json b/package.json index 9513e3e..506ee9c 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "cannon": "^0.6.2", "react": "~15.3.1", "react-dom": "^15.3.1", + "react-router": "^3.0.0-alpha.3", + "react-sizeme": "^2.1.3", "react-three-renderer": "2.3.1", "stats.js": "^1.0.0", "three": "0.79.0" diff --git a/src/examples/ExampleBrowser.js b/src/examples/ExampleBrowser.js index 1ad3134..6ba3ab8 100644 --- a/src/examples/ExampleBrowser.js +++ b/src/examples/ExampleBrowser.js @@ -1,4 +1,6 @@ import React from 'react'; +import { Link } from 'react-router'; +import ExampleViewer from './ExampleViewer'; import SimpleExample from './Simple/index'; import ManualRenderingExample from './ManualRendering/index'; @@ -17,41 +19,49 @@ const examples = [ name: 'Simple', component: SimpleExample, url: 'Simple/index', + slug: 'webgl_simple', }, { name: 'Cloth', component: ClothExample, url: 'AnimationCloth/index', + slug: 'webgl_cloth', }, { name: 'Camera', component: CameraExample, url: 'WebGLCameraExample/index', + slug: 'webgl_camera', }, { name: 'Geometries', component: GeometriesExample, url: 'Geometries/index', + slug: 'webgl_geometries', }, { name: 'Geometry Shapes', component: GeometryShapesExample, url: 'GeometryShapes/index', + slug: 'webgl_geometry_shapes', }, { name: 'Draggable Cubes', component: DraggableCubes, url: 'DraggableCubes/index', + slug: 'webgl_draggable_cubes', }, { name: 'Physics', component: Physics, url: 'Physics/index', + slug: 'webgl_physics', }, { name: 'Physics - MousePick', component: PhysicsMousePick, url: 'Physics/mousePick', + slug: 'webgl_physics_mousepick', }, { separator: true, @@ -66,6 +76,7 @@ const examples = [ name: 'Manual rendering', component: ManualRenderingExample, url: 'ManualRendering/index', + slug: 'advanced_manual_rendering', }, { separator: true, @@ -75,74 +86,20 @@ const examples = [ name: 'RotatingCubes - Through React', component: BenchmarkRotatingCubes, url: 'Benchmark/RotatingCubes', + slug: 'benchmarks_rotating_cubes_react', }, { name: 'RotatingCubes - Direct Updates', component: RotatingCubesDirectUpdates, url: 'Benchmark/RotatingCubesDirectUpdates', + slug: 'benchmarks_rotating_cubes_direct', }, ]; -class ExampleBrowser extends React.Component { - constructor(props, context) { - super(props, context); - - this.state = { - activeExample: null, - viewerWidth: 0, - viewerHeight: 0, - }; - } - - componentDidMount() { - window.addEventListener('resize', this._onWindowResize, false); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._onWindowResize, false); - } - - _onWindowResize = () => { - const viewer = this.refs.viewer; - - this.setState({ - viewerWidth: viewer.offsetWidth, - viewerHeight: viewer.offsetHeight, - }); - }; - - render() { - let exampleContent = null; - - const { - viewerWidth, - viewerHeight, - } = this.state; - - let sourceButton = null; - - if (this.state.activeExample !== null) { - const { - component: ExampleComponent, - url, - } = examples[this.state.activeExample]; - - exampleContent = (); - - sourceButton = (); - } - - return (
+const ExampleBrowser = ({ params }) => { + const activeExample = params.slug && examples.find(example => example.slug === params.slug); + return ( +

react-three-renderer / examples

@@ -159,33 +116,25 @@ class ExampleBrowser extends React.Component {
); } - const onLinkClick = () => { - const viewer = this.refs.viewer; - - this.setState({ - viewerWidth: viewer.offsetWidth, - viewerHeight: viewer.offsetHeight, - activeExample: index, - }); - }; - - return (
{example.name} -
); + ); })}
-
- {exampleContent} - {sourceButton} -
- ); - } -} + + + ); +}; + +ExampleBrowser.propTypes = { + params: React.PropTypes.object.isRequired, +}; export default ExampleBrowser; diff --git a/src/examples/ExampleViewer.js b/src/examples/ExampleViewer.js new file mode 100644 index 0000000..2ddd014 --- /dev/null +++ b/src/examples/ExampleViewer.js @@ -0,0 +1,37 @@ +import React from 'react'; +import sizeMe from 'react-sizeme'; + +const ExampleViewer = ({ example, size }) => { + let sourceButton = null; + let exampleContent = null; + + if (example) { + const { + component: ExampleComponent, + url, + } = example; + exampleContent = (); + sourceButton = (); + } + + return ( +
+ {exampleContent} + {sourceButton} +
+ ); +}; + +ExampleViewer.propTypes = { + example: React.PropTypes.object, + size: React.PropTypes.object, +}; + +export default sizeMe({ monitorHeight: true, refreshRate: 200 })(ExampleViewer); diff --git a/src/index.js b/src/index.js index 2b74ff8..5fb2ce3 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,14 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { Router, Route, hashHistory } from 'react-router'; import ExampleBrowser from './examples/ExampleBrowser'; import Perf from 'react-addons-perf'; window.Perf = Perf; -ReactDOM.render(, document.getElementById('content')); +ReactDOM.render( + + + , + document.getElementById('content') +);