Remove old Globe

This commit is contained in:
2022-09-25 13:23:55 +02:00
parent bae3b4cdf7
commit 193f6dc2ee
47 changed files with 301 additions and 9037 deletions

View File

@@ -3,140 +3,159 @@
</style>
<script lang="ts">
import { onMount, getContext } from 'svelte'
import { getPosition, getRandomItem } from '$utils/functions'
import { getContext, onMount } from 'svelte'
import { fade, fly as flySvelte } from 'svelte/transition'
import { quartOut } from 'svelte/easing'
import { Globe, type Marker } from '$modules/globe'
import { getRandomItem, debounce } from '$utils/functions'
import reveal from '$animations/reveal'
// Components
import SplitText from '$components/SplitText.svelte'
const isDev = import.meta.env.DEV
export let type: string = undefined
export let autoRotate: boolean = true
export let scrollSmooth: number = 0.5
export let opacity: number = 1
export let enableMarkers: boolean = true
export let enableMarkersLinks: boolean = true
export let speed: number = 0.1
export let pane: boolean = isDev
export let width: number = undefined
let InteractiveGlobe: any
let globeEl: HTMLElement
let observer: IntersectionObserver
let globe: any
let innerWidth: number
let innerHeight: number
let containerTop = 0
let containerHeight = 0
$: globeResolution = innerWidth > 1440 && window.devicePixelRatio > 1 ? '4k' : '2k'
let globeParentEl: HTMLElement, globeEl: HTMLElement
let globe: any
let observer: IntersectionObserver
let animation: number
let hoveredMarker: { name: string, country: string } = null
const { continents, locations }: any = getContext('global')
const randomContinent: any = getRandomItem(continents.filter((cont: any) => cont.countries))
const markers = locations.map(({ name, slug, country, globe_close: isClose, coordinates: { coordinates }}: any) => ({
const randomContinent: any = getRandomItem(continents)
const markers = locations.map(({ name, slug, country, coordinates: { coordinates }}): Marker => ({
name,
slug,
countryName: country.name,
countrySlug: country.slug,
country: { ...country },
lat: coordinates[1],
lng: coordinates[0],
className: isClose ? 'is-close' : '',
}))
/*
** Functions
*/
// Globe update
const update = () => {
requestAnimationFrame(update)
globe.update()
}
onMount(() => {
const globeResolution = innerWidth > 1440 && window.devicePixelRatio > 1 ? 4 : 2
// On scroll
const handleScroll = () => {
let scrollDiff = (containerTop + innerHeight + (containerHeight - innerHeight) / 2) - document.documentElement.scrollTop
let scrollRatio = (1 - (scrollDiff / innerHeight)) * 2
if (globe) {
globe.updateCameraPos(scrollRatio, scrollDiff - innerHeight)
}
}
// On resize
const handleResize = () => {
if (globeEl && globe) {
containerTop = getPosition(globeEl).top
containerHeight = globeEl.clientHeight
requestAnimationFrame(() => {
globe.resize()
globe.update()
handleScroll()
})
}
}
/*
** Run code when mounted
*/
onMount(async () => {
// Import libraries and code
const { default: InteractiveGlobe } = await import('$modules/globe')
// Init the globe from library
globe = new InteractiveGlobe({
globe = new Globe({
el: globeEl,
//cameraDistance: size, // Smaller number == larger globe
autoRotationSpeed: autoRotate ? -0.0025 : 0,
rotationStart: randomContinent.rotation, // In degrees
scrollSmoothing: scrollSmooth,
opacity: opacity,
texture: `/images/globe-map-${globeResolution}.png`,
parent: globeParentEl,
mapFile: `/images/globe-map-${globeResolution}k.png`,
mapFileDark: `/images/globe-map-dark-${globeResolution}k.png`,
dpr: Math.min(Math.round(window.devicePixelRatio), 2),
autoRotate: true,
speed,
sunAngle: 2,
rotationStart: randomContinent.rotation,
enableMarkers,
enableMarkersLinks: enableMarkersLinks && type !== 'cropped',
markers,
onLinkClicked: () => {}
pane,
})
// Run the globe
update()
setTimeout(() => {
handleResize()
handleScroll()
}, 1000)
resize()
// Render only if in viewport
observer = new IntersectionObserver(([{ isIntersecting }]) => {
if (isIntersecting) {
update()
// Enable/Disable the globe when shown/hidden
const globeCanvas = document.querySelector('.globe-canvas')
observer = new IntersectionObserver(entries => {
entries.forEach(({ isIntersecting }: IntersectionObserverEntry) => {
if (isIntersecting) {
globe.enable()
globeCanvas.classList.remove('is-hidden')
} else {
globe.disable()
globeCanvas.classList.add('is-hidden')
if (isDev) {
console.log('globe: render/start')
}
})
}, {
threshold: 0,
rootMargin: '0px 0px 0px'
})
} else {
stop()
if (isDev) {
console.log('globe: render/stop')
}
}
}, { threshold: 0 })
observer.observe(globeEl)
// Destroy
return () => {
globe && globe.destroy()
destroy()
observer && observer.disconnect()
}
})
/**
* Methods
*/
// Update
const update = () => {
animation = requestAnimationFrame(update)
globe.render()
}
// Stop
const stop = () => {
cancelAnimationFrame(animation)
}
// Resize
const resize = debounce(() => {
globe.resize()
}, 100)
// Destroy
const destroy = () => {
stop()
globe.destroy()
}
</script>
<svelte:window
on:scroll={handleScroll}
on:resize={handleResize}
bind:innerHeight
bind:innerWidth
<svelte:window bind:innerWidth
on:resize={resize}
/>
<div class="globe" bind:this={globeParentEl}
class:is-cropped={type === 'cropped'}
style:--width={width ? `${width}px` : null}
>
<div class="globe__canvas" bind:this={globeEl}
class:is-faded={hoveredMarker}
>
<ul class="globe__markers">
{#each markers as { name, slug, country, lat, lng }}
<li class="globe__marker" data-location={slug} data-lat={lat} data-lng={lng}>
<a href="/{country.slug}/{slug}" data-sveltekit-noscroll
on:mouseenter={() => hoveredMarker = { name, country: country.name }}
on:mouseleave={() => hoveredMarker = null}
>
<i />
<span>{name}</span>
</a>
</li>
{/each}
</ul>
</div>
<section id="globe">
{#if type === 'cropped'}
<div class="globe-cropped">
<div class="globe" bind:this={globeEl} />
{#if hoveredMarker}
<div class="globe__location"
transition:fade={{ duration: 300, easing: quartOut }}
use:reveal={{
children: '.char',
animation: { y: ['110%', 0] },
options: {
stagger: 0.04,
duration: 1,
threshold: 0,
},
}}
>
<SplitText text={hoveredMarker.name} mode="chars" class="name" />
<p class="country" in:flySvelte={{ y: 16, duration: 800, easing: quartOut, delay: 900 }}>
{hoveredMarker.country}
</p>
</div>
{:else}
<div class="globe" bind:this={globeEl} />
{/if}
</section>
</div>