Skip to content

Instantly share code, notes, and snippets.

@sommerper
Last active January 19, 2024 20:02
Show Gist options
  • Save sommerper/b856980408ba311d5a2ac6fdc9d8cfb3 to your computer and use it in GitHub Desktop.
Save sommerper/b856980408ba311d5a2ac6fdc9d8cfb3 to your computer and use it in GitHub Desktop.

Revisions

  1. sommerper revised this gist Jan 19, 2024. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion +page.svelte
    Original file line number Diff line number Diff line change
    @@ -16,7 +16,6 @@
    let scrollOffset = 0;
    let lenis: Lenis;
    let mountingPage: HTMLElement;
    let progressText = '0%';
    onMount( () => {
  2. sommerper revised this gist Jan 19, 2024. 1 changed file with 0 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions +page.svelte
    Original file line number Diff line number Diff line change
    @@ -75,10 +75,6 @@
    }
    }
    :global(html) {
    // height: 100%;
    }
    $color: #14a32c;
    .the-canvas {
  3. sommerper revised this gist Jan 19, 2024. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions +page.svelte
    Original file line number Diff line number Diff line change
    @@ -58,9 +58,7 @@
    </div>
    <div class="the-canvas">
    <Canvas colorSpace="srgb" rendererParameters={webGLRendererParameters}>
    <!-- {#if preloaded} -->
    <Scene {scrollOffset} {lenis} {mountingPage} />
    <!-- {:else}{/if} -->
    </Canvas>
    </div>
    <div class="loadingWrapper">
  4. sommerper created this gist Jan 19, 2024.
    132 changes: 132 additions & 0 deletions +page.svelte
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    <script lang="ts">
    export const trailingSlash = 'always';
    import { Canvas } from '@threlte/core';
    import Lenis from '@studio-freight/lenis';
    import { onMount } from 'svelte';
    import Scene from '$lib/3d/Scene.svelte';
    import Stats from 'three/examples/jsm/libs/stats.module';
    import { T, forwardEventHandlers, useThrelte, useRender, useFrame } from '@threlte/core';
    import { createPreloader } from 'asset-preloader';
    import { gsap } from 'gsap';
    import { useProgress } from '@threlte/extras';
    import { useLoader } from '@threlte/core';
    let scrollOffset = 0;
    let lenis: Lenis;
    let mountingPage: HTMLElement;
    let progressText = '0%';
    onMount( () => {
    lenis = new Lenis({
    wrapper: document.querySelector('.scrollWrapper'), // element which has overflow
    content: document.querySelector('.pages') // usually wrapper's direct child
    });
    mountingPage = document.querySelector('.pages') || document.body;
    const stats = new Stats();
    document.body.appendChild(stats.dom);
    function raf(time: number) {
    lenis.raf(time);
    stats.update();
    requestAnimationFrame(raf);
    }
    requestAnimationFrame(raf);
    });
    const webGLRendererParameters = {
    antialias: true,
    alpha: true,
    powerPreference: 'high-performance',
    stencil: true,
    depth: true,
    logarithmicDepthBuffer: true
    };
    </script>


    <div class="scrollWrapper">
    <div class="scroll">
    <div class="pages">
    <!-- -->
    </div>
    </div>
    </div>
    <div class="the-canvas">
    <Canvas colorSpace="srgb" rendererParameters={webGLRendererParameters}>
    <!-- {#if preloaded} -->
    <Scene {scrollOffset} {lenis} {mountingPage} />
    <!-- {:else}{/if} -->
    </Canvas>
    </div>
    <div class="loadingWrapper">
    <div class="loadingCover" />
    <div class="loading">Loading... {progressText}</div>
    </div>


    <style lang="scss">
    :root {
    --color: #222222;
    * {
    box-sizing: border-box;
    }
    }
    :global(html) {
    // height: 100%;
    }
    $color: #14a32c;
    .the-canvas {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    }
    .scrollWrapper {
    z-index: 1000;
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    width: 100vw;
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
    pointer-events: all;
    .scroll {
    width: 100vw;
    }
    }
    .loadingWrapper {
    opacity: 1;
    z-index: 1000;
    .loadingCover {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    width: 100vw;
    height: 0vh;
    background-color: rgba(0, 0, 0, 0.8);
    }
    .loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    }
    }
    </style>
    112 changes: 112 additions & 0 deletions Scene.svelte
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,112 @@
    <script lang="ts">
    import Lenis from '@studio-freight/lenis';
    import DeviceDetector from 'device-detector-js';
    import { Canvas } from '@threlte/core';
    import { onMount } from 'svelte';
    import { injectLookAtPlugin } from '$lib/threlteplugins/lookat';
    import { Environment } from '@threlte/extras';
    import { OrbitControls } from '@threlte/extras';
    import { Group } from 'three';
    import * as THREE from 'three';
    import { T, forwardEventHandlers, useThrelte, useRender, useFrame } from '@threlte/core';
    import { TextureLoader } from 'three';
    import { useLoader } from '@threlte/core';
    import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
    import * as MathUtils from '$lib/utils/mathutils';
    import { setupEffectComposer, setupComposer } from '$lib/3d/sceneEffects';
    import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
    import { useGltf } from '@threlte/extras';
    import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
    import IntroPage from './IntroPage.svelte';
    import Molly from './custom/molly.svelte';
    import Mine from './custom/mine.svelte';
    injectLookAtPlugin();
    export let lenis: Lenis;
    export let mountingPage: HTMLElement;
    let target: any;
    const deviceDetector = new DeviceDetector();
    const device = deviceDetector.parse(navigator.userAgent);
    let preloaded = false;
    export const ref = new Group();
    const { scene, renderer, camera, size, invalidate } = useThrelte();
    if (device.os?.name === 'iOS' || device.os?.name === 'Android') {
    renderer.setPixelRatio(1);
    } else {
    renderer.setPixelRatio(window.devicePixelRatio);
    }
    const component = forwardEventHandlers();
    let rot = 0;
    const composer = setupComposer(renderer);
    $: setupEffectComposer(scene, $camera, composer);
    $: composer.setSize($size.width, $size.height);
    $: sizeChanged($size);
    function sizeChanged(size: any) {
    renderer.render(scene, $camera);
    composer.render();
    }
    useRender((_, delta) => {
    composer.render(delta);
    });
    const { start, stop, started } = useFrame(
    (ctx, delta) => {
    rot += delta * 0.1;
    },
    { autostart: true }
    );
    const textureLoader = useLoader(TextureLoader);
    const initPreloader = async () => {
    console.log('initPreloader start');
    await textureLoader.load('/textures/space-001.jpg').then((texture) => {
    console.log('texture', texture);
    });
    await textureLoader.load('/textures/trees-001.jpg').then((texture) => {
    console.log('texture', texture);
    });
    await useGltf('/3d/box-001.glb', { useDraco: true });
    console.log('initPreloader end');
    preloaded = true;
    };
    onMount(async () => {
    initPreloader();
    });
    </script>

    {#if preloaded}
    <T.PerspectiveCamera makeDefault fov={60} position={[0, 0, 10]} lookAt={[0, 0, 0]}>
    <!-- <OrbitControls enableDamping enableZoom={false} zoomSpeed={0.1} target={[0, 0, 0]} /> -->
    </T.PerspectiveCamera>
    <T.Object3D position={[0, 0, 0]} bind:ref={target} />
    <T.DirectionalLight {target} position={[0, 1, 1]} intensity={3} />
    <T.AmbientLight intensity={1} color={[0.2, 0.2, 0.2]} />

    <T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
    <T.Group>
    <IntroPage {lenis} {mountingPage} />
    <Molly {lenis} {mountingPage} />
    <Mine {lenis} {mountingPage} />
    </T.Group>

    <slot {ref} />
    </T>
    {:else}
    <p>Preloading</p>
    {/if}