Skip to content

Commit

Permalink
add flying text, add fallback, update test
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor-Vuk committed Oct 18, 2024
1 parent 9d46e9c commit 3ab84eb
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 49 deletions.
4 changes: 2 additions & 2 deletions src/Experience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Canvas } from "react-three-map"
import Mapbox from "mapbox-gl"
import "mapbox-gl/dist/mapbox-gl.css"

// import Fallback from "./contentComponents/canvasComponents/fallback/Fallback" /* use Fallback component on Suspense if needed */
import Fallback from "./contentComponents/canvasComponents/fallback/Fallback" /* use Fallback component on Suspense if needed */
import { CanvasControl, SceneRenderControl } from "./helpers/leva"
import DirectionalLight from "./sceneComponents/DirectionalLight.tsx"
import SoftShadowsModifier from "./sceneComponents/SoftShadowsModifier.tsx"
Expand Down Expand Up @@ -137,7 +137,7 @@ export default function Experience() {
<EnvironmentMap />
</Suspense>
)}
<Suspense fallback={null}>
<Suspense fallback={<Fallback />}>
<Models zoomLevel={zoomLevel} />
</Suspense>
</Canvas>
Expand Down
136 changes: 106 additions & 30 deletions src/contentComponents/canvasComponents/CityText/CityText.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,121 @@
import { FC, useRef } from "react"
import { FC, useRef, Fragment, useMemo } from "react"
import { useFrame } from "@react-three/fiber"
import assetsPath from "../../../data/assetsPath.json"
import { Text, Line } from "@react-three/drei"
import * as THREE from "three"
import { BigNameValue } from "../canvasComponents.types"

const CityText: FC = () => {
console.log("CITY TEXT")
const textRef = useRef<THREE.Mesh>(null)

const schoolRef = useRef<THREE.Mesh>(null)
const footballRef = useRef<THREE.Mesh>(null)
const jeruzalemRef = useRef<THREE.Mesh>(null)
const betlehemRef = useRef<THREE.Mesh>(null)
const kindergartenRef = useRef<THREE.Mesh>(null)
const doctorRef = useRef<THREE.Mesh>(null)
const churchRef = useRef<THREE.Mesh>(null)

useFrame(({ camera }) => {
if (textRef.current) {
// Make the text follow the camera's rotation
textRef.current.quaternion.copy(camera.quaternion)
}
})
const refs = [
schoolRef,
footballRef,
jeruzalemRef,
betlehemRef,
kindergartenRef,
doctorRef,
churchRef,
]

return (
<>
<Text
ref={textRef}
font={assetsPath.cityFonts}
fontSize={10}
// material-toneMapped={false}
position={[-200, 45, 208]}
rotation={[0, -0.55, 0]} // Rotate 45 degrees around the Y-axis
refs.forEach((ref) => {
if (ref.current) {
ref.current.quaternion.copy(camera.quaternion)
}
})
})

/* {...textOptions} */
>
Hello world!
<meshBasicMaterial side={THREE.DoubleSide} color={"red"} />
</Text>
<Line
points={[
[-200, 40, 205], // Start point of the line (slightly below the text)
[-200, 5, 205], // End point of the line (further down)
]}
color="black"
lineWidth={1}
/>
</>
const defaultValues: BigNameValue[] = useMemo(
() => [
{
text: "OŠ Braće Radić",
ref: schoolRef,
textPosition: [-30, 45, 100],
lineStart: [-30, 40, 100],
lineEnd: [-30, 15, 100],
},
{
text: "NK Botinec",
ref: footballRef,
textPosition: [-315, 45, 290],
lineStart: [-315, 40, 290],
lineEnd: [-315, 10, 290],
},
{
text: "Park Jeruzalem",
ref: jeruzalemRef,
textPosition: [-225, 45, 310],
lineStart: [-225, 40, 310],
lineEnd: [-225, 10, 310],
},
{
text: "Park Betlehem",
ref: betlehemRef,
textPosition: [140, 45, -150],
lineStart: [140, 40, -150],
lineEnd: [140, 10, -150],
},
{
text: "Dječji vrtić Botinec",
ref: kindergartenRef,
textPosition: [290, 45, 250],
lineStart: [290, 40, 250],
lineEnd: [290, 15, 250],
},
{
text: "Dom zdravlja",
ref: doctorRef,
textPosition: [330, 45, 155],
lineStart: [330, 40, 155],
lineEnd: [330, 15, 155],
},
{
text: "Crkva sv.Stjepan",
ref: churchRef,
textPosition: [145, 45, 220],
lineStart: [145, 40, 220],
lineEnd: [145, 15, 220],
},
],
[],
)

