├── .gitignore
├── README.md
├── build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── precache-manifest.183c1118394b3870f418b9fee0b2a94e.js
├── robots.txt
├── service-worker.js
└── static
│ └── js
│ ├── 2.8e76e459.chunk.js
│ ├── 2.8e76e459.chunk.js.map
│ ├── main.620dc5e7.chunk.js
│ ├── main.620dc5e7.chunk.js.map
│ ├── runtime-main.d1b2ac6a.js
│ └── runtime-main.d1b2ac6a.js.map
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── src
├── App.js
├── App.test.js
├── ReactTHREE.js
└── index.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 |
13 | # misc
14 | .DS_Store
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [Demo](https://liyuanqiu.github.io/react-reconciler-three/build/)
2 |
3 | ```javascript
4 | import React from "react";
5 | import ReactTHREE from "./ReactTHREE";
6 | import App from "./App";
7 |
8 | ReactTHREE.render(, document.getElementById("root"));
9 | ```
10 |
11 | `ReactTHREE` is a custom renderer for `react`.
12 |
--------------------------------------------------------------------------------
/build/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {
3 | "main.js": "/react-reconciler-three/build/static/js/main.620dc5e7.chunk.js",
4 | "main.js.map": "/react-reconciler-three/build/static/js/main.620dc5e7.chunk.js.map",
5 | "runtime-main.js": "/react-reconciler-three/build/static/js/runtime-main.d1b2ac6a.js",
6 | "runtime-main.js.map": "/react-reconciler-three/build/static/js/runtime-main.d1b2ac6a.js.map",
7 | "static/js/2.8e76e459.chunk.js": "/react-reconciler-three/build/static/js/2.8e76e459.chunk.js",
8 | "static/js/2.8e76e459.chunk.js.map": "/react-reconciler-three/build/static/js/2.8e76e459.chunk.js.map",
9 | "index.html": "/react-reconciler-three/build/index.html",
10 | "precache-manifest.183c1118394b3870f418b9fee0b2a94e.js": "/react-reconciler-three/build/precache-manifest.183c1118394b3870f418b9fee0b2a94e.js",
11 | "service-worker.js": "/react-reconciler-three/build/service-worker.js"
12 | },
13 | "entrypoints": [
14 | "static/js/runtime-main.d1b2ac6a.js",
15 | "static/js/2.8e76e459.chunk.js",
16 | "static/js/main.620dc5e7.chunk.js"
17 | ]
18 | }
--------------------------------------------------------------------------------
/build/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyuanqiu/react-reconciler-three/c66eb9081e3f727e3258692c588380fc835d1848/build/favicon.ico
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
React App
--------------------------------------------------------------------------------
/build/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyuanqiu/react-reconciler-three/c66eb9081e3f727e3258692c588380fc835d1848/build/logo192.png
--------------------------------------------------------------------------------
/build/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyuanqiu/react-reconciler-three/c66eb9081e3f727e3258692c588380fc835d1848/build/logo512.png
--------------------------------------------------------------------------------
/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/build/precache-manifest.183c1118394b3870f418b9fee0b2a94e.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = (self.__precacheManifest || []).concat([
2 | {
3 | "revision": "05efa540c18ca603272747a4707be343",
4 | "url": "/react-reconciler-three/build/index.html"
5 | },
6 | {
7 | "revision": "08054b8f8e2a42a5e7c8",
8 | "url": "/react-reconciler-three/build/static/js/2.8e76e459.chunk.js"
9 | },
10 | {
11 | "revision": "86819e16e57e26d8bab9",
12 | "url": "/react-reconciler-three/build/static/js/main.620dc5e7.chunk.js"
13 | },
14 | {
15 | "revision": "38c9fbe17ac6cc581614",
16 | "url": "/react-reconciler-three/build/static/js/runtime-main.d1b2ac6a.js"
17 | }
18 | ]);
--------------------------------------------------------------------------------
/build/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/build/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
15 |
16 | importScripts(
17 | "/react-reconciler-three/build/precache-manifest.183c1118394b3870f418b9fee0b2a94e.js"
18 | );
19 |
20 | self.addEventListener('message', (event) => {
21 | if (event.data && event.data.type === 'SKIP_WAITING') {
22 | self.skipWaiting();
23 | }
24 | });
25 |
26 | workbox.core.clientsClaim();
27 |
28 | /**
29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
30 | * requests for URLs in the manifest.
31 | * See https://goo.gl/S9QRab
32 | */
33 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
35 |
36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/react-reconciler-three/build/index.html"), {
37 |
38 | blacklist: [/^\/_/,/\/[^\/?]+\.[^\/]+$/],
39 | });
40 |
--------------------------------------------------------------------------------
/build/static/js/main.620dc5e7.chunk.js:
--------------------------------------------------------------------------------
1 | (this["webpackJsonpreact-three"]=this["webpackJsonpreact-three"]||[]).push([[0],{10:function(e,t,n){"use strict";n.r(t);var r=n(0),a=n.n(r),i=n(3),o=n.n(i),c=n(1),s={createInstance:!0,appendChildToContainer:!0,appendChild:!0,appendInitialChild:!0,removeChildFromContainer:!0,removeChild:!0,insertInContainerBefore:!0,insertBefore:!0,prepareUpdate:!1,commitUpdate:!1};function l(e,t){!0===s[e]&&(console.log("*** ".concat(e," ***")),console.log(t))}var d=o()({supportsMutation:!0,createInstance:function(e,t,n,r,a){switch(l("createInstance",arguments),e){case"threeBoxGeometry":var i=t.width,o=t.height,s=t.depth;return new c.a(i,o,s);case"threeMeshBasicMaterial":var d=t.parameters;return new c.c(d);case"threeMesh":var h=t.rotation,u=h.x,p=h.y,m=new c.b;return void 0!==u&&(m.rotation.x=u),void 0!==p&&(m.rotation.y=p),m;case"threeScene":return new c.e;case"threePerspectiveCamera":var f=t.fov,C=t.aspect,v=t.near,x=t.far,y=t.position,w=y.x,b=y.y,B=y.z,I=new c.d(f,C,v,x);return void 0!==w&&(I.position.x=w),void 0!==b&&(I.position.y=b),void 0!==B&&(I.position.z=B),I;case"threeWebGLRenderer":var M=t.width,g=t.height,E=t.antialias,G=new c.f({antialias:E});return G.setSize(M,g),{renderer:G,scene:null,camera:null};default:return null}},createTextInstance:function(e,t,n,r){return null},appendChildToContainer:function(e,t){l("appendChildToContainer",arguments),e.appendChild(t.renderer.domElement)},appendChild:function(e,t){l("appendChild",arguments)},appendInitialChild:function(e,t){if(l("appendInitialChild",arguments),e.renderer instanceof c.f){switch(t.type){case"Scene":e.scene=t;break;case"PerspectiveCamera":e.camera=t}null!==e.scene&&null!==e.camera&&e.renderer.render(e.scene,e.camera)}switch(e.type){case"Mesh":switch(t.type){case"BoxGeometry":e.geometry=t;break;case"MeshBasicMaterial":e.material=t}break;case"Scene":e.add(t)}},removeChildFromContainer:function(e,t){l("removeChildFromContainer",arguments),e.removeChild(t.renderer.domElement)},removeChild:function(e,t){l("removeChild",arguments)},insertInContainerBefore:function(e,t,n){l("insertInContainerBefore",arguments)},insertBefore:function(e,t,n){l("insertBefore",arguments)},prepareUpdate:function(e,t,n,r,a,i){switch(l("prepareUpdate",arguments),t){case"threeWebGLRenderer":return!0;case"threeMesh":var o=n.rotation,c=o.x,s=o.y,d=r.rotation,h=d.x,u=d.y;if(c!==h||s!==u)return{rotation:r.rotation}}},commitUpdate:function(e,t,n,r,a,i){switch(l("commitUpdate",arguments),n){case"threeWebGLRenderer":if(!0===t){var o=e.renderer,c=e.scene,s=e.camera;null!==c&&null!==s&&o.render(c,s)}break;case"threeMesh":if(void 0!==t.rotation){var d=t.rotation,h=d.x,u=d.y;void 0!==h&&(e.rotation.x=h),void 0!==u&&(e.rotation.y=u)}}},finalizeInitialChildren:function(){},getChildHostContext:function(){},getPublicInstance:function(){},getRootHostContext:function(){},prepareForCommit:function(){},resetAfterCommit:function(){},shouldSetTextContent:function(){return!1}}),h=function(e,t){var n=d.createContainer(t,!1,!1);d.updateContainer(e,n,null,null)},u=n(4),p=300,m=300;var f=function(){var e=Object(r.useState)({x:0,y:0}),t=Object(u.a)(e,2),n=t[0],i=t[1];return Object(r.useEffect)((function(){var e=-1;return function t(){e=requestAnimationFrame(t),i((function(e){return{x:e.x+.01,y:e.y+.01}}))}(),function(){cancelAnimationFrame(e)}}),[]),a.a.createElement("threeWebGLRenderer",{width:p,height:m,antialias:!0},a.a.createElement("threeScene",null,a.a.createElement("threeMesh",{rotation:n},a.a.createElement("threeBoxGeometry",{width:1,height:1,depth:1}),a.a.createElement("threeMeshBasicMaterial",{parameters:{color:65280}}))),a.a.createElement("threePerspectiveCamera",{fov:75,aspect:p/m,near:.1,far:1e3,position:{z:5}}))};h(a.a.createElement(f,null),document.getElementById("root"))},5:function(e,t,n){e.exports=n(10)}},[[5,1,2]]]);
2 | //# sourceMappingURL=main.620dc5e7.chunk.js.map
--------------------------------------------------------------------------------
/build/static/js/main.620dc5e7.chunk.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["ReactTHREE.js","App.js","index.js"],"names":["logConfig","createInstance","appendChildToContainer","appendChild","appendInitialChild","removeChildFromContainer","removeChild","insertInContainerBefore","insertBefore","prepareUpdate","commitUpdate","log","type","args","console","reconciler","ReactReconciler","supportsMutation","props","rootContainerInstance","hostContext","internalInstanceHandle","arguments","width","height","depth","BoxGeometry","parameters","MeshBasicMaterial","rotation","x","y","mesh","Mesh","undefined","Scene","fov","aspect","near","far","position","z","camera","PerspectiveCamera","antialias","renderer","WebGLRenderer","setSize","scene","createTextInstance","text","container","child","domElement","parent","render","geometry","material","add","before","instance","oldProps","newProps","currentHostContext","ox","oy","nx","ny","updatePayload","finishedWork","finalizeInitialChildren","getChildHostContext","getPublicInstance","getRootHostContext","prepareForCommit","resetAfterCommit","shouldSetTextContent","whatToRender","div","createContainer","updateContainer","App","useState","setRotation","useEffect","id","animate","requestAnimationFrame","prev","cancelAnimationFrame","color","ReactTHREE","document","getElementById"],"mappings":"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","file":"static/js/main.620dc5e7.chunk.js","sourcesContent":["import ReactReconciler from \"react-reconciler\";\nimport {\n BoxGeometry,\n MeshBasicMaterial,\n Mesh,\n Scene,\n PerspectiveCamera,\n WebGLRenderer\n} from \"three\";\n\nconst logConfig = {\n createInstance: true,\n appendChildToContainer: true,\n appendChild: true,\n appendInitialChild: true,\n removeChildFromContainer: true,\n removeChild: true,\n insertInContainerBefore: true,\n insertBefore: true,\n prepareUpdate: false,\n commitUpdate: false\n};\n\nfunction log(type, args) {\n if (logConfig[type] === true) {\n console.log(`*** ${type} ***`);\n console.log(args);\n }\n}\n\nlet reconciler = ReactReconciler({\n /* configuration for how to talk to the host environment */\n /* aka \"host config\" */\n\n supportsMutation: true,\n\n createInstance(\n type,\n props,\n rootContainerInstance,\n hostContext,\n internalInstanceHandle\n ) {\n log(\"createInstance\", arguments);\n switch (type) {\n case \"threeBoxGeometry\": {\n const { width, height, depth } = props;\n return new BoxGeometry(width, height, depth);\n }\n case \"threeMeshBasicMaterial\": {\n const { parameters } = props;\n return new MeshBasicMaterial(parameters);\n }\n case \"threeMesh\": {\n const {\n rotation: { x, y }\n } = props;\n const mesh = new Mesh();\n if (x !== undefined) {\n mesh.rotation.x = x;\n }\n if (y !== undefined) {\n mesh.rotation.y = y;\n }\n return mesh;\n }\n case \"threeScene\": {\n return new Scene();\n }\n case \"threePerspectiveCamera\": {\n const {\n fov,\n aspect,\n near,\n far,\n position: { x, y, z }\n } = props;\n const camera = new PerspectiveCamera(fov, aspect, near, far);\n if (x !== undefined) {\n camera.position.x = x;\n }\n if (y !== undefined) {\n camera.position.y = y;\n }\n if (z !== undefined) {\n camera.position.z = z;\n }\n return camera;\n }\n case \"threeWebGLRenderer\": {\n const { width, height, antialias } = props;\n const renderer = new WebGLRenderer({\n antialias\n });\n renderer.setSize(width, height);\n return {\n renderer,\n scene: null,\n camera: null\n };\n }\n default:\n return null;\n }\n },\n createTextInstance(\n text,\n rootContainerInstance,\n hostContext,\n internalInstanceHandle\n ) {\n return null;\n },\n\n appendChildToContainer(container, child) {\n log(\"appendChildToContainer\", arguments);\n container.appendChild(child.renderer.domElement);\n },\n appendChild(parent, child) {\n log(\"appendChild\", arguments);\n },\n appendInitialChild(parent, child) {\n log(\"appendInitialChild\", arguments);\n if (parent.renderer instanceof WebGLRenderer) {\n switch (child.type) {\n case \"Scene\":\n parent.scene = child;\n break;\n case \"PerspectiveCamera\":\n parent.camera = child;\n break;\n default:\n }\n if (parent.scene !== null && parent.camera !== null) {\n parent.renderer.render(parent.scene, parent.camera);\n }\n }\n switch (parent.type) {\n case \"Mesh\": {\n switch (child.type) {\n case \"BoxGeometry\":\n parent.geometry = child;\n break;\n case \"MeshBasicMaterial\":\n parent.material = child;\n break;\n default:\n }\n break;\n }\n case \"Scene\": {\n parent.add(child);\n break;\n }\n default:\n }\n },\n\n removeChildFromContainer(container, child) {\n log(\"removeChildFromContainer\", arguments);\n container.removeChild(child.renderer.domElement);\n },\n removeChild(parent, child) {\n log(\"removeChild\", arguments);\n },\n insertInContainerBefore(container, child, before) {\n log(\"insertInContainerBefore\", arguments);\n },\n insertBefore(parent, child, before) {\n log(\"insertBefore\", arguments);\n },\n\n prepareUpdate(\n instance,\n type,\n oldProps,\n newProps,\n rootContainerInstance,\n currentHostContext\n ) {\n log(\"prepareUpdate\", arguments);\n switch (type) {\n case \"threeWebGLRenderer\": {\n return true;\n }\n case \"threeMesh\":\n const {\n rotation: { x: ox, y: oy }\n } = oldProps;\n const {\n rotation: { x: nx, y: ny }\n } = newProps;\n if (ox !== nx || oy !== ny) {\n return {\n rotation: newProps.rotation\n };\n }\n break;\n default:\n }\n },\n commitUpdate(\n instance,\n updatePayload,\n type,\n oldProps,\n newProps,\n finishedWork\n ) {\n log(\"commitUpdate\", arguments);\n switch (type) {\n case \"threeWebGLRenderer\": {\n if (updatePayload === true) {\n const { renderer, scene, camera } = instance;\n if (scene !== null && camera !== null) {\n renderer.render(scene, camera);\n }\n }\n break;\n }\n case \"threeMesh\":\n if (updatePayload.rotation !== undefined) {\n const {\n rotation: { x, y }\n } = updatePayload;\n if (x !== undefined) {\n instance.rotation.x = x;\n }\n if (y !== undefined) {\n instance.rotation.y = y;\n }\n }\n break;\n default:\n }\n },\n\n finalizeInitialChildren() {},\n getChildHostContext() {},\n getPublicInstance() {},\n getRootHostContext() {},\n prepareForCommit() {},\n resetAfterCommit() {},\n shouldSetTextContent() {\n return false;\n }\n});\n\nexport default {\n render(whatToRender, div) {\n let container = reconciler.createContainer(div, false, false);\n reconciler.updateContainer(whatToRender, container, null, null);\n }\n};\n","/* eslint react/jsx-no-undef:0 */\nimport React, { useState, useEffect } from \"react\";\n\nconst width = 300;\nconst height = 300;\n\nfunction App() {\n const [rotation, setRotation] = useState({\n x: 0,\n y: 0\n });\n useEffect(() => {\n let id = -1;\n function animate() {\n id = requestAnimationFrame(animate);\n setRotation(prev => ({\n x: prev.x + 0.01,\n y: prev.y + 0.01\n }));\n }\n animate();\n return () => {\n cancelAnimationFrame(id);\n };\n }, []);\n return (\n \n \n \n \n \n \n \n \n \n );\n}\n\nexport default App;\n","import React from \"react\";\nimport ReactTHREE from \"./ReactTHREE\";\nimport App from \"./App\";\n\nReactTHREE.render(, document.getElementById(\"root\"));\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/build/static/js/runtime-main.d1b2ac6a.js:
--------------------------------------------------------------------------------
1 | !function(e){function r(r){for(var n,l,a=r[0],c=r[1],i=r[2],p=0,s=[];p0.2%",
26 | "not dead",
27 | "not op_mini all"
28 | ],
29 | "development": [
30 | "last 1 chrome version",
31 | "last 1 firefox version",
32 | "last 1 safari version"
33 | ]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyuanqiu/react-reconciler-three/c66eb9081e3f727e3258692c588380fc835d1848/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyuanqiu/react-reconciler-three/c66eb9081e3f727e3258692c588380fc835d1848/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liyuanqiu/react-reconciler-three/c66eb9081e3f727e3258692c588380fc835d1848/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | /* eslint react/jsx-no-undef:0 */
2 | import React, { useState, useEffect } from "react";
3 |
4 | const width = 300;
5 | const height = 300;
6 |
7 | function App() {
8 | const [rotation, setRotation] = useState({
9 | x: 0,
10 | y: 0
11 | });
12 | useEffect(() => {
13 | let id = -1;
14 | function animate() {
15 | id = requestAnimationFrame(animate);
16 | setRotation(prev => ({
17 | x: prev.x + 0.01,
18 | y: prev.y + 0.01
19 | }));
20 | }
21 | animate();
22 | return () => {
23 | cancelAnimationFrame(id);
24 | };
25 | }, []);
26 | return (
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
47 |
48 | );
49 | }
50 |
51 | export default App;
52 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactTHREE from "./ReactTHREE";
3 | import App from "./App";
4 |
5 | it("renders without crashing", () => {
6 | const div = document.createElement("div");
7 | ReactTHREE.render(, div);
8 | ReactTHREE.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/src/ReactTHREE.js:
--------------------------------------------------------------------------------
1 | import ReactReconciler from "react-reconciler";
2 | import {
3 | BoxGeometry,
4 | MeshBasicMaterial,
5 | Mesh,
6 | Scene,
7 | PerspectiveCamera,
8 | WebGLRenderer
9 | } from "three";
10 |
11 | const logConfig = {
12 | createInstance: true,
13 | appendChildToContainer: true,
14 | appendChild: true,
15 | appendInitialChild: true,
16 | removeChildFromContainer: true,
17 | removeChild: true,
18 | insertInContainerBefore: true,
19 | insertBefore: true,
20 | prepareUpdate: false,
21 | commitUpdate: false
22 | };
23 |
24 | function log(type, args) {
25 | if (logConfig[type] === true) {
26 | console.log(`*** ${type} ***`);
27 | console.log(args);
28 | }
29 | }
30 |
31 | let reconciler = ReactReconciler({
32 | /* configuration for how to talk to the host environment */
33 | /* aka "host config" */
34 |
35 | supportsMutation: true,
36 |
37 | createInstance(
38 | type,
39 | props,
40 | rootContainerInstance,
41 | hostContext,
42 | internalInstanceHandle
43 | ) {
44 | log("createInstance", arguments);
45 | switch (type) {
46 | case "threeBoxGeometry": {
47 | const { width, height, depth } = props;
48 | return new BoxGeometry(width, height, depth);
49 | }
50 | case "threeMeshBasicMaterial": {
51 | const { parameters } = props;
52 | return new MeshBasicMaterial(parameters);
53 | }
54 | case "threeMesh": {
55 | const {
56 | rotation: { x, y }
57 | } = props;
58 | const mesh = new Mesh();
59 | if (x !== undefined) {
60 | mesh.rotation.x = x;
61 | }
62 | if (y !== undefined) {
63 | mesh.rotation.y = y;
64 | }
65 | return mesh;
66 | }
67 | case "threeScene": {
68 | return new Scene();
69 | }
70 | case "threePerspectiveCamera": {
71 | const {
72 | fov,
73 | aspect,
74 | near,
75 | far,
76 | position: { x, y, z }
77 | } = props;
78 | const camera = new PerspectiveCamera(fov, aspect, near, far);
79 | if (x !== undefined) {
80 | camera.position.x = x;
81 | }
82 | if (y !== undefined) {
83 | camera.position.y = y;
84 | }
85 | if (z !== undefined) {
86 | camera.position.z = z;
87 | }
88 | return camera;
89 | }
90 | case "threeWebGLRenderer": {
91 | const { width, height, antialias } = props;
92 | const renderer = new WebGLRenderer({
93 | antialias
94 | });
95 | renderer.setSize(width, height);
96 | return {
97 | renderer,
98 | scene: null,
99 | camera: null
100 | };
101 | }
102 | default:
103 | return null;
104 | }
105 | },
106 | createTextInstance(
107 | text,
108 | rootContainerInstance,
109 | hostContext,
110 | internalInstanceHandle
111 | ) {
112 | return null;
113 | },
114 |
115 | appendChildToContainer(container, child) {
116 | log("appendChildToContainer", arguments);
117 | container.appendChild(child.renderer.domElement);
118 | },
119 | appendChild(parent, child) {
120 | log("appendChild", arguments);
121 | },
122 | appendInitialChild(parent, child) {
123 | log("appendInitialChild", arguments);
124 | if (parent.renderer instanceof WebGLRenderer) {
125 | switch (child.type) {
126 | case "Scene":
127 | parent.scene = child;
128 | break;
129 | case "PerspectiveCamera":
130 | parent.camera = child;
131 | break;
132 | default:
133 | }
134 | if (parent.scene !== null && parent.camera !== null) {
135 | parent.renderer.render(parent.scene, parent.camera);
136 | }
137 | }
138 | switch (parent.type) {
139 | case "Mesh": {
140 | switch (child.type) {
141 | case "BoxGeometry":
142 | parent.geometry = child;
143 | break;
144 | case "MeshBasicMaterial":
145 | parent.material = child;
146 | break;
147 | default:
148 | }
149 | break;
150 | }
151 | case "Scene": {
152 | parent.add(child);
153 | break;
154 | }
155 | default:
156 | }
157 | },
158 |
159 | removeChildFromContainer(container, child) {
160 | log("removeChildFromContainer", arguments);
161 | container.removeChild(child.renderer.domElement);
162 | },
163 | removeChild(parent, child) {
164 | log("removeChild", arguments);
165 | },
166 | insertInContainerBefore(container, child, before) {
167 | log("insertInContainerBefore", arguments);
168 | },
169 | insertBefore(parent, child, before) {
170 | log("insertBefore", arguments);
171 | },
172 |
173 | prepareUpdate(
174 | instance,
175 | type,
176 | oldProps,
177 | newProps,
178 | rootContainerInstance,
179 | currentHostContext
180 | ) {
181 | log("prepareUpdate", arguments);
182 | switch (type) {
183 | case "threeWebGLRenderer": {
184 | return true;
185 | }
186 | case "threeMesh":
187 | const {
188 | rotation: { x: ox, y: oy }
189 | } = oldProps;
190 | const {
191 | rotation: { x: nx, y: ny }
192 | } = newProps;
193 | if (ox !== nx || oy !== ny) {
194 | return {
195 | rotation: newProps.rotation
196 | };
197 | }
198 | break;
199 | default:
200 | }
201 | },
202 | commitUpdate(
203 | instance,
204 | updatePayload,
205 | type,
206 | oldProps,
207 | newProps,
208 | finishedWork
209 | ) {
210 | log("commitUpdate", arguments);
211 | switch (type) {
212 | case "threeWebGLRenderer": {
213 | if (updatePayload === true) {
214 | const { renderer, scene, camera } = instance;
215 | if (scene !== null && camera !== null) {
216 | renderer.render(scene, camera);
217 | }
218 | }
219 | break;
220 | }
221 | case "threeMesh":
222 | if (updatePayload.rotation !== undefined) {
223 | const {
224 | rotation: { x, y }
225 | } = updatePayload;
226 | if (x !== undefined) {
227 | instance.rotation.x = x;
228 | }
229 | if (y !== undefined) {
230 | instance.rotation.y = y;
231 | }
232 | }
233 | break;
234 | default:
235 | }
236 | },
237 |
238 | finalizeInitialChildren() {},
239 | getChildHostContext() {},
240 | getPublicInstance() {},
241 | getRootHostContext() {},
242 | prepareForCommit() {},
243 | resetAfterCommit() {},
244 | shouldSetTextContent() {
245 | return false;
246 | }
247 | });
248 |
249 | export default {
250 | render(whatToRender, div) {
251 | let container = reconciler.createContainer(div, false, false);
252 | reconciler.updateContainer(whatToRender, container, null, null);
253 | }
254 | };
255 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactTHREE from "./ReactTHREE";
3 | import App from "./App";
4 |
5 | ReactTHREE.render(, document.getElementById("root"));
6 |
--------------------------------------------------------------------------------