All Projects → pmndrs → React Three Flex

pmndrs / React Three Flex

Licence: mit
💪📦 Flexbox for react-three-fiber

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to React Three Flex

Flex.css
flex.css is declarative layout which is compatible with wechat, UC, webview and other main-stream mobile browser and surpports react, vue, angular.
Stars: ✭ 1,537 (+101.18%)
Mutual labels:  flex, flexbox
Core Layout
Flexbox & CSS-style Layout in Swift.
Stars: ✭ 215 (-71.86%)
Mutual labels:  flex, flexbox
React Flexa
Responsive React Flexbox (CSS Flexible Box Layout Module) grid system based heavily on the standard CSS API.
Stars: ✭ 120 (-84.29%)
Mutual labels:  flex, flexbox
Lbrnmeituan
ReactNative 仿美团项目
Stars: ✭ 84 (-89.01%)
Mutual labels:  flex, flexbox
flexui
A light UI for C++ with XML and CSS support
Stars: ✭ 21 (-97.25%)
Mutual labels:  flex, flexbox
Flexy
Flexy is minimal CSS framework made with Flex
Stars: ✭ 114 (-85.08%)
Mutual labels:  flex, flexbox
Flexulator
A visual flexbox space distribution calculator
Stars: ✭ 171 (-77.62%)
Mutual labels:  flex, flexbox
Infinity Css Grid
Fluid Flex Solution for making infinite grid columns.
Stars: ✭ 112 (-85.34%)
Mutual labels:  flex, flexbox
react-styled-flexbox
A Flexbox React component harnessing the power of styled-components
Stars: ✭ 30 (-96.07%)
Mutual labels:  flex, flexbox
sass-flexbox
Manage Flexbox in Sass easily.
Stars: ✭ 40 (-94.76%)
Mutual labels:  flex, flexbox
Sprite Flex Layout
grid-layout is a layout engine which implements flex, can use in canvas/node-canvas
Stars: ✭ 15 (-98.04%)
Mutual labels:  flex, flexbox
React Flexview
A powerful React component to abstract over flexbox and create any layout on any browser
Stars: ✭ 276 (-63.87%)
Mutual labels:  flex, flexbox
Flexible Grid
Flexible grid layouts to get you familiar with building within the flexible grid system.(HTML, CSS, SASS, SCSS)
Stars: ✭ 154 (-79.84%)
Mutual labels:  flex, flexbox
flexboxes
CSS flexbox framework with pure flexbox grid ability
Stars: ✭ 27 (-96.47%)
Mutual labels:  flex, flexbox
Katana
Katana is CSS Layout System made with Flexbox
Stars: ✭ 57 (-92.54%)
Mutual labels:  flex, flexbox
Waffle Grid
An easy to use flexbox grid system.
Stars: ✭ 602 (-21.2%)
Mutual labels:  flex, flexbox
Ol Cesium
OpenLayers - Cesium integration
Stars: ✭ 660 (-13.61%)
Mutual labels:  3d
3d Convolutional Speaker Recognition
🔈 Deep Learning & 3D Convolutional Neural Networks for Speaker Verification
Stars: ✭ 697 (-8.77%)
Mutual labels:  3d
Fauxgl
Software-only 3D renderer written in Go.
Stars: ✭ 658 (-13.87%)
Mutual labels:  3d
Extreme 3d faces
Extreme 3D Face Reconstruction: Looking Past Occlusions
Stars: ✭ 653 (-14.53%)
Mutual labels:  3d

@react-three/flex

Build Status Version Downloads Discord Shield

Placing content in THREE.js is hard. @react-three/flex brings the webs flexbox spec to react-three-fiber. It is based on Yoga, Facebook's open source layout engine for react-native.

npm install @react-three/flex

These demos are real, you can click them! They contain the full code, too.

Table of contents

Usage

Simply create layouts by wrapping your 3D objects in different <Box /> instances inside a <Flex /> container. This way they will be automatically placed in the 3D space following the flexbox specification just like in the DOM.

