Skip to main content

🍡react-mol

https://tsei.jp/rmol






build-✔ types-✔- demos-✔ license-MIT npm-package tweet

Installation

  • npm i three @react-three/fiber react-mol

Quick started

  • git clone https://github.com/tseijp/react-mol
  • cd react-mol
  • npm i
  • npm start
  • open browser and visit localhost:3000
  • Now you can go to our demo, and try its usage.





Recipes

AtomMolFlowTileSpring

Recipes of Atom


🍡<Mol/> is a molecular chemistry based simulation component that covers most cases of organic molecule simulation. (More Recipes)

View Code
import React from 'react'
import { Atom } from 'react-mol'

export const Mol = React.forwardRef((props, ref) => {
const {index: i, angle: a, double:d} = props
const state = React.useMemo(() => {
const position = calcMolPos(i, a, d)
const rotation = eulerVec3(position, [0,1,0])
return {position, rotation}
}, [i, a, d])

const children = React.useMemo(() =>
React.Children.map(props.children, (child, index) =>
React.cloneElement(child, {index})
), [props.children])

return <Atom {...props} ref={ref}
{...state} children={children}/>
})

Mol

🍭<Flow/> (More Recipes)

View Code
import React from 'react'
import { Atom } from 'react-mol'
import { useFrame } from ""

export const Flow = React.forwardRef((props, forwardRef) => {
const now = React.useRef(0)
const ref = React.useRef(null)
const fun = (value) => typeof value==="function"
useFrame((_, delta) => {
if (!ref.current) return
now.current += delta
const { position: p, scale: s, args: a,
rotation: r, color: c } = props
const args = fun(a)
? a(now.current,...ref.current.position.toArray())
: [ now.current,...(a || []) ]
p && ref.current.position.set(...(fun(p)? p(...args): p))
r && ref.current.rotation.set(...(fun(r)? r(...args): r))
s && ref.current.scale.set(...(fun(s)? s(...args): s))
c && ref.current.color.set(fun(c)? c(...args): c)
})
return <Atom ref={ref}/>
})

Points

What does it look like?

🪐<Atom/> (live demo).

import React from 'react'
import ReactDOM from 'react-dom'
import { Atom } from 'react-mol'
import { Canvas, useFrame } from ''

function Basic () {
// This reference will give us direct access to the last instance
const ref = React.useRef(null)

// Rotate instance every frame, this is outside of React without overhead
useFrame(() => {
ref.current.rotation.x =
ref.current.rotation.y =
ref.current.rotation.z += 0.025
})

return (
<Instanced>
<boxBufferGeometry attach="geometry" />
<meshPhongMaterial attach="material" />
<Atom color="red" position={[1, -2, -5]} rotation={[0, 0, Math.PI/3]}>
<Atom color="green" position={[2, 0, 1]} rotation={[0, 0, Math.PI/3]}>
<Atom color="green" position={[2, 0, 1]} rotation={[0, 0, Math.PI/3]}>
<Atom color="green" position={[2, 0, 1]} rotation={[0, 0, Math.PI/3]}>
<Atom color="green" position={[2, 0, 1]} rotation={[0, 0, Math.PI/3]}>
<Atom color="green" position={[2, 0, 1]} rotation={[0, 0, Math.PI/3]}>
<Atom color="blue" position={[2, 0, 0]} ref={ref}/>
</Atom>
</Atom>
</Atom>
</Atom>
</Atom>
</Atom>
</Instanced>
)
}

ReactDOM.render(
<Canvas>
<pointLight />
<ambientLight />
<Basic />
</Canvas>,
document.getElementById('root')
)
Show Recursion Example
import React from 'react'
import ReactDOM from 'react-dom'
import { Atom } from 'react-mol'
import { Canvas, useFrame } from ''

function Basic () {
// This reference will give us direct access to the last instance
const ref = React.useRef(null)

// Rotate instance every frame, this is outside of React without overhead
useFrame(() => {
ref.current.rotation.x =
ref.current.rotation.y =
ref.current.rotation.z += 0.025
})

return (
<Instanced>
<Recursion>
<boxBufferGeometry/>
<meshPhongMaterial/>
<Atom color="red" position={[1, -2, -5]} rotation={[0, 0, Math.PI/3]}/>
{[...Array(5)].map((_, i) =>
<Atom color="green" position={[2, 0, 1]} rotation={[0, 0, Math.PI/3]} key={i}/>
)}
<Atom color="blue" position={[2, 0, 0]} ref={ref}/>
</Recursion>
</Instanced>
)
}