const renderBigNames = () => {
return defaultValues.map((value, index) => (
<Fragment key={index}>
<Text
ref={value.ref}
font={assetsPath.cityFonts}
fontSize={8}
position={value.textPosition}
rotation={[0, 0, 0]}
outlineWidth={0.4}
outlineColor={new THREE.Color("#000000")}
>
{value.text}
<meshBasicMaterial side={THREE.DoubleSide} color={"#FFD700"} />
</Text>
<Line
points={[
value.lineStart, // Start point of the line (slightly below the text)
value.lineEnd, // End point of the line (further down)
]}
color="black"
lineWidth={1.2}
/>
</Fragment>
))
}
return <>{renderBigNames()}</>
}

export default CityText
28 changes: 16 additions & 12 deletions src/contentComponents/canvasComponents/CityText/cityText.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ReactThreeTestRenderer from "@react-three/test-renderer"

import CityText from "./CityText"

/* Mock must be declared before importing the component but it is is hoisted,
/* Mock must be declared before importing the component but it is hoisted,
meaning it will always be executed before any other code, regardless of where it's placed in the file. */

/* ------------------------- */
Expand All @@ -24,18 +24,22 @@ vi.mock("@react-three/drei", async () => {
specific parts of the module while leaving the rest unchanged. In this case we only want to mock Text component*/
const actual = (await vi.importActual("@react-three/drei")) as any

/* React.forwardRef allows you to pass a ref through a component to one of its child DOM nodes.
This is important because your CityText component relies on the textRef to control the text's orientation. */
const MockText = forwardRef(({ children, ...props }: any, ref: any) => {
return (
/* Instead of rendering Text we change it with mesh and just pass props to it and text */
<mesh {...props} text={children[0]} ref={ref} name="MockTextMesh">
{children}
</mesh>
)
})

MockText.displayName = "MockText"

return {
...actual,
/* React.forwardRef allows you to pass a ref through a component to one of its child DOM nodes.
This is important because your CityText component relies on the textRef to control the text's orientation. */
Text: forwardRef(({ children, ...props }: any, ref: any) => {
return (
/* Instead of rendering Text we change it with mesh and just pass props to it and text */
<mesh {...props} text={children[0]} ref={ref} name="MockTextMesh">
{children}
</mesh>
)
}),
Text: MockText,
}
})

Expand All @@ -44,6 +48,6 @@ describe("CityText Component", () => {
const renderer = await ReactThreeTestRenderer.create(<CityText />)

const meshChildren = renderer.scene.allChildren
expect(meshChildren.length).toBe(2)
expect(meshChildren.length).toBe(14)
})
})
2 changes: 1 addition & 1 deletion src/contentComponents/canvasComponents/Models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const Models = ({ zoomLevel }: { zoomLevel: ZoomLevel }) => {
textures={adjustedModelsTerrainTexture}
/>
<BuildingsModels groupedMeshes={groupedMeshes} />
<Suspense>
<Suspense fallback={null}>
<CityText />
</Suspense>
</group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ export type AssetProps = {
}

export type ZoomLevel = "minLevel" | "middleLevel" | "maxLevel"

export type BigNameValue = {
text: string
ref: React.RefObject<THREE.Mesh>
textPosition: [number, number, number]
lineStart: [number, number, number]
lineEnd: [number, number, number]
}
20 changes: 16 additions & 4 deletions src/contentComponents/canvasComponents/fallback/Fallback.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { useRef } from "react"
import { useFrame } from "@react-three/fiber"
import * as THREE from "three"

const Fallback = () => {
const meshRef = useRef<THREE.Mesh>(null)

// This function updates every frame, rotating the mesh
useFrame(() => {
if (meshRef.current) {
meshRef.current.rotation.x += 0.1 // Spin on the x-axis
}
})

return (
<mesh>
<sphereGeometry />
<meshStandardMaterial color="white" />
<mesh ref={meshRef} scale={[20, 20, 20]} position={[27, -120, 0]}>
<torusGeometry args={[1, 0.3, 16, 100]} />
<meshStandardMaterial color="#A8B99F" />
</mesh>
)
}

export default Fallback

0 comments on commit 3ab84eb

Please sign in to comment.