Last active
April 17, 2024 15:05
-
-
Save Typiqally/d2acdab215a4c76902aabf90cdd162f0 to your computer and use it in GitHub Desktop.
OrientationCube for React and TailwindCSS, can be used with Three.js easily
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Example usage | |
const [rotationMatrix, setRotationMatrix] = useState<number[]>(new Array(16).fill(0)); | |
<OrientationCube | |
sizeInPixels={64} | |
rotationMatrix={rotationMatrix} | |
/> | |
setRotationMatrix(camera.matrixWorldInverse.clone().elements); | |
*/ | |
import {CSSProperties} from 'react'; | |
export enum Orientation { | |
Front = 'front', | |
Right = 'right', | |
Back = 'back', | |
Left = 'left', | |
Top = 'top', | |
Bottom = 'bottom', | |
} | |
interface Props { | |
sizeInPixels: number; | |
rotationMatrix: number[]; | |
labels?: { [key in Orientation]: string } | |
className?: string; | |
onFaceClicked?: (orientation: Orientation) => void; | |
} | |
export function OrientationCube(props: Props) { | |
const sizeInPixelsHalved = props.sizeInPixels / 2; | |
const styles: { [key in Orientation]: CSSProperties } = { | |
front: {transform: `rotateY(0deg) translateZ(${sizeInPixelsHalved}px)`}, | |
right: {transform: `rotateY(90deg) translateZ(${sizeInPixelsHalved}px)`}, | |
back: {transform: `rotateY(180deg) translateZ(${sizeInPixelsHalved}px)`}, | |
left: {transform: `rotateY(-90deg) translateZ(${sizeInPixelsHalved}px)`}, | |
top: {transform: `rotateX(90deg) translateZ(${sizeInPixelsHalved}px)`}, | |
bottom: {transform: `rotateX(-90deg) translateZ(${sizeInPixelsHalved}px)`}, | |
}; | |
const convertRotationMatrixToCss = (rotationMatrix: number[]): CSSProperties => { | |
return { | |
transform: `translateZ(-${sizeInPixelsHalved}px) matrix3d( | |
${rotationMatrix[0]}, ${-rotationMatrix[1]}, ${rotationMatrix[2]}, 0, | |
${-rotationMatrix[4]}, ${rotationMatrix[5]}, ${-rotationMatrix[6]}, 0, | |
${rotationMatrix[8]}, ${-rotationMatrix[9]}, ${rotationMatrix[10]}, 0, | |
0, 0, 0, 1)` | |
}; | |
}; | |
const handleFaceClicked = (orientation: Orientation) => { | |
if (props.onFaceClicked) { | |
props.onFaceClicked(orientation); | |
} | |
}; | |
const getLabelForOrientation = (orientation: Orientation): string => { | |
return props.labels && orientation in props.labels | |
? props.labels[orientation] | |
: orientation.valueOf(); | |
}; | |
return <div | |
className="transform-style-3d relative " style={{ | |
width: `${props.sizeInPixels}px`, | |
height: `${props.sizeInPixels}px`, | |
...convertRotationMatrixToCss(props.rotationMatrix) | |
}}> | |
{Object.values(Orientation).map((o, index) => ( | |
<div | |
className={`absolute flex select-none items-center justify-center border-2 border-white ${props.className ?? ''}`} | |
key={index} | |
style={{ | |
width: `${props.sizeInPixels}px`, | |
height: `${props.sizeInPixels}px`, | |
...styles[o], | |
}} | |
onClick={() => handleFaceClicked(o)}> | |
{getLabelForOrientation(o)} | |
</div> | |
))} | |
</div>; | |
} | |
export default OrientationCube; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment