get routing working, add index for poetry, list first 6 poems on index, let each take you to their page with the poem's content

This commit is contained in:
2024-05-16 02:52:32 -04:00
parent 2cf484aa46
commit 3d22344e7f
44 changed files with 1134 additions and 178 deletions

View File

@@ -0,0 +1,41 @@
<script lang="ts">
import { T, useTask, useThrelte } from '@threlte/core';
import { World } from '@threlte/rapier';
import { Inspector } from 'three-inspect';
import { dev } from '$app/environment';
import SpaceSkysphere from './SpaceSkysphere.svelte';
import { Group, type Object3DEventMap } from 'three';
import DollyCam from './DollyCam.svelte';
import Planet from '$lib/components/scenes/app/Planet.svelte';
const { invalidate } = useThrelte();
let spaceObjects: Group<Object3DEventMap>;
useTask(
'updateSpaceObjects',
(delta) => {
if (!spaceObjects) return;
spaceObjects.rotation.y += 0.3 * delta;
spaceObjects.position.y = Math.sin(spaceObjects.rotation.y);
invalidate();
},
{ autoInvalidate: false }
);
</script>
<World gravity={[0, 0, 0]}>
<DollyCam />
<T.Group bind:ref={spaceObjects}>
<SpaceSkysphere size={100} count={500} />
<Planet />
<slot />
</T.Group>
</World>
{#if false}
<Inspector />
{/if}

View File

@@ -0,0 +1,26 @@
<!-- src/lib/CanvasLayout.svelte -->
<script lang="ts">
import { Canvas } from '@threlte/core';
</script>
<div class="canvas">
<Canvas>
<slot />
</Canvas>
</div>
<style>
:global(body) {
margin: 0;
}
.canvas {
width: 100%;
height: 100%;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
position: absolute;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -0,0 +1,44 @@
<script lang="ts">
import { T, useTask, useThrelte } from '@threlte/core';
import { onMount } from 'svelte';
import { PerspectiveCamera, Vector3 } from 'three';
const { invalidate } = useThrelte();
let camLookatPosition: Vector3 = new Vector3();
let camCurrentPosition: Vector3 = new Vector3();
let camDamping: number = 1;
let camera: PerspectiveCamera;
const handleMouseMove = (event: MouseEvent) => {
// normalize the mouse position to [-1, 1], and smoothly interpolate the camera's lookAt position
camLookatPosition.set(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0
);
};
useTask(
'dollyCam',
(delta) => {
if (!camera) return;
camCurrentPosition.lerp(camLookatPosition, camDamping * delta);
camera.lookAt(camCurrentPosition);
if (camera && camCurrentPosition.distanceTo(camLookatPosition) > 0.1) {
invalidate();
}
},
{ autoInvalidate: false }
);
onMount(() => {
document.addEventListener('mousemove', handleMouseMove);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
};
});
</script>
<T.PerspectiveCamera position.z={25} makeDefault fov={50} far={10000} bind:ref={camera} />

View File

@@ -0,0 +1,51 @@
<script lang="ts">
import { HTML } from '@threlte/extras';
import { Attractor } from '@threlte/rapier';
export let position: [number, number, number] = [0, 0, 0];
export let range: number = 100;
export let clickHandler: (() => void) | undefined = undefined;
export let htmlContent: HTMLElement | string = 'Hello!';
export let href: string = '/';
let isHovering = false;
let isPointerDown = false;
const onClick = () => {
console.log('clicked!');
if (clickHandler) {
clickHandler();
}
};
</script>
<HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}>
<a
{href}
on:pointerenter={() => (isHovering = true)}
on:pointerleave={() => {
isPointerDown = false;
isHovering = false;
}}
on:pointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)}
on:pointercancel={() => {
isPointerDown = false;
isHovering = false;
}}
on:click={onClick}
class="bg-green-700 px-3 py-3 text-white opacity-50 hover:opacity-90 active:opacity-100"
style="transform: translate(-50%, 50%); display: block;"
>
{htmlContent}
</a>
</HTML>
<Attractor
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
{range}
strength={isHovering ? 1 : 0}
gravityType={'static'}
/>

View File

@@ -0,0 +1,19 @@
<script lang="ts" context="module">
import { T } from '@threlte/core';
import { Attractor, Collider, RigidBody } from '@threlte/rapier';
import { MeshBasicMaterial, SphereGeometry } from 'three';
const geometry = new SphereGeometry(1, 8, 4);
const material = new MeshBasicMaterial({ color: '#339933', wireframe: true });
const position: [number, number, number] = [0, 0, 0];
const scale: number = 2;
const offset = position.map((el) => el + 1.5);
</script>
<Attractor {position} range={100} strength={0.3} gravityType={'linear'} />
<T.Group position.x={-offset[0]} position.y={-offset[1]} position.z={offset[2]}>
<RigidBody linearDamping={0.3}>
<Collider shape="ball" args={[scale]} mass={scale} />
<T.Mesh scale={[scale, scale, scale]} {geometry} {material} />
</RigidBody>
</T.Group>

View File

