Skip to content

Instantly share code, notes, and snippets.

@amcdnl
Created July 11, 2022 12:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amcdnl/2bbe3e6cbe6ab2f738c8e6a45441cb73 to your computer and use it in GitHub Desktop.
Save amcdnl/2bbe3e6cbe6ab2f738c8e6a45441cb73 to your computer and use it in GitHub Desktop.
import React, { FC, useMemo, useRef } from 'react';
import { a, useSpring } from '@react-spring/three';
import { TextureLoader, LinearFilter, DoubleSide, Color, MathUtils } from 'three';
import { animationConfig } from '../utils';
import { useLoader } from '@react-three/fiber';
import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader';
export interface IconProps {
image: string;
opacity?: number;
id: string;
animated?: boolean;
size?: number;
onActive?: (state: boolean) => void;
onClick?: () => void;
onContextMenu?: () => void;
}
const SvgShape = ({ shape, color, index }) => (
<mesh>
<meshBasicMaterial
color={color}
aspect={window.innerWidth / window.innerHeight}
opacity={1}
side={DoubleSide}
depthWrite={false}
transparent
polygonOffset
polygonOffsetFactor={index * -0.1}
/>
<shapeGeometry args={[shape]} />
</mesh>
);
export const Icon: FC<IconProps> = ({
image,
id,
size,
opacity,
animated,
onActive,
onClick,
onContextMenu
}) => {
const { paths } = useLoader(SVGLoader, image);
const shapes = useMemo(
() =>
paths.flatMap((path, index) =>
path.toShapes(true).map(shape => ({ index, shape, color: new Color('blue') }))
),
[paths]
);
// const texture = useMemo(() => new TextureLoader().load(image), [image]);
const { scale, spriteOpacity } = useSpring({
from: {
scale: [0.00001, 0.00001, 0.00001],
spriteOpacity: 0
},
to: {
scale: [1, 1, 1],
spriteOpacity: opacity
},
config: {
...animationConfig,
duration: animated ? undefined : 0
}
});
console.log('here', paths, shapes);
return (
<a.group
position={[-6.5, 5, 10]}
scale={[0.25, 0.25, 0.25]}
rotation={[MathUtils.degToRad(0), MathUtils.degToRad(180), MathUtils.degToRad(180)]}
userData={{ id }}
onClick={onClick}
onPointerDown={event => {
// context menu controls
if (event.nativeEvent.buttons === 2) {
event.stopPropagation();
onContextMenu();
}
}}
onPointerOver={() => onActive(true)}
onPointerOut={() => onActive(false)}
>
{shapes.map((props, key) => (
<SvgShape key={key} {...props} />
))}
</a.group>
);
};
Icon.defaultProps = {
opacity: 1
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment