This repository was archived by the owner on Jun 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathPhone.tsx
89 lines (78 loc) · 3.15 KB
/
Phone.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
import { useThree } from "@react-three/fiber"
import React, { useEffect, useMemo } from "react"
import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"
import { VideoTexture } from "three"
import { CAMERA_DISTANCE, getPhoneLayout, PHONE_COLOR, PHONE_CURVE_SEGMENTS, PHONE_SHININESS } from "./helpers/layout"
import { roundedRect } from "./helpers/rounded-rectangle"
import { RoundedBox } from "./RoundedBox"
export const Phone: React.FC<{
videoTexture: VideoTexture | null
aspectRatio: number
baseScale: number
}> = ({ aspectRatio, videoTexture, baseScale }) => {
const frame = useCurrentFrame()
const { fps, durationInFrames } = useVideoConfig()
const layout = useMemo(() => getPhoneLayout(aspectRatio, baseScale), [aspectRatio, baseScale])
// Place a camera and set the distance to the object.
// Then make it look at the object.
const camera = useThree((state) => state.camera)
useEffect(() => {
camera.position.set(0, 0, CAMERA_DISTANCE)
camera.near = 0.2
camera.far = Math.max(5000, CAMERA_DISTANCE * 2)
camera.lookAt(0, 0, 0)
}, [camera])
// Make the video fill the phone texture
useEffect(() => {
if (videoTexture) {
videoTexture.repeat.y = 1 / layout.screen.height
videoTexture.repeat.x = 1 / layout.screen.width
}
}, [aspectRatio, layout.screen.height, layout.screen.width, videoTexture])
// During the whole scene, the phone is rotating.
// 2 * Math.PI is a full rotation.
const constantRotation = interpolate(frame, [0, durationInFrames], [0, Math.PI * 6])
// When the composition starts, there is some extra
// rotation and translation.
const entranceAnimation = spring({
frame,
fps,
config: {
damping: 200,
mass: 3,
},
})
// Calculate the entrance rotation,
// doing one full spin
const entranceRotation = interpolate(entranceAnimation, [0, 1], [-Math.PI, Math.PI])
// Calculating the total rotation of the phone
const rotateY = entranceRotation + constantRotation
// Calculating the translation of the phone at the beginning.
// The start position of the phone is set to 4 "units"
const translateY = interpolate(entranceAnimation, [0, 1], [-4, 0])
// Calculate a rounded rectangle for the phone screen
const screenGeometry = useMemo(() => {
return roundedRect({
width: layout.screen.width,
height: layout.screen.height,
radius: layout.screen.radius,
})
}, [layout.screen.height, layout.screen.radius, layout.screen.width])
return (
<group scale={entranceAnimation} rotation={[0, rotateY, 0]} position={[2.148, 0, -9.153]}>
<RoundedBox
radius={0.11395999999999931}
depth={layout.phone.thickness}
curveSegments={PHONE_CURVE_SEGMENTS}
position={layout.phone.position}
width={layout.phone.width}
height={layout.phone.height}>
<meshPhongMaterial color={PHONE_COLOR} shininess={PHONE_SHININESS} />
</RoundedBox>
<mesh position={layout.screen.position}>
<shapeGeometry args={[screenGeometry]} />
{videoTexture ? <meshBasicMaterial color="#ffc2c2" toneMapped={false} map={videoTexture} /> : null}
</mesh>
</group>
)
}