@@ -5,7 +5,7 @@
import { Studio } from '@threlte/theatre';
</script>
<Studio enabled={false} />
<Studio enabled={dev} />
<Canvas>
<Spinners />

View File

@@ -8,18 +8,18 @@
let sequence: SequenceController;
let box: Mesh;
let ball: Mesh;
let spotlight: SpotLight;
let lastBoxPosition = new Vector3();
let currentBoxPosition = new Vector3();
let lastBallPosition = new Vector3();
let currentBallPosition = new Vector3();
let config = spinnersJson as IProjectConfig;
const boxMoved: any = (props: { position: { x: number; y: number; z: number } }) => {
if (box && spotlight) {
const ballMoved: any = (props: { position: { x: number; y: number; z: number } }) => {
if (ball && spotlight) {
const { x, y, z } = props.position;
currentBoxPosition.set(x, y, z);
spotlight.lookAt(currentBoxPosition);
lastBoxPosition.copy(currentBoxPosition);
currentBallPosition.set(x, y, z);
spotlight.lookAt(currentBallPosition);
lastBallPosition.copy(currentBallPosition);
}
};
</script>
@@ -33,10 +33,10 @@
<!-- create a T.SpotLight that looks at box-->
<T.SpotLight position={[0, 5, 3]} intensity={10} bind:ref={spotlight}></T.SpotLight>
<SheetObject key="Box" let:Transform let:Sync on:change={boxMoved}>
<SheetObject key="Box" let:Transform let:Sync on:change={ballMoved}>
<Transform>
<T.Mesh position.y={0.5} bind:ref={box}>
<T.BoxGeometry args={[1, 1, 1]} />
<T.Mesh position.y={0.5} bind:ref={ball}>
<T.SphereGeometry args={[1, 8, 4]} />
<T.MeshStandardMaterial color="#b00d03">
<Sync color roughness metalness />
</T.MeshStandardMaterial>

View File

@@ -1,32 +0,0 @@
<script lang="ts">
import { Canvas, T } from '@threlte/core';
import { OrbitControls } from '@threlte/extras';
import OrbitingSpheres from '$lib/components/scenes/home/OrbitingSpheres.svelte';
import { World } from '@threlte/rapier';
import { Inspector } from 'three-inspect';
import { dev } from '$app/environment';
import SpaceSkysphere from './SpaceSkysphere.svelte';
</script>
<Canvas>
<World gravity={[0, 0, 0]}>
<T.PerspectiveCamera position.y={15} position.z={25} makeDefault fov={70} far={10000}>
<OrbitControls
enableZoom={false}
enablePan={false}
enableRotate={false}
enableDamping
target.y={0}
autoRotate
/>
</T.PerspectiveCamera>
<SpaceSkysphere size={100} count={500} />
<OrbitingSpheres position={[0, 0, 0]} range={10} />
</World>
{#if dev}
<Inspector />
{/if}
</Canvas>

View File

@@ -1,86 +0,0 @@
<script lang="ts" context="module">
const geometry = new SphereGeometry(1, 8, 4);
const material = new MeshBasicMaterial({ color: '#339933' });
</script>
<script lang="ts">
import { T } from '@threlte/core';
import { HTML } from '@threlte/extras';
import { Attractor, Collider, RigidBody } from '@threlte/rapier';
import { MeshBasicMaterial, SphereGeometry, Vector3 } from 'three';
export let range: number = 10;
export let position: [number, number, number] = [0, 0, 0];
let isHovering = false;
let isPointerDown = false;
const bodyPositions = [
new Vector3(position[0] - range, position[0] - range, position[0] - range).toArray(),
new Vector3(position[1] + range / 2, position[1] + range, position[1] + range).toArray(),
new Vector3(position[2] + range, position[2] - range / 2, position[2] + range).toArray()
];
const getId = () => {
return Math.random().toString(16).slice(2);
};
const getRandomSize = (): number => {
return Math.random() / 4 + 0.25;
};
const generateBodies = (c: number) => {
return Array(c)
.fill('x')
.map((_, index) => {
return {
id: getId(),
position: bodyPositions[index],
size: getRandomSize()
};
});
};
const onClick = () => {
console.log('clicked');
};
$: bodies = generateBodies(2);
</script>
<HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}>
<button
on:pointerenter={() => (isHovering = true)}
on:pointerleave={() => {
isPointerDown = false;
isHovering = false;
}}
on:pointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)}
on:pointercancel={() => {
isPointerDown = false;
isHovering = false;
}}
on:click={onClick}
class="rounded-full bg-orange-500 px-3 text-white hover:opacity-90 active:opacity-70"
>
Hello!
</button>
</HTML>
<Attractor
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
range={200}
strength={isHovering ? 1 : 0.1}
gravityType={'linear'}
/>
{#each bodies as body (body.id)}
<T.Group position={body.position}>
<RigidBody>
<Collider shape="ball" args={[body.size]} mass={body.size} />
<Attractor range={50} strength={1} gravityType={'newtonian'} />
<T.Mesh scale={[body.size, body.size, body.size]} {geometry} {material} />
</RigidBody>
</T.Group>
{/each}