ReactDOM.render(
<Canvas>
<pointLight/>
<ambientLight/>
<Basic/>
</Canvas>,
document.getElementById('root')
)





Recipes of Mol


Mol


Hierarchy


Recurtion


Results

Methyl alcohol

CH3 OH

<C>
<H/>
<H/>
<H/>
<OH/>
</C>
<Recursion>
<CH3/>
<OH/>
</Recursion>

CH3OH

Acetil acid

CH3 COOH

<C>
<CH3/>
<O double/>
<OH/>
</C>
<Recursion>
<CH3/>
<COOH/>
</Recursion>

CH3COOH

Poly ethylene

Poly CH2

<H>
<Poly n={100}}>
{next =>
<CH2>
<CH2>
{next||<H/>}
</CH2>
</CH2>
}
</Poly>
</H>
<Recursion>
<H/>
{Array(200)
.fill(0)
.map((_,i) =>
<C key={i}>
<H/>
<H/>
</C>
)}
<H/>
</Recursion>

Polyethylene






Recipes of Flow


Flow


Code


Results

Points
<Instanced position={[-12.5,0,-25]} count={2500}>
<sphereBufferGeometry/>
<meshPhongMaterial />
{[...Array(2500)].map((_,i) =>
<Flow key={i} color={colors[i]}
args={(t,x,_,z) => [
sin((x+t)/3)+sin((z+t)/2)]}
position={r => [i%c,r,i/c%c]}
scale={r => [r/3,r/3,r/3]} />
)}
</Instanced>

Points

Boxes
<Instanced count={10**3}>
<boxBufferGeometry />
<meshPhongMaterial/>
{[...Array(1000)].map((_,i) =>
<Flow key={i} color={colors[i]}
args={(t,x,y,z) => [
sin(x/4+t)+sin(y/4+t)+sin(z/4+t) ]}
position={[i%10-5,i/10%10-5,i/100-5]}
rotation={r => [0,r*2,r*3]}
scale={r => [r/4,r/4,r/4]}/>
)}
</Instanced>

Boxes

Spheres
<Instanced count={1000}>
<sphereBufferGeometry args={[1,32,32]}/>
<meshPhongMaterial color={0xffffff}/>
{[...Array(1000)].map((_, i) =>
<Flow key={i} color={colors[i]}
args={[...Array(4)].map(() => rand())}
position={(t,s,x,y,z) => [
x*40-20 + cos(t*s*6) + sin(t*s*2),
y*40-20 + sin(t*s*4) + cos(t*s*4),
z*40-20 + cos(t*s*2) + sin(t*s*6),]}
scale={(t,s) => Array(3).fill(
max(.3, cos((t+s*10)*s))*s)}/>
)}
</Instanced>

Spheres

Dodecas
<Instanced count={1000}>
<dodecahedronBufferGeometry args={[1,0]}/>
<meshStandardMaterial/>
{[...Array(1000)].map((_,i) =>
<Flow key={i} color={colors[i]}
args={[...Array(4)].map(() => rand())}
position={(t,s,x,y,z) => [
((x-.5)-cos(t*s+x)-sin(t*s/1))*x*100,
((y-.5)-sin(t*s+y)-cos(t*s/3))*y*100,
((z-.5)-cos(t*s+z)-sin(t*s/5))*z*100,]}
rotation={(t,s)=>Array(3).fill(cos(t*s))}
scale={(t,s)=>Array(3).fill(cos(t*s))}/>
)}
</Instanced>

Dodecas






Recipes of Spring


Spring


Results

Pieces

Pieces

Bounds

Bounds

Pipes

Pipes

Recipes of Tile


Tile


Code






Recipes of Plant

TODO

Koch Curve
<F recursion LR={[90,90]}>
<F />
<F L/>
<F R/>
<F L/>
</F>
Meandering Snake
<F recursion
LR={[90,90]}>
<F />
<F LL/>
<F RR/>
<F L/>
<F R/>
</F>
Urban Charting
<F recursion
LR={[90,90]}>
<F/>
<F LL/>
<F RR/>
<F RR/>
<F LL/>
</F>