-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.tsx
94 lines (81 loc) · 2.61 KB
/
index.tsx
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
86
87
88
89
90
91
92
93
94
import React, {FC, useRef} from 'react';
import {Dimensions, StyleSheet} from 'react-native';
import {TScreenProps} from '@navigation/constants';
import {Canvas, useFrame} from '@react-three/fiber/native';
import {BufferGeometry, Material, Mesh, MeshStandardMaterial, NormalBufferAttributes} from 'three';
import {Gesture, GestureDetector} from 'react-native-gesture-handler';
import {SharedValue, useSharedValue} from 'react-native-reanimated';
import * as THREE from 'three';
import animateValueToZero from '@utils/animate-value-to-zero';
import Header from '@components/header';
const {width: SCREEN_WIDTH, height: SCREEN_HEIGHT} = Dimensions.get('screen');
interface ICube {
isPressed: SharedValue<boolean>;
cursor: SharedValue<{
x: number;
y: number;
}>;
}
const Cube: FC<ICube> = ({isPressed, cursor}) => {
const mesh = useRef<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[]>>(null);
const material = useRef<MeshStandardMaterial>(null);
useFrame(({camera}) => {
if (mesh.current) {
if (!isPressed.value) {
cursor.value = {
x: animateValueToZero(cursor.value.x, 0.01),
y: animateValueToZero(cursor.value.y, 0.01),
};
}
camera.position.x = Math.sin(-cursor.value.x * Math.PI * 2) * 3;
camera.position.z = Math.cos(-cursor.value.x * Math.PI * 2) * 3;
camera.position.y = -cursor.value.y * 10;
camera.lookAt(mesh.current.position);
if (material.current) {
material.current.color = new THREE.Color(isPressed.value ? 'red' : '#FF00FF');
}
}
});
return (
<mesh ref={mesh} rotation={[Math.PI / 4, Math.PI / 4, 0]}>
<boxGeometry />
<meshStandardMaterial color="#FF00FF" ref={material} />
</mesh>
);
};
const Lesson4: FC<TScreenProps<'Lesson 4'>> = () => {
const isPressed = useSharedValue(false);
const cursor = useSharedValue({x: 0, y: 0});
const gesture = Gesture.Pan()
.onBegin(() => {
isPressed.value = true;
})
.onUpdate((e) => {
cursor.value = {
x: e.absoluteX / SCREEN_WIDTH - 0.5,
y: -(e.absoluteY / SCREEN_HEIGHT - 0.5),
};
})
.onFinalize(() => {
isPressed.value = false;
});
return (
<>
<Header title="Interaction" />
<GestureDetector gesture={gesture}>
<Canvas style={styles.flex}>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Cube isPressed={isPressed} cursor={cursor} />
</Canvas>
</GestureDetector>
</>
);
};
const styles = StyleSheet.create({
flex: {
flex: 1,
backgroundColor: 'black',
},
});
export default Lesson4;