globae update

This commit is contained in:
2020-04-18 23:58:18 +02:00
parent 8e36c2b2f0
commit c531181972
3 changed files with 49 additions and 30 deletions

View File

@@ -29,11 +29,15 @@ class WebglGlobe {
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 = this.options.cameraDistance || 1 //a multiplier to move camera backward or forward this.options.cameraDistance = this.options.cameraDistance || 1 //a multiplier to move camera backward or forward
this.referenceHeight = 1;//used to set camera distance from globe where referenceHeight == window height
this._canUpdate = false
this.cities = options.markers//list of cities with their options this.cities = options.markers//list of cities with their options
this._canUpdate = false
this.hasUpdateCameraPos = false
this.referenceHeight = 1;//used to set camera distance from globe where referenceHeight == window height
this.currMarkerScrollOffset = 0
this.markersScrollOffset = 0
this.globeScrollOffset = 0
let gl let gl
let canvas = document.createElement('canvas') let canvas = document.createElement('canvas')
try { gl = canvas.getContext('webgl') } try { gl = canvas.getContext('webgl') }
@@ -55,7 +59,7 @@ class WebglGlobe {
//to allow transparent background on webgl canvas //to allow transparent background on webgl canvas
alpha: true, alpha: true,
//only enable antialiasing if screen is small with no retina(for performances reasons) //only enable antialiasing if screen is small with no retina(for performances reasons)
antialias: window.innerWidth < 768 || !window.devicePixelRatio == 1 ? true : false, antialias: window.innerWidth < 768 || window.devicePixelRatio == 1 ? true : false,
}) })
// we put the canvas at the end of body tag as 'position:fixed' // we put the canvas at the end of body tag as 'position:fixed'
@@ -153,6 +157,11 @@ class WebglGlobe {
// Position marker // Position marker
let p = lonLatToVector3(markers[i].lng, markers[i].lat) let p = lonLatToVector3(markers[i].lng, markers[i].lat)
//scale marker position to fit globe size
p[0] *= this.referenceHeight/2;
p[1] *= this.referenceHeight/2;
p[2] *= this.referenceHeight/2;
// Wrap marker in link // Wrap marker in link
let el = document.createElement('a') let el = document.createElement('a')
el.style.pointerEvents = 'auto' el.style.pointerEvents = 'auto'
@@ -233,10 +242,17 @@ class WebglGlobe {
* As the camera rotates arount the globe, we cant simply move the Y position of the camera or the globe * As the camera rotates arount the globe, we cant simply move the Y position of the camera or the globe
* Instead, we move the globe vertex inside the vertex shadder after compute the project on screen, so we pass the 'scroll' position to a uniform * Instead, we move the globe vertex inside the vertex shadder after compute the project on screen, so we pass the 'scroll' position to a uniform
*/ */
updateCameraPos(y) { updateCameraPos(y, scrollDiff) {
y *= 2; this.globeScrollOffset = y;
this.markersScrollOffset = scrollDiff
//avoid jump due to smoothing when setting it for first time as the inital values are 0
if (!this.hasUpdateCameraPos) {
this.hasUpdateCameraPos = true
if (this.globeMesh.material.uniforms.uCameraOffsetY) { if (this.globeMesh.material.uniforms.uCameraOffsetY) {
this.globeMesh.material.uniforms.uCameraOffsetY.value += ( y - this.globeMesh.material.uniforms.uCameraOffsetY.value ) * this.options.scrollSmoothing this.globeMesh.material.uniforms.uCameraOffsetY.value = this.globeScrollOffset
}
this.currMarkerScrollOffset = this.markersScrollOffset
} }
} }
@@ -255,10 +271,16 @@ class WebglGlobe {
// Update // Update
update () { update () {
if (!this.supportWebgl || !this._canUpdate || !this.imageLoaded) { if (!this.supportWebgl || !this._canUpdate || !this.imageLoaded || !this.hasUpdateCameraPos) {
return return
} }
if (this.globeMesh.material.uniforms.uCameraOffsetY) {
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
//compute the camera view-projection matrix to use it on the markers //compute the camera view-projection matrix to use it on the markers
this.camera.update() this.camera.update()
vec3.set(this.cameraPosition, this.camera.worldMatrix[12], this.camera.worldMatrix[13], this.camera.worldMatrix[14]) vec3.set(this.cameraPosition, this.camera.worldMatrix[12], this.camera.worldMatrix[13], this.camera.worldMatrix[14])
@@ -266,7 +288,7 @@ class WebglGlobe {
mat4.multiply(this.viewProjectionMatrix, this.viewProjectionMatrix, this.camera.inverseWorldMatrix) mat4.multiply(this.viewProjectionMatrix, this.viewProjectionMatrix, this.camera.inverseWorldMatrix)
//Auto rotate the globe //Auto rotate the globe
this.globeMesh.rotation[1] = this.options.autoRotationSpeed this.globeMesh.rotation[1] += this.options.autoRotationSpeed
this.globeMesh.updateMatrix() this.globeMesh.updateMatrix()
this.globeMesh.updateWorldMatrix() this.globeMesh.updateWorldMatrix()
@@ -294,6 +316,8 @@ class WebglGlobe {
vec3.subtract(V, V, this.cameraPosition) vec3.subtract(V, V, this.cameraPosition)
vec3.normalize(V, V) vec3.normalize(V, V)
//the marker is behind the globe: clamp it to the globe edge //the marker is behind the globe: clamp it to the globe edge
if (vec3.dot(V, N) * -1 < 0) { if (vec3.dot(V, N) * -1 < 0) {
let dir = vec2.create() let dir = vec2.create()
@@ -305,11 +329,14 @@ class WebglGlobe {
vec2.normalize(dir2d, dir2d) vec2.normalize(dir2d, dir2d)
vec2.scale(dir2d, dir2d, this.circleScreenSize) vec2.scale(dir2d, dir2d, this.circleScreenSize)
vec2.add(dir2d, dir2d, center) vec2.add(dir2d, dir2d, center)
dir2d[1] += this.currMarkerScrollOffset
marker.el.style.transform = `translate(${dir2d[0]}px, ${dir2d[1]}px) translateZ(0)` marker.el.style.transform = `translate(${dir2d[0]}px, ${dir2d[1]}px) translateZ(0)`
marker.el.classList.remove('is-active') marker.el.classList.remove('is-active')
} }
//marker is in front of the globe; update 2D position //marker is in front of the globe; update 2D position
else { else {
y += this.currMarkerScrollOffset
marker.el.style.transform = `translate(${x}px, ${y}px) translateZ(0)` marker.el.style.transform = `translate(${x}px, ${y}px) translateZ(0)`
marker.el.classList.add('is-active') marker.el.classList.add('is-active')
} }

View File

@@ -18,9 +18,8 @@
}; };
} }
// Props // Props
// export let type = '' export let type = ''
let scope let scope
let globe let globe
let containerTop = 0 let containerTop = 0
@@ -36,6 +35,7 @@
globe.resize() globe.resize()
globe.update() globe.update()
} }
const update = () => { const update = () => {
requestAnimationFrame(update) requestAnimationFrame(update)
globe.update() globe.update()
@@ -43,10 +43,10 @@
const onScroll = (e)=> { const onScroll = (e)=> {
let scrollDiff = (containerTop + window.innerHeight + (containerHeight - window.innerHeight) /2 ) - document.documentElement.scrollTop let scrollDiff = (containerTop + window.innerHeight + (containerHeight - window.innerHeight) /2 ) - document.documentElement.scrollTop
let scrollRatio = 1 - ( scrollDiff / window.innerHeight ) let scrollRatio = (1 - ( scrollDiff / window.innerHeight ) ) * 2
globe && globe.updateCameraPos( scrollRatio, scrollDiff - window.innerHeight)
globe && globe.updateCameraPos( scrollRatio )
} }
/* /*
** Run code when mounted ** Run code when mounted
*/ */
@@ -72,8 +72,8 @@
// Init the globe from library // Init the globe from library
globe = new InteractiveGlobe({ globe = new InteractiveGlobe({
el: scope, el: scope,
cameraDistance: 1.5, cameraDistance: 0.5,//smaller number == larger globe
autoRotationSpeed: -0.01, autoRotationSpeed: -0.0025,
scrollSmoothing: 0.5, scrollSmoothing: 0.5,
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 => {
@@ -99,12 +99,8 @@
<svelte:window on:resize={resize} on:scroll={onScroll} /> <svelte:window on:resize={resize} on:scroll={onScroll} />
<!-- {#if type === 'part'} {#if type === 'part'}
<div class="globe__cut"> <div class="globe globe--cut" bind:this={scope} />
<div class="globe" bind:this={scope} />
</div>
{:else} {:else}
<div class="globe" bind:this={scope} /> <div class="globe" bind:this={scope} />
{/if} --> {/if}
<div class="globe" bind:this={scope} />

View File

@@ -9,6 +9,7 @@
// pointer-events: none; // pointer-events: none;
user-select: none; user-select: none;
////DEBUG//// ////DEBUG////
background: rgba(255,0,0,0.2); background: rgba(255,0,0,0.2);
&:after { &:after {
@@ -30,19 +31,14 @@
height: 2000px; height: 2000px;
} }
// Cut // Cut
&__cut { &--cut {
opacity: 0.5; opacity: 0.5;
overflow: hidden; overflow: hidden;
width: 100vw; width: 100vw;
height: 35vw; height: 35vw;
min-height: 400px; min-height: 400px;
padding: 0; padding: 0;
// Partial globe
// .globe {
// margin-top: -18vw;
// }
} }
} }