Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example with props #8

Open
stripuramallu3 opened this issue May 1, 2023 · 7 comments
Open

Example with props #8

stripuramallu3 opened this issue May 1, 2023 · 7 comments

Comments

@stripuramallu3
Copy link

stripuramallu3 commented May 1, 2023

Could an example be provided where the Scene component has to receive props (for example for the mesh position)?
How does the worker.jsx file to pass the props to the Scene?

// Scene.jsx (a self contained webgl app)
export default function App() {
  return (
    <mesh>
      <boxGeometry />
    </mesh>
  )
}
@drcmda
Copy link
Member

drcmda commented May 6, 2023

dom and canvas run into two different threads, it's up to you how you bridge that. broadcasts maybe, but there's no conventional way.

@stripuramallu3
Copy link
Author

Thank you! Was hoping there was a better/conventional way

@sshmaxime
Copy link

sshmaxime commented May 12, 2023

It would be so beautiful to pass a ref to the worker canvas and manipulate it from the main thread.

@drcmda
Copy link
Member

drcmda commented May 14, 2023

if you guys have any ideas go ahead, would love to have a standard interface of some sort. i have never used broadcasts before but it's gotta be something that works both in a worker and in a main thread.

@mhmdjaw
Copy link

mhmdjaw commented Dec 18, 2023

Does that also mean that <Html> from drei doesn't work in offscreen canvas? I tried it and it doesn't show any HTML elements.

@rob-myers
Copy link

To get this working, we can patch @react-three/[email protected] as follows:

Show patches/@react-three+offscreen+0.0.8.patch
diff --git a/node_modules/@react-three/offscreen/dist/Canvas.d.ts b/node_modules/@react-three/offscreen/dist/Canvas.d.ts
index 7084e67..e79c825 100644
--- a/node_modules/@react-three/offscreen/dist/Canvas.d.ts
+++ b/node_modules/@react-three/offscreen/dist/Canvas.d.ts
@@ -13,5 +13,6 @@ export interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size'
     eventSource?: HTMLElement | React.MutableRefObject<HTMLElement>;
     /** The event prefix that is cast into canvas pointer x/y events, default: "offset" */
     eventPrefix?: 'offset' | 'client' | 'page' | 'layer' | 'screen';
+    sceneProps?: Record<string, any>;
 }
 export declare function Canvas({ eventSource, worker, fallback, style, className, id, ...props }: CanvasProps): JSX.Element;
diff --git a/node_modules/@react-three/offscreen/dist/index.mjs b/node_modules/@react-three/offscreen/dist/index.mjs
index acf1918..9282957 100644
--- a/node_modules/@react-three/offscreen/dist/index.mjs
+++ b/node_modules/@react-three/offscreen/dist/index.mjs
@@ -86,6 +86,7 @@ function Canvas({
   style,
   className,
   id,
+  sceneProps = {},
   ...props
 }) {
   const [shouldFallback, setFallback] = React.useState(false);
@@ -111,7 +112,7 @@ function Canvas({
     worker.postMessage({
       type: 'init',
       payload: {
-        props,
+        props: { sceneProps, ...props },
         drawingSurface: offscreen,
         width: canvas.clientWidth,
         height: canvas.clientHeight,
@@ -181,9 +182,9 @@ function Canvas({
     if (!worker) return;
     worker.postMessage({
       type: 'props',
-      payload: props
+      payload: { sceneProps, ...props }
     });
-  }, [worker, props]);
+  }, [worker, props, sceneProps]);
   return shouldFallback ? /*#__PURE__*/React.createElement(Canvas$1, _extends({
     id: id,
     className: className,
@@ -203,7 +204,7 @@ function Canvas({
   });
 }
 
-function render(children) {
+function render(component) {
   extend(THREE);
   let root;
   let dpr = [1, 2];
@@ -218,6 +219,7 @@ function render(children) {
   const handleInit = payload => {
     const {
       props,
+      sceneProps,
       drawingSurface: canvas,
       width,
       top,
@@ -281,7 +283,7 @@ function render(children) {
       });
 
       // Render children once
-      root.render(children);
+      root.render(React.createElement(component, sceneProps));
     } catch (e) {
       postMessage({
         type: 'error',
@@ -317,14 +319,15 @@ function render(children) {
       stopPropagation() {}
     });
   };
-  const handleProps = payload => {
+  const handleProps = ({ sceneProps, ...payload }) => {
     if (!root) return;
     if (payload.dpr) dpr = payload.dpr;
     root.configure({
       size,
       dpr,
-      ...payload
+      ...payload,
     });
+    root.render(React.createElement(component, sceneProps));
   };
   const handlerMap = {
     resize: handleResize,
diff --git a/node_modules/@react-three/offscreen/dist/render.d.ts b/node_modules/@react-three/offscreen/dist/render.d.ts
index 2be3f9c..0cceb2b 100644
--- a/node_modules/@react-three/offscreen/dist/render.d.ts
+++ b/node_modules/@react-three/offscreen/dist/render.d.ts
@@ -1,2 +1,2 @@
 /// <reference types="react" />
-export declare function render(children: React.ReactNode): void;
+export declare function render<P extends {}>(component: React.FunctionComponent<P> | React.ComponentClass<P>): void;

Finally, restructure the project a bit:

// create-worker.js
// separate file fixes HMR
export const worker = new Worker(new URL('./worker.jsx', import.meta.url), { type: 'module' });
// App.jsx
import { worker } from "./create-worker";
// ...

  return (
      <Canvas
        fallback={<Scene testProp="hello, world! (fallback)" />}
        worker={worker}
        sceneProps={{ foo: "hello, world!" }}
      />
  );
// worker.jsx
import { render } from '@react-three/offscreen';
import Scene from "./Scene";

// Send component instead of ReactElement
render(Scene);

@richi-coder
Copy link

Does that also mean that <Html> from drei doesn't work in offscreen canvas? I tried it and it doesn't show any HTML elements.

How have you dealt with this so far? @mhmdjaw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants