-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathmapbox.stories.tsx
More file actions
85 lines (78 loc) · 2.36 KB
/
mapbox.stories.tsx
File metadata and controls
85 lines (78 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { useFrame, Vector3 } from "@react-three/fiber";
import { useControls } from "leva";
import MapboxGl from "mapbox-gl";
import 'mapbox-gl/dist/mapbox-gl.css';
import { FC, PropsWithChildren, useRef, useState } from "react";
import Map from 'react-map-gl/mapbox';
import { Canvas } from "react-three-map";
import { Mesh } from "three";
export default { title: 'Canvas' }
export function Mapbox() {
const { mapboxToken } = useControls({
mapboxToken: {
value: import.meta.env.VITE_MAPBOX_TOKEN || '',
label: 'mapbox token',
}
})
MapboxGl.accessToken = mapboxToken;
return <div style={{ height: '100vh' }}>
{!mapboxToken && <Center>Add a mapbox token to load this component</Center>}
{!!mapboxToken && <Map
antialias
initialViewState={{
latitude: 51,
longitude: 0,
zoom: 13,
pitch: 60,
}}
mapStyle="mapbox://styles/mapbox/streets-v12"
>
<Canvas latitude={51} longitude={0}>
<hemisphereLight
args={["#ffffff", "#60666C"]}
position={[1, 4.5, 3]}
intensity={Math.PI}
/>
<object3D scale={500}>
<Box position={[-1.2, 1, 0]} />
<Box position={[1.2, 1, 0]} />
</object3D>
</Canvas>
</Map>}
</div>
}
const Center = ({ children }: PropsWithChildren) => (
<div style={{
display: 'flex',
height: '100%',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
}}>{children}</div>
)
const Box: FC<{ position: Vector3 }> = (props) => {
// This reference gives us direct access to the THREE.Mesh object
const ref = useRef<Mesh>(null)
// Hold state for hovered and clicked events
const [hovered, hover] = useState(false)
const [clicked, click] = useState(false)
// Subscribe this component to the render-loop, rotate the mesh every frame
useFrame((_state, delta) => {
if (!ref.current) return;
ref.current.rotation.x += delta;
ref.current.rotation.z -= delta;
})
// Return the view, these are regular Threejs elements expressed in JSX
return (
<mesh
{...props}
ref={ref}
scale={clicked ? 1.5 : 1}
onClick={() => click(!clicked)}
onPointerOver={() => hover(true)}
onPointerOut={() => hover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}