import { Flex, Box } from '@react-three/flex'

const Layout = () => (
  <Flex justifyContent="center" alignItems="center">
    <Box centerAnchor>
      <mesh geometry={box} />
    </Box>
    <Box centerAnchor flexGrow={1}>
      <mesh geometry={torus} />
    </Box>
  </Flex>
)

You can tweak the container and the boxes using standard CSS flex properties, like flexDirection or justifyContent for the container and flexGrow for the boxes. There are also shorthands, like align and justify. See the props docs below for more info.

Anchors

When positioning items, react-three-flex needs to know where the object anchor is: Yoga Layout expects the object position to be relative to the upper left corner, which is the same as the DOM expects.

Most THREE.js geometries, though, are positioned relative to the object center. To tell react-three-flex that your <Box /> positioning is relative to the center you need to set the centerAnchor prop to true.

<Box centerAnchor>
  <mesh geometry={sphere} />
</Box>

If you nest <Box /> elements, though, you need to set it to false. See Nesting.

Anchors

Stretching

By default @react-three/flex controls elements position only. In some cases you may want to control element sizing too. Since @react-three/flex has no information about how the inner content size works, you need to set your content size manually. To do so @react-three/flex provides you the container size in two ways:

  • Using a children render function:
<Flex>
  <Box width="auto" height="auto" flexGrow={1} centerAnchor>
    {(width, height) => <Plane args={[width, height]} />}
  </Box>
</Flex>
  • Using a hook:
function Inner() {
  const [width, height] = useFlexSize()
  return <Plane args={[width, height]} />
}

