Globe: Add opacity option, Part globe WIP

- Don't run the onScroll method on load, creates a funky translate otherwise
- Bind window innerHeight via Svelte
- Path scroll smoothing option value as prop
This commit is contained in:
2020-04-21 09:46:27 +02:00
parent c9ba6a9f29
commit 65c9822b73
6 changed files with 62 additions and 33 deletions

View File

@@ -31,7 +31,8 @@ class WebglGlobe {
this.options = options this.options = options
this.options.autoRotationSpeed = this.options.autoRotationSpeed || 0 this.options.autoRotationSpeed = this.options.autoRotationSpeed || 0
this.options.scrollSmoothing = this.options.scrollSmoothing || 0.5 // Smooth the globe position to avoid janks on scroll (lower == smoother) this.options.scrollSmoothing = this.options.scrollSmoothing || 0.5 // Smooth the globe position to avoid janks on scroll (lower == smoother)
this.options.cameraDistance = 1//this.options.cameraDistance || 1 // A multiplier to move camera backward or forward this.options.cameraDistance = 1 // this.options.cameraDistance || 1 // A multiplier to move camera backward or forward
this.options.opacity = this.options.opacity || 1
this.cities = options.markers // List of cities with their options this.cities = options.markers // List of cities with their options
this._canUpdate = false this._canUpdate = false
@@ -171,7 +172,7 @@ class WebglGlobe {
el.style.pointerEvents = 'auto' el.style.pointerEvents = 'auto'
el.setAttribute('href', '/location/' + markers[i].countrySlug + '/' + markers[i].slug) el.setAttribute('href', '/location/' + markers[i].countrySlug + '/' + markers[i].slug)
el.setAttribute('sapper-noscroll', '') el.setAttribute('sapper-noscroll', '')
if (markers[i].className) el.classList.add( markers[i].className ) if (markers[i].className) el.classList.add(markers[i].className)
// Add label // Add label
let span = document.createElement('span') let span = document.createElement('span')
@@ -193,6 +194,11 @@ class WebglGlobe {
// Add class // Add class
el.classList.add('marker') el.classList.add('marker')
// Add a class if opacity is below 1
if (this.options.opacity < 1) {
el.classList.add('is-light')
}
// Callback on click // Callback on click
el.addEventListener('click', () => { el.addEventListener('click', () => {
this.options.onLinkClicked && this.options.onLinkClicked() this.options.onLinkClicked && this.options.onLinkClicked()
@@ -238,7 +244,7 @@ class WebglGlobe {
this.options.cameraDistance = this.height / this.$el.clientHeight; this.options.cameraDistance = this.height / this.$el.clientHeight;
// Remove retina on small screen (aka mobile) to boost perfs // Remove retina on small screen (aka mobile) to boost perfs
this.renderer.setPixelRatio( window.innerWidth < 768 ? 1 : window.devicePixelRatio) this.renderer.setPixelRatio(window.innerWidth < 768 ? 1 : window.devicePixelRatio)
this.renderer.resize(this.width , this.height) this.renderer.resize(this.width , this.height)
// Update camera aspect ratio // Update camera aspect ratio
@@ -277,8 +283,8 @@ class WebglGlobe {
// Destroy // Destroy
destroy() { destroy() {
this.disable()//stop render loop this.disable()//stop render loop
document.body.removeChild( this.$markerWrapper ) document.body.removeChild(this.$markerWrapper )
document.body.removeChild( this.renderer.canvas ) document.body.removeChild(this.renderer.canvas )
this.camera.delete()//to remove event listeners this.camera.delete()//to remove event listeners
} }
@@ -287,7 +293,7 @@ class WebglGlobe {
* This helps saving perfs and battery * This helps saving perfs and battery
*/ */
enable () { enable () {
this.renderer.canvas.style.opacity = 1 this.renderer.canvas.style.opacity = this.options.opacity
this.$markerWrapper.style.opacity = 1 this.$markerWrapper.style.opacity = 1
this._canUpdate = true this._canUpdate = true
} }
@@ -305,7 +311,7 @@ class WebglGlobe {
} }
if (this.globeMesh.material.uniforms.uCameraOffsetY) { if (this.globeMesh.material.uniforms.uCameraOffsetY) {
this.globeMesh.material.uniforms.uCameraOffsetY.value += ( this.globeScrollOffset - this.globeMesh.material.uniforms.uCameraOffsetY.value ) * this.options.scrollSmoothing this.globeMesh.material.uniforms.uCameraOffsetY.value += (this.globeScrollOffset - this.globeMesh.material.uniforms.uCameraOffsetY.value ) * this.options.scrollSmoothing
} }
this.currMarkerScrollOffset += (this.markersScrollOffset - this.currMarkerScrollOffset) * this.options.scrollSmoothing this.currMarkerScrollOffset += (this.markersScrollOffset - this.currMarkerScrollOffset) * this.options.scrollSmoothing

View File

@@ -7,11 +7,13 @@
import Lazy from 'svelte-lazy' import Lazy from 'svelte-lazy'
// Props // Props
export let type = '' export let type = null
export let size = 0.575
export let autoRotate = true export let autoRotate = true
export let scrollSmooth = 0.5
export let opacity = 1
let scope let scope
let globe let globe
let windowHeight
let containerTop = 0 let containerTop = 0
let containerHeight = 0 let containerHeight = 0
$: randomRotationPosition = getRandomArrayItem($continents.filter(continent => continent.countries)).rotation_position $: randomRotationPosition = getRandomArrayItem($continents.filter(continent => continent.countries)).rotation_position
@@ -26,6 +28,13 @@
globe.update() globe.update()
} }
// On scroll
const onScroll = () => {
let scrollDiff = (containerTop + windowHeight + (containerHeight - windowHeight) / 2) - document.documentElement.scrollTop
let scrollRatio = (1 - (scrollDiff / windowHeight)) * 2
globe && globe.updateCameraPos(scrollRatio, scrollDiff - windowHeight)
}
// On resize // On resize
const onResize = () => { const onResize = () => {
if (scope) { if (scope) {
@@ -34,13 +43,7 @@
} }
globe.resize() globe.resize()
globe.update() globe.update()
} onScroll()
// On scroll
const onScroll = () => {
let scrollDiff = (containerTop + window.innerHeight + (containerHeight - window.innerHeight) / 2) - document.documentElement.scrollTop
let scrollRatio = (1 - (scrollDiff / window.innerHeight)) * 2
globe && globe.updateCameraPos(scrollRatio, scrollDiff - window.innerHeight)
} }
@@ -58,7 +61,8 @@
//cameraDistance: size, // Smaller number == larger globe //cameraDistance: size, // Smaller number == larger globe
autoRotationSpeed: autoRotate ? -0.0025 : 0, autoRotationSpeed: autoRotate ? -0.0025 : 0,
rotationStart: randomRotationPosition, // In degrees rotationStart: randomRotationPosition, // In degrees
scrollSmoothing: 0.5, scrollSmoothing: scrollSmooth,
opacity: opacity,
texture: `/img/globe/map-${window.innerWidth > 1440 && window.devicePixelRatio > 1 ? '4k' : '2k'}.png`, texture: `/img/globe/map-${window.innerWidth > 1440 && window.devicePixelRatio > 1 ? '4k' : '2k'}.png`,
markers: [ ...$locations.map(location => { markers: [ ...$locations.map(location => {
return { return {
@@ -71,13 +75,12 @@
className: location.close ? 'is-close' : '', className: location.close ? 'is-close' : '',
} }
}) ], }) ],
onLinkClicked: () => { } onLinkClicked: () => {}
}) })
// Run the globe // Run the globe
onResize()
update() update()
onScroll() onResize()
// Enable/Disable the globe when shown/hidden // Enable/Disable the globe when shown/hidden
const globeScroll = ScrollOut({ const globeScroll = ScrollOut({
@@ -96,6 +99,12 @@
}) })
</script> </script>
<svelte:window on:resize={onResize} on:scroll={onScroll} /> <svelte:window on:scroll={onScroll} on:resize={onResize} bind:innerHeight={windowHeight} />
<div class="globe" class:globe--part={type === 'part'} bind:this={scope} /> {#if type === 'part'}
<div class="globe--part">
<div class="globe" bind:this={scope} />
</div>
{:else}
<div class="globe" bind:this={scope} />
{/if}

View File

@@ -80,7 +80,7 @@
{#if process.browser} {#if process.browser}
<Lazy offset={window.innerHeight}> <Lazy offset={window.innerHeight}>
<InteractiveGlobe type="part" /> <InteractiveGlobe type="part" opacity="0.5" />
</Lazy> </Lazy>
{/if} {/if}

View File

@@ -120,11 +120,7 @@
{#if process.browser} {#if process.browser}
<Lazy offset={window.innerHeight}> <Lazy offset={window.innerHeight}>
<InteractiveGlobe size={ <InteractiveGlobe />
(winWidth <= 768) ? 0.96 :
(winWidth <= 992) ? 0.6 :
0.575}
/>
</Lazy> </Lazy>
{/if} {/if}

View File

@@ -40,7 +40,6 @@
overflow: hidden; overflow: hidden;
height: 30vw; height: 30vw;
min-height: 300px; min-height: 300px;
opacity: 0.5;
} }
/* /*
@@ -102,6 +101,7 @@
font-size: rem(8px); font-size: rem(8px);
line-height: 1; line-height: 1;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 1px;
@include breakpoint (sm) { @include breakpoint (sm) {
font-size: rem(10px); font-size: rem(10px);
@@ -123,6 +123,20 @@
} }
} }
// Is light
&.is-light {
&.is-active {
.marker {
&__city {
color: #fff;
}
&__country {
color: #d2b7e4;
}
}
}
}
// Left positioned // Left positioned
&.is-left { &.is-left {
.marker { .marker {

View File

@@ -92,7 +92,11 @@
} }
// Globe // Globe
// .globe { .globe--part {
// } margin-top: 72px;
@include breakpoint (sm) {
margin-top: 136px;
}
}
} }