cyberbotics / webots

Webots Robot Simulator
https://cyberbotics.com
Apache License 2.0
3.31k stars 1.72k forks source link

The usage of Webots.js inside the React App. #6626

Open AndRockSYS opened 3 months ago

AndRockSYS commented 3 months ago

Hi!

I'm trying to implement Webots.js inside my React App with the useEffect hook which calls loadScene() on webots-view component and that just gives me an error and loadScene()is undefined. Also, I was trying to put the path to the .x3d file straight from the component, didn't work as well.

I was wondering if that's even possible and if yes then how can I implement the Webots view inside my React app?

Thanks in advance!

lukicdarkoo commented 3 days ago

Here is an example of how to make a React/TypeScript wrapper:

import { useRef, useImperativeHandle, forwardRef, useEffect } from 'react';
import './wwi/WebotsView';

type WebotsConnectFunction = (
  server: string,            // Server address
  mode: string,              // Mode (string)
  isBroadcast: boolean,      // Broadcast flag
  isMobileDevice: boolean,   // Mobile device flag
  timeout: number,           // Timeout in milliseconds
  thumbnail: string          // Thumbnail as string
) => void;

type WebotsViewProps = {
  ondisconnect?: () => void;
}

type WebotsViewRef = {
  connect: WebotsConnectFunction; // Custom ref type,
  close: () => void;             // Custom ref type
};

const WebotsView = forwardRef<WebotsViewRef, WebotsViewProps>(({ ondisconnect }, ref) => {
  const webComponentRef = useRef<HTMLElement>(null);

  useImperativeHandle(ref, () => ({
    connect: (server: string, mode: number | string, isBroadcast: boolean, isMobileDevice: boolean, timeout: number, thumbnail: string) => {
      console.log('Connecting to Webots server');
      if (webComponentRef.current) {
        (webComponentRef.current as any).connect(server, mode, isBroadcast, isMobileDevice, timeout, thumbnail);
      }
    },
    close: () => {
      console.log('Closing Webots connection');
      if (webComponentRef.current) {
        (webComponentRef.current as any).close();
      }
    }
  }));

  useEffect(() => {
    return () => {
      console.log('Closing Webots connection');
      if (webComponentRef.current) {
        (webComponentRef.current as any).close();
      }
      webComponentRef.current = null;
    };
  }, []);

  return (
    (<webots-view style={{ width: '100%', height: '100%', display: 'block', position: 'relative' }} ondisconnect={ondisconnect} ref={webComponentRef} />)
  );
});

export type {
  WebotsConnectFunction,
  WebotsViewRef,
};

export default WebotsView;
AndRockSYS commented 22 hours ago

Thanks for the example @lukicdarkoo , is it possible to run the server, which is needed for simulation, inside a browser is a different tab, so the user doesn't have to install webots app