├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── LICENSE
├── README.md
├── bower.json
├── example
└── src
│ ├── .gitignore
│ ├── example.js
│ ├── example.less
│ └── index.html
├── gulpfile.js
├── package.json
└── src
├── ReactRegl.js
├── components
├── Rectangle.js
├── Surface.js
└── Triangle.js
└── renderers
└── triangle.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 | root = true
4 |
5 | [*]
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = false
9 | insert_final_newline = true
10 | indent_style = tab
11 |
12 | [*.json]
13 | indent_style = space
14 | indent_size = 2
15 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | .publish/*
2 | dist/*
3 | example/dist/*
4 | lib/*
5 | node_modules/*
6 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true,
5 | "node": true
6 | },
7 | "plugins": [
8 | "react"
9 | ],
10 | "rules": {
11 | "curly": [2, "multi-line"],
12 | "quotes": [2, "single", "avoid-escape"],
13 | "react/display-name": 0,
14 | "react/jsx-boolean-value": 1,
15 | "react/jsx-quotes": 1,
16 | "react/jsx-no-undef": 1,
17 | "react/jsx-sort-props": 0,
18 | "react/jsx-sort-prop-types": 1,
19 | "react/jsx-uses-react": 1,
20 | "react/jsx-uses-vars": 1,
21 | "react/no-did-mount-set-state": 1,
22 | "react/no-did-update-set-state": 1,
23 | "react/no-multi-comp": 1,
24 | "react/no-unknown-property": 1,
25 | "react/prop-types": 1,
26 | "react/react-in-jsx-scope": 1,
27 | "react/self-closing-comp": 1,
28 | "react/wrap-multilines": 1,
29 | "semi": 2,
30 | "strict": 0
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Coverage tools
11 | lib-cov
12 | coverage
13 | coverage.html
14 | .cover*
15 |
16 | # Dependency directory
17 | node_modules
18 |
19 | # Example build directory
20 | example/dist
21 | .publish
22 |
23 | # Editor and other tmp files
24 | *.swp
25 | *.un~
26 | *.iml
27 | *.ipr
28 | *.iws
29 | *.sublime-*
30 | .idea/
31 | *.DS_Store
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Matthew Conlen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Regl
2 |
3 | React bindings to [regl](https://github.com/mikolalysenko/regl)
4 |
5 | ## Demo & Examples
6 |
7 | Live demo: [mathisonian.github.io/react-regl](http://mathisonian.github.io/react-regl/)
8 |
9 | To build the examples locally, run:
10 |
11 | ```
12 | npm install
13 | npm start
14 | ```
15 |
16 | Then open [`localhost:8000`](http://localhost:8000) in a browser.
17 |
18 |
19 | ## Installation
20 |
21 | The easiest way to use react-regl is to install it from NPM and include it in your own React build process (using [Browserify](http://browserify.org), [Webpack](http://webpack.github.io/), etc).
22 |
23 | You can also use the standalone build by including `dist/react-regl.js` in your page. If you use this, make sure you have already included React, and it is available as a global variable.
24 |
25 | ```
26 | npm install react-regl --save
27 | ```
28 |
29 |
30 | ## Usage
31 |
32 | Example:
33 |
34 | ```js
35 | var React = require('react');
36 | var ReactDOM = require('react-dom');
37 | var { Surface, Triangle } = require('react-regl');
38 | var Victory = require('victory');
39 |
40 | var App = React.createClass({
41 |
42 | getInitialState () {
43 | return {
44 | x: 0
45 | }
46 | },
47 |
48 | toggleState () {
49 | this.setState({
50 | x: 2 * Math.PI - this.state.x
51 | })
52 | },
53 |
54 | componentDidMount () {
55 | this.toggleState();
56 | },
57 |
58 | render () {
59 | return (
60 |
61 |
62 | {
63 | (tweened) => {
64 | return (
65 |
66 |
69 |
70 | )
71 | }
72 | }
73 |
74 |
75 | );
76 | }
77 | });
78 |
79 | ReactDOM.render(, document.getElementById('app'));
80 | ```
81 |
82 | ### Properties
83 |
84 | * __DOCUMENT PROPERTIES HERE__
85 |
86 | ### Notes
87 |
88 | __ADDITIONAL USAGE NOTES__
89 |
90 |
91 | ## Development (`src`, `lib` and the build process)
92 |
93 | **NOTE:** The source code for the component is in `src`. A transpiled CommonJS version (generated with Babel) is available in `lib` for use with node.js, browserify and webpack. A UMD bundle is also built to `dist`, which can be included without the need for any build system.
94 |
95 | To build, watch and serve the examples (which will also watch the component source), run `npm start`. If you just want to watch changes to `src` and rebuild `lib`, run `npm run watch` (this is useful if you are working with `npm link`).
96 |
97 | ## License
98 |
99 | MIT
100 |
101 | Copyright (c) 2016 Matthew Conlen.
102 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-regl",
3 | "version": "0.0.0",
4 | "description": "React Regl",
5 | "main": "dist/react-regl.min.js",
6 | "homepage": "https://github.com/mathisonian/react-regl",
7 | "authors": [
8 | "Matthew Conlen"
9 | ],
10 | "moduleType": [
11 | "amd",
12 | "globals",
13 | "node"
14 | ],
15 | "keywords": [
16 | "react",
17 | "react-component"
18 | ],
19 | "license": "MIT",
20 | "ignore": [
21 | ".editorconfig",
22 | ".gitignore",
23 | "package.json",
24 | "src",
25 | "node_modules",
26 | "example",
27 | "test"
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/example/src/.gitignore:
--------------------------------------------------------------------------------
1 | ## This file is here to ensure it is included in the gh-pages branch,
2 | ## when `gulp deploy` is used to push updates to the demo site.
3 |
4 | # Dependency directory
5 | node_modules
6 |
--------------------------------------------------------------------------------
/example/src/example.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var ReactDOM = require('react-dom');
3 | var { Surface, Triangle, Rectangle } = require('react-regl');
4 | var Victory = require('victory');
5 |
6 | var App = React.createClass({
7 |
8 | getInitialState () {
9 | return {
10 | x: 0
11 | }
12 | },
13 |
14 | toggleState () {
15 | this.setState({
16 | x: 2 * Math.PI - this.state.x
17 | })
18 | },
19 |
20 | componentDidMount () {
21 | this.toggleState();
22 | setInterval(() => { this.toggleState(); }, 500);
23 | },
24 |
25 | render () {
26 |
27 | var points = [];
28 | for (var i = 0; i < 1000; i ++) {
29 | points.push({
30 | x: Math.random() * 2 - 1,
31 | y: Math.random() * 2 - 1
32 | });
33 | }
34 | return (
35 |
36 |
37 | {
38 | points.map((d, i) => {
39 | return (
40 |
41 | );
42 | })
43 | }
44 |
45 |
46 | );
47 | }
48 | });
49 |
50 | ReactDOM.render(, document.getElementById('app'));
51 |
--------------------------------------------------------------------------------
/example/src/example.less:
--------------------------------------------------------------------------------
1 | /*
2 | // Examples Stylesheet
3 | // -------------------
4 | */
5 |
6 | body {
7 | font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
8 | font-size: 14px;
9 | color: #333;
10 | margin: 0;
11 | padding: 0;
12 | }
13 |
14 | a {
15 | color: #08c;
16 | text-decoration: none;
17 | }
18 |
19 | a:hover {
20 | text-decoration: underline;
21 | }
22 |
23 | .container {
24 | margin-left: auto;
25 | margin-right: auto;
26 | max-width: 720px;
27 | padding: 1em;
28 | }
29 |
30 | .footer {
31 | margin-top: 50px;
32 | border-top: 1px solid #eee;
33 | padding: 20px 0;
34 | font-size: 12px;
35 | color: #999;
36 | }
37 |
38 | h1, h2, h3, h4, h5, h6 {
39 | color: #222;
40 | font-weight: 100;
41 | margin: 0.5em 0;
42 | }
43 |
44 | label {
45 | color: #999;
46 | display: inline-block;
47 | font-size: 0.85em;
48 | font-weight: bold;
49 | margin: 1em 0;
50 | text-transform: uppercase;
51 | }
52 |
53 | .hint {
54 | margin: 15px 0;
55 | font-style: italic;
56 | color: #999;
57 | }
58 |
--------------------------------------------------------------------------------
/example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Regl
4 |
5 |
6 |
7 |
8 |
React Regl
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var initGulpTasks = require('react-component-gulp-tasks');
3 |
4 | /**
5 | * Tasks are added by the react-component-gulp-tasks package
6 | *
7 | * See https://github.com/JedWatson/react-component-gulp-tasks
8 | * for documentation.
9 | *
10 | * You can also add your own additional gulp tasks if you like.
11 | */
12 |
13 | var taskConfig = {
14 |
15 | component: {
16 | name: 'ReactRegl',
17 | dependencies: [
18 | 'classnames',
19 | 'react',
20 | 'react-dom'
21 | ],
22 | lib: 'lib'
23 | },
24 |
25 | example: {
26 | src: 'example/src',
27 | dist: 'example/dist',
28 | files: [
29 | 'index.html',
30 | '.gitignore'
31 | ],
32 | scripts: [
33 | 'example.js'
34 | ],
35 | less: [
36 | 'example.less'
37 | ]
38 | }
39 |
40 | };
41 |
42 | initGulpTasks(gulp, taskConfig);
43 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-regl",
3 | "version": "1.0.0",
4 | "description": "React Regl",
5 | "main": "lib/ReactRegl.js",
6 | "author": "Matthew Conlen",
7 | "homepage": "https://github.com/mathisonian/react-regl",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/mathisonian/react-regl.git"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/mathisonian/react-regl/issues"
14 | },
15 | "dependencies": {
16 | "classnames": "^2.1.2",
17 | "react": "^15.0.2",
18 | "react-dom": "^15.0.2",
19 | "regl": "^0.4.0"
20 | },
21 | "devDependencies": {
22 | "babel-eslint": "^4.1.3",
23 | "eslint": "^1.6.0",
24 | "eslint-plugin-react": "^3.5.1",
25 | "gulp": "^3.9.0",
26 | "react-component-gulp-tasks": "^0.7.6",
27 | "victory": "^0.7.0"
28 | },
29 | "peerDependencies": {
30 | "react": "^0.14.0"
31 | },
32 | "browserify-shim": {
33 | "react": "global:React"
34 | },
35 | "scripts": {
36 | "build": "gulp clean && NODE_ENV=production gulp build",
37 | "examples": "gulp dev:server",
38 | "lint": "eslint ./; true",
39 | "publish:site": "NODE_ENV=production gulp publish:examples",
40 | "release": "NODE_ENV=production gulp release",
41 | "start": "gulp dev",
42 | "test": "echo \"no tests yet\" && exit 0",
43 | "watch": "gulp watch:lib"
44 | },
45 | "keywords": [
46 | "react",
47 | "react-component"
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/src/ReactRegl.js:
--------------------------------------------------------------------------------
1 | import Surface from './components/Surface';
2 | import Triangle from './components/Triangle';
3 | import Rectangle from './components/Rectangle';
4 |
5 | export { Surface, Triangle, Rectangle };
6 |
--------------------------------------------------------------------------------
/src/components/Rectangle.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | var Rectangle = React.createClass({
4 |
5 | getInitialState () {
6 | return {
7 |
8 | };
9 | },
10 |
11 | initialize(regl) {
12 | this.setState({
13 | regl: regl,
14 | renderer: this.props.getRenderer('triangle')
15 | });
16 | },
17 |
18 | componentDidMount () {
19 | var regl = this.props.getRegl();
20 | if (!regl) {
21 | return;
22 | }
23 |
24 | if (!this.state.renderer) {
25 | this.initialize(regl);
26 | }
27 |
28 | this.paint(this.state.renderer);
29 | },
30 |
31 | componentDidUpdate () {
32 | var regl = this.props.getRegl();
33 | if (!regl) {
34 | return;
35 | }
36 | if (!this.state.renderer) {
37 | this.initialize(regl);
38 | }
39 |
40 | this.paint(this.state.renderer);
41 | },
42 |
43 | paint (renderer) {
44 | if (!renderer) {
45 | return;
46 | }
47 |
48 | var x = this.props.x;
49 | var y = this.props.y;
50 | var width = this.props.width;
51 | var height = this.props.height;
52 |
53 | renderer(() => {
54 | var scopedRenderer = this.state.regl({
55 | uniforms: {
56 | color: this.props.color
57 | }
58 | });
59 |
60 | scopedRenderer(() => {
61 | var first = this.state.regl({
62 | attributes: {
63 | position: this.state.regl.buffer([[x, y], [x, y + height], [x + width, y + height]])
64 | },
65 | });
66 | var second = this.state.regl({
67 | attributes: {
68 | position: this.state.regl.buffer([[x, y], [x + width, y], [x + width, y + height]])
69 | },
70 | });
71 |
72 | first();
73 | second();
74 | });
75 | });
76 | },
77 |
78 | render () {
79 | return null;
80 | }
81 | });
82 |
83 | export default Rectangle;
84 |
--------------------------------------------------------------------------------
/src/components/Surface.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var TriangleRenderer = require('../renderers/triangle');
3 | var renderers = {
4 | triangle: TriangleRenderer
5 | };
6 |
7 | var Surface = React.createClass({
8 |
9 | getInitialState () {
10 | return {
11 | rendererCache: {}
12 | };
13 | },
14 |
15 | componentDidMount () {
16 | var regl = require('regl')(this.refs.canvas);
17 | this.setState({
18 | regl: regl
19 | });
20 | },
21 |
22 | getRenderer (name) {
23 | if (!this.state.regl) {
24 | return;
25 | }
26 |
27 | if (!this.state.rendererCache[name]) {
28 | this.state.rendererCache[name] = renderers[name](this.state.regl);
29 | }
30 |
31 | return this.state.rendererCache[name];
32 | },
33 |
34 | componentDidUpdate: function() {
35 | if (!this.state.regl) {
36 | return;
37 | }
38 |
39 | var children = Object.keys(this.refs).filter(k => k !== 'canvas').map(k => this.refs[k]);
40 | children.forEach((child) => {
41 | child.paint();
42 | });
43 | },
44 |
45 | getRegl () {
46 | return this.state.regl;
47 | },
48 |
49 | render () {
50 | var regl = this.refs.canvas;
51 | var children = React.Children.map(this.props.children, (child, i) => {
52 | return React.cloneElement(child, {
53 | getRegl: this.getRegl,
54 | getRenderer: this.getRenderer,
55 | ref: 'child' + i
56 | });
57 | }, this);
58 |
59 | return (
60 |
63 | );
64 | }
65 | });
66 |
67 | export default Surface;
68 |
--------------------------------------------------------------------------------
/src/components/Triangle.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | var Triangle = React.createClass({
4 |
5 | getInitialState () {
6 | return {
7 |
8 | };
9 | },
10 |
11 | initialize(regl) {
12 | this.setState({
13 | regl: regl,
14 | renderer: this.getRenderer(regl)
15 | });
16 | },
17 |
18 | componentDidMount () {
19 | var regl = this.props.getRegl();
20 | if (!regl) {
21 | return;
22 | }
23 |
24 | if (!this.state.renderer) {
25 | this.initialize(regl);
26 | }
27 |
28 | this.paint(this.state.renderer);
29 | },
30 |
31 | componentDidUpdate () {
32 | var regl = this.props.getRegl();
33 | if (!regl) {
34 | return;
35 | }
36 | if (!this.state.renderer) {
37 | this.initialize(regl);
38 | }
39 |
40 | this.paint(this.state.renderer);
41 | },
42 |
43 | getRenderer (regl) {
44 | return regl({
45 | frag: `
46 | precision mediump float;
47 | uniform vec4 color;
48 | void main () {
49 | gl_FragColor = color;
50 | }
51 | `,
52 | vert: `
53 | precision mediump float;
54 | attribute vec2 position;
55 | void main () {
56 | gl_Position = vec4(position.x, position.y, 0, 1);
57 | }
58 | `,
59 | count: 3
60 | });
61 | },
62 |
63 | paint (renderer) {
64 | if (!renderer) {
65 | return;
66 | }
67 |
68 | renderer(() => {
69 | var scopedRenderer = this.state.regl({
70 | attributes: {
71 | position: this.state.regl.buffer(this.props.position)
72 | },
73 | uniforms: {
74 | color: this.props.color
75 | }
76 | });
77 |
78 | scopedRenderer();
79 | });
80 | },
81 |
82 | render () {
83 | return null;
84 | }
85 | });
86 |
87 | export default Triangle;
88 |
--------------------------------------------------------------------------------
/src/renderers/triangle.js:
--------------------------------------------------------------------------------
1 | export default (regl) => {
2 | return regl({
3 | frag: `
4 | precision mediump float;
5 | uniform vec4 color;
6 | void main () {
7 | gl_FragColor = color;
8 | }
9 | `,
10 | vert: `
11 | precision mediump float;
12 | attribute vec2 position;
13 | void main () {
14 | gl_Position = vec4(position.x, position.y, 0, 1);
15 | }
16 | `,
17 | count: 3
18 | });
19 | };
20 |
--------------------------------------------------------------------------------