react-babylonjs lets you build your scene and components using a familiar declarative syntax with the benefits of reusable components and hooks. The Babylon.js API is mostly covered thanks to code generation, but also custom props allow you to declaratively add shadows, physics, attach 2D/3D UI to meshes, 3D models, etc.
react-babylonjs' integrates the Babylon.js real time 3D engine with React
react-babylonjs
lets you build your scene and components using a familiar declarative syntax with the benefits of reusable components and hooks. The Babylon.js API is mostly covered thanks to code generation, but also custom props allow you to declaratively add shadows, physics, attach 2D/3D UI to meshes, 3D models, etc.
Fully supports hooks. Full support for TypeScript with auto-completion on elements and compile time checks. Context API and hooks provide easy access to Scene/Engine/Canvas.
$ npm i react-babylonjs @babylonjs/core @babylonjs/gui
OR
$ yarn add react-babylonjs @babylonjs/core @babylonjs/gui
No third party dependencies outside of React + babylon.js If you are upgrading from 2.x please follow the breaking changes guide:
If you are using 3D models ensure you have added the @babylonjs/loaders
NPM. It is not a direct dependency, but registers loaders as plugins via imports with side effects:
import @babylonjs/loaders;
import '@babylonjs/loaders/OBJ';
import '@babylonjs/loaders/glTF';
(more instructions on model loading in ES6 here )
react-babylonjs
tries to remain unopinionated about how you integrate BabylonJS with React. This module provides a 100% declarative option and/or you can customise by adding code. There are lots of escape hatches where you can switch to imperative coding and direct access to objects.
If you are new to React or babylon.js (or both) there is some learning ahead. The babylon.js documentation site is really useful for understanding the basics of lighting, cameras, etc. This project aims to make easy to integrate those into React using JSX.
Here we re-use a SpinningBox
component that can be clicked or hovered. These reusable components can be used to compose a declarative scene. We are using hooks for the clicking, hovering and spinning.
import React, { useRef, useState } from 'react'
import { Engine, Scene, useBeforeRender, useClick, useHover } from 'react-babylonjs'
import { Vector3, Color3 } from '@babylonjs/core'
const DefaultScale = new Vector3(1, 1, 1);
const BiggerScale = new Vector3(1.25, 1.25, 1.25);
const SpinningBox = (props) => {
// access Babylon scene objects with same React hook as regular DOM elements
const boxRef = useRef(null);
const [clicked, setClicked] = useState(false);
useClick(
() => setClicked(clicked => !clicked),
boxRef
);
const [hovered, setHovered] = useState(false);
useHover(
() => setHovered(true),
() => setHovered(false),
boxRef
);
// This will rotate the box on every Babylon frame.
const rpm = 5;
useBeforeRender((scene) => {
if (boxRef.current) {
// Delta time smoothes the animation.
var deltaTimeInMillis = scene.getEngine().getDeltaTime();
boxRef.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000));
}
});
return (<box name={props.name} ref={boxRef} size={2} position={props.position} scaling={clicked ? BiggerScale : DefaultScale}>
<standardMaterial name={`${props.name}-mat`} diffuseColor={hovered ? props.hoveredColor : props.color} specularColor={Color3.Black()} />
</box>);
}
export const SceneWithSpinningBoxes = () => (
<div>
<Engine antialias adaptToDeviceRatio canvasId='babylonJS' >
<Scene>
<arcRotateCamera name="camera1" target={Vector3.Zero()} alpha={Math.PI / 2} beta={Math.PI / 4} radius={8} />
<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
<SpinningBox name='left' position={new Vector3(-2, 0, 0)}
color={Color3.FromHexString('#EEB5EB')} hoveredColor={Color3.FromHexString('#C26DBC')}
/>
<SpinningBox name='right' position={new Vector3(2, 0, 0)}
color={Color3.FromHexString('#C8F4F9')} hoveredColor={Color3.FromHexString('#3CACAE')}
/>
</Scene>
</Engine>
</div>
)
You can declaratively use many features together - here only the button click handler actually has any code - and we have declarative Physics, GUI, Lighting and Shadows. demo: Bouncy demo
import React, { useCallback } from 'react';
/// full code at https://github.com/brianzinn/create-react-app-typescript-babylonjs
const onButtonClicked = () => {
if (sphere !== null) {
sphere.physicsImpostor!.applyImpulse(
Vector3.Up().scale(10), sphere.getAbsolutePosition()
)
}
}
const App: React.FC = () => {
const sphereRef = useCallback(node => {
sphere = node;
}, []);
return (
<Engine antialias={true} adaptToDeviceRatio={true} canvasId="sample-canvas">
<Scene enablePhysics={[gravityVector, new CannonJSPlugin()]}>
<arcRotateCamera name="arc" target={ new Vector3(0, 1, 0) }
alpha={-Math.PI / 2} beta={(0.5 + (Math.PI / 4))}
radius={4} minZ={0.001} wheelPrecision={50}
lowerRadiusLimit={8} upperRadiusLimit={20} upperBetaLimit={Math.PI / 2}
/>
<hemisphericLight name='hemi' direction={new Vector3(0, -1, 0)} intensity={0.8} />
<directionalLight name="shadow-light" setDirectionToTarget={[Vector3.Zero()]} direction={Vector3.Zero()} position = {new Vector3(-40, 30, -40)}
intensity={0.4} shadowMinZ={1} shadowMaxZ={2500}>
<shadowGenerator mapSize={1024} useBlurExponentialShadowMap={true} blurKernel={32}
shadowCasters={["sphere1", "dialog"]} forceBackFacesOnly={true} depthScale={100}
/>
</directionalLight>
<sphere ref={sphereRef} name="sphere1" diameter={2} segments={16} position={new Vector3(0, 2.5, 0)}>
<physicsImpostor type={PhysicsImpostor.SphereImpostor} _options={{
mass: 1,
restitution: 0.9
}} />
<plane name="dialog" size={2} position={new Vector3(0, 1.5, 0)}>
<advancedDynamicTexture name="dialogTexture" height={1024} width={1024} createForParentMesh={true} hasAlpha={true}>
<rectangle name="rect-1" height={0.5} width={1} thickness={12} cornerRadius={12}>
<rectangle>
<babylon-button name="close-icon" background="green" onPointerDownObservable={onButtonClicked} >
<textBlock text={'\uf00d click me'} fontFamily="FontAwesome" fontStyle="bold" fontSize={200} color="white" />
</babylon-button>
</rectangle>
</rectangle>
</advancedDynamicTexture>
</plane>
</sphere>
<ground name="ground1" width={10} height={10} subdivisions={2} receiveShadows={true}>
<physicsImpostor type={PhysicsImpostor.BoxImpostor} _options={{
mass: 0,
restitution: 0.9
}} />
</ground>
<vrExperienceHelper webVROptions={{ createDeviceOrientationCamera: false }} enableInteractions={true} />
</Scene>
</Engine>
);
}
With declarative (TSX/JSX) coding and fast refresh, you experience the same development workflow in 3D - ie: save changes in your editor and see them immediately in the browser. Note in this capture when the light is dimmed that the state changes persist even after code updates and scene refresh.
This project uses code generation, which allows fast reconciliation and excellent typings support.
react-babylon-spring
- https://github.com/hookex/react-babylon-spring.<pointsCloudSystem .../>
as host element.Author: brianzinn
Demo: https://brianzinn.github.io/react-babylonjs/?path=/story/*
Source Code: https://github.com/brianzinn/react-babylonjs
Article covers: How native is react native?, React Native vs (Ionic, Cordova), Similarities and difference between React Native and Native App Development.
Increase Performance of React Applications Via Array JavaScript Methods. We will create a simple event management application in the react to add, update, and delete an event.
I have been using React JS in my projects for quite some time now and am used to managing routing in my app using the react-router package. I have always been keen on having as little dependencies in my apps as possible, so, I always felt perturbed by the use of this particular package in simpler apps which did not have complex routes.
In this post, I will share my own point of view about React Hooks, and as the title of this post implies, I am not a big fan.
This article will walk you through the concepts you would need to know to step into the world of widely used ReactJS.