diff --git a/src/globe/index.js b/src/globe/index.js index 7f01240..94ce280 100644 --- a/src/globe/index.js +++ b/src/globe/index.js @@ -29,10 +29,14 @@ class WebglGlobe { 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.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.cities = options.markers//list of cities with their options + this._canUpdate = false - - this.cities = options.markers//list of cities with their options + 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 canvas = document.createElement('canvas') @@ -55,7 +59,7 @@ class WebglGlobe { //to allow transparent background on webgl canvas alpha: true, //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' @@ -153,6 +157,11 @@ class WebglGlobe { // Position marker 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 let el = document.createElement('a') 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 * 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) { - y *= 2; - if (this.globeMesh.material.uniforms.uCameraOffsetY) { - this.globeMesh.material.uniforms.uCameraOffsetY.value += ( y - this.globeMesh.material.uniforms.uCameraOffsetY.value ) * this.options.scrollSmoothing + updateCameraPos(y, scrollDiff) { + 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) { + this.globeMesh.material.uniforms.uCameraOffsetY.value = this.globeScrollOffset + } + this.currMarkerScrollOffset = this.markersScrollOffset } } @@ -255,10 +271,16 @@ class WebglGlobe { // Update update () { - if (!this.supportWebgl || !this._canUpdate || !this.imageLoaded) { + if (!this.supportWebgl || !this._canUpdate || !this.imageLoaded || !this.hasUpdateCameraPos) { 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 this.camera.update() 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) //Auto rotate the globe - this.globeMesh.rotation[1] = this.options.autoRotationSpeed + this.globeMesh.rotation[1] += this.options.autoRotationSpeed this.globeMesh.updateMatrix() this.globeMesh.updateWorldMatrix() @@ -294,6 +316,8 @@ class WebglGlobe { vec3.subtract(V, V, this.cameraPosition) vec3.normalize(V, V) + + //the marker is behind the globe: clamp it to the globe edge if (vec3.dot(V, N) * -1 < 0) { let dir = vec2.create() @@ -305,11 +329,14 @@ class WebglGlobe { vec2.normalize(dir2d, dir2d) vec2.scale(dir2d, dir2d, this.circleScreenSize) vec2.add(dir2d, dir2d, center) + + dir2d[1] += this.currMarkerScrollOffset marker.el.style.transform = `translate(${dir2d[0]}px, ${dir2d[1]}px) translateZ(0)` marker.el.classList.remove('is-active') } //marker is in front of the globe; update 2D position else { + y += this.currMarkerScrollOffset marker.el.style.transform = `translate(${x}px, ${y}px) translateZ(0)` marker.el.classList.add('is-active') } diff --git a/src/molecules/InteractiveGlobe.svelte b/src/molecules/InteractiveGlobe.svelte index ec5b617..973cb2e 100644 --- a/src/molecules/InteractiveGlobe.svelte +++ b/src/molecules/InteractiveGlobe.svelte @@ -18,9 +18,8 @@ }; } - // Props - // export let type = '' + export let type = '' let scope let globe let containerTop = 0 @@ -36,6 +35,7 @@ globe.resize() globe.update() } + const update = () => { requestAnimationFrame(update) globe.update() @@ -43,10 +43,10 @@ const onScroll = (e)=> { let scrollDiff = (containerTop + window.innerHeight + (containerHeight - window.innerHeight) /2 ) - document.documentElement.scrollTop - let scrollRatio = 1 - ( scrollDiff / window.innerHeight ) - - globe && globe.updateCameraPos( scrollRatio ) + let scrollRatio = (1 - ( scrollDiff / window.innerHeight ) ) * 2 + globe && globe.updateCameraPos( scrollRatio, scrollDiff - window.innerHeight) } + /* ** Run code when mounted */ @@ -72,8 +72,8 @@ // Init the globe from library globe = new InteractiveGlobe({ el: scope, - cameraDistance: 1.5, - autoRotationSpeed: -0.01, + cameraDistance: 0.5,//smaller number == larger globe + autoRotationSpeed: -0.0025, scrollSmoothing: 0.5, texture: `/img/globe/map-${window.innerWidth > 1440 && window.devicePixelRatio > 1 ? '4k' : '2k'}.png`, markers: [...$locations.map(location => { @@ -99,12 +99,8 @@ - - -
\ No newline at end of file +{/if} diff --git a/src/style/molecules/_globe.scss b/src/style/molecules/_globe.scss index d9299b0..745b663 100644 --- a/src/style/molecules/_globe.scss +++ b/src/style/molecules/_globe.scss @@ -9,6 +9,7 @@ // pointer-events: none; user-select: none; + ////DEBUG//// background: rgba(255,0,0,0.2); &:after { @@ -30,19 +31,14 @@ height: 2000px; } - // Cut - &__cut { + &--cut { opacity: 0.5; overflow: hidden; width: 100vw; height: 35vw; min-height: 400px; padding: 0; - // Partial globe - // .globe { - // margin-top: -18vw; - // } } }