function Outer() {
  return (
    <Flex>
      <Box width="auto" height="auto" flexGrow={1} centerAnchor>
        <Inner />

Remember that the useFlexSize hook works ONLY if your <Box/> is outside the component.

Invalidation and Reflow

While the DOM's Flexbox has full control over all the changes of the tree, @react-three/flex runs on React, hence it has no way to know if a children size or shape has changed. For performance reasons Flex layout calculation does not run every frame, and it has to be triggered manually in some cases.

What will trigger a reflow:

  • <Flexbox/> props changes (alignItems, size, ...)
  • <Box/> props changes (flexGrow, margin, ...)
  • <Flexbox/> and <Box/> rerenders with children differences
function AnimatedBox() {
  // Since <Box/> is inside the component, setting the state will rerender it, thus causing a reflow.
  // ⚠️ If <Box/> were outside this component, this would NOT cause a reflow!
  const [state, setState] = useState(true)
  useInterval(() => setState((s) => !s), 1000)
  return (
    <Box centerAnchor>
      <mesh>
        <boxBufferGeometry attach="geometry" args={[state ? 10 : 30, 10, 10]} />

This will NOT cause a reflow!

function AnimatedBox() {
  // ⚠️ Setting state does not rerender <Box/> since it's in the parent
  // ‼️ No Reflow!!
  const [state, setState] = useState(true)
  useInterval(() => setState((s) => !s), 1000)
  return (
    <mesh scale={[state ? 1 : 3, 1, 1]}>
      <boxBufferGeometry attach="geometry" />
    </mesh>
  )
}

function Layout() {
  return (
    <Flex>
      <Box centerAnchor>
        <AnimatedBox />

For every other case (setting size with the useFrame hook, performing react-spring animation, or <Box/> are not rerendered) you'll need to manually cause a reflow, using the useReflow() hook. Reflows requests are batched every frame so you can call it from hundreds of components without performance issues.

Animation with useFrame():

function AnimatedBox() {
  const ref = useRef()
  const reflow = useReflow()
  useFrame(({ clock }) => {
    ref.current.scale.x = 1 + Math.sin(clock.getElapsed())
    reflow()
  })
  return (
    <Box centerAnchor>
      <mesh ref={ref}>

<Box/> outside of component:

function AnimatedBox() {
  const [state, setState] = useState(true)
  useInterval(() => setState((s) => !s), 1000)
  const reflow = useReflow()
  useEffect(reflow, [state])
  return (
    <mesh ref={ref} scale={[state ? 1 : 3, 1, 1]}>

Sizing

@react-three/flex differs from DOM Flexbox in that it relies on a parent container for the root flex. It is required to specify its dimensions using size prop for wrapping and to be responsive.

<Flex flexDirection="row" flexWrap="wrap" size={[300, 200, 0]}>
  {/* ... */}
</Flex>

⚠️ WATCH OUT! Yoga flexbox engine uses whole integer numbers to perform layout calculation to preserve precision - @react-three/flex multiplies every element size and flex prop by the scaleFactor of the root flex container. By default it's 100, and works well for small scenes. If you use a different scene scale, make sure to tweak it accordingly.

Bounds

Axis Orientation

Another important difference with DOM Flexbox is that you have to specify the plane of the container in 3D. The elements will be positioned in the 2D plane given by the two axes, using width and height calculated along the two axes.

The 2D flex container width and height will be calculated by looking at the size prop with respect of the chosen axes (100 for xy and 200 for y in this example).

The default plane is xy, the other possibilites are yz and xz.

<Flex plane="xy" size={[100, 200, 0]}>
  {/* ... */}
</Flex>

Axes Orientation

Margin and Padding

For every <Flex /> and <Box /> component you can specify the margin and padding like in DOM elements.

<Flex flexDirection="row" size={[300, 200, 0]} padding={30} margin={5}>
  <Box padding={5} marginTop={5} centerAnchor>
    <mesh geometry={sphere} />
  </Box>
</Flex>

Margin

Nesting

Since a <Flex /> component works the same way as a DOM one, you can easily make complex layouts by nesting flex containers.

<Flex flexDirection="row" flexWrap="wrap" size={[50, 0, 0]}>
  <Box centerAnchor>
    <mesh geometry={sphere} />
  </Box>
  <Box flexDirection="column" flexWrap="no-wrap">
    <Box centerAnchor>
      <mesh geometry={sphere} />
    </Box>
    <Box centerAnchor>
      <mesh geometry={box} />
    </Box>
  </Box>
</Flex>

Measuring the container

When building responsive layouts you might need to synchronize the size of the 3D Flex container with the DOM, for example to synchronize scroll position or to modify the height of a scroll container. To make it easier, you can use the onReflow prop on the root <Flex> component that will be called every time the flex layout is recalculated - e.g. when any content changes.

<Flex onReflow={(totalWidth, totalHeight) => ...}>
 {/* ... */}
</Flex>

API

You can find a full list of props here.

<Flex
  size={[1, 1, 1]} // Total size of the flex container, see above
  position={[0, 0, 0]} // Default - position for the flex container in the scene
  direction="ltr" // Default - right to left or right to left
  plane="xy" // Default - plane axes, see above
  scaleFactor={100} // Default - integer scale factor, see above (Sizing)
  onReflow={fn} // Called everytime the layout is recalculated
  {...R3FlexProps} // Standard Flexbox props, described below
>
  <Box>{/* ... */}</Box>
</Flex>
<Box
  centerAnchor // If the inner content position is relative to its center, see above (Anchors)
  {...R3FlexProps} // Standard Flexbox props, described below
>
  <mesh geometry={box} />
</Box>

Or you can pass a function as children:

<Box>{(width, height) => <Model width={width} height={height} />}</Box>

Flexbox props

Both <Flex/> and <Box /> components share the same Flexbox props API from Yoga. The library also provides string and number inputs for convenience and shorthands.

Example:

// Flex with padding top set to 10, alignItems to 'center', justifyContent to 'space-around' and flexWrap to 'wrap'
<Flex pt={10} align="center" justify="space-around" wrap="wrap">
  {/* ... */}
</Flex>
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].