react-globe
Version:
Create beautiful and interactive React + ThreeJS globe visualizations with ease.
3 lines (2 loc) • 14 kB
JavaScript
function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var t=require("react"),o=e(t),n=require("es6-tween"),a=require("three"),i=e(require("resize-observer-polyfill")),r=require("three-glow-mesh"),s=require("d3-scale"),c=require("three/examples/jsm/controls/OrbitControls"),u=require("three.interaction"),l=e(require("tippy.js")),d={onClickMarker:function(e,t,o){},onDefocus:function(e){},onGlobeBackgroundTextureLoaded:function(){},onGlobeCloudsTextureLoaded:function(){},onGlobeTextureLoaded:function(){},onMouseOutMarker:function(e,t,o){},onMouseOverMarker:function(e,t,o){}},m="https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/clouds.png",h="https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/globe.jpg",f=[1.29027,103.851959],p={ambientLightColor:"white",ambientLightIntensity:.8,cameraAutoRotateSpeed:.1,cameraDistanceRadiusScale:3,cameraMaxDistanceRadiusScale:100,cameraMaxPolarAngle:Math.PI,cameraMinPolarAngle:0,cameraRotateSpeed:.2,cameraZoomSpeed:1,enableCameraAutoRotate:!0,enableCameraRotate:!0,enableCameraZoom:!0,enableDefocus:!0,enableGlobeGlow:!0,enableMarkerGlow:!0,enableMarkerTooltip:!0,focusAnimationDuration:1e3,focusDistanceRadiusScale:1.5,focusEasingFunction:["Cubic","Out"],globeCloudsOpacity:.3,globeGlowCoefficient:.1,globeGlowColor:"#d1d1d1",globeGlowPower:3,globeGlowRadiusScale:.2,markerEnterAnimationDuration:1e3,markerEnterEasingFunction:["Linear","None"],markerExitAnimationDuration:500,markerExitEasingFunction:["Cubic","Out"],markerGlowCoefficient:0,markerGlowPower:3,markerGlowRadiusScale:2,markerOffsetRadiusScale:0,markerRadiusScaleRange:[.005,.02],markerRenderer:null,markerTooltipRenderer:function(e){return JSON.stringify(e.coordinates)},markerType:"dot",pointLightColor:"white",pointLightIntensity:1,pointLightPositionRadiusScales:[-2,1,-1]};function b(){return(b=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e}).apply(this,arguments)}function k(e,t){var o=e[0]*Math.PI/180,n=(e[1]-180)*Math.PI/180;return[-t*Math.cos(o)*Math.cos(n),t*Math.sin(o),t*Math.cos(o)*Math.sin(n)]}function g(e,t){var o=b({},t);return Object.keys(o).forEach(function(t){var n=e[t];o[t]=void 0===n?o[t]:n}),o}function v(e){var t=e.to,o=e.animationDuration,a=e.easingFunction,i=e.onUpdate,r=e.onEnd,s=void 0===r?null:r,c=e.delay,u=void 0===c?0:c,l=a[0],d=a[1];new n.Tween(e.from).to(t,o).easing(n.Easing[l][d]).on("update",i).on("complete",s).delay(u).start()}var w=function(){function e(e){this.element=e,this.instance=l([e],{animation:"scale",arrow:!1})[0]}var t=e.prototype;return t.destroy=function(){this.instance.destroy()},t.hide=function(){document.body.style.cursor="inherit",this.element.style.position="fixed",this.element.style.left="0",this.element.style.top="0",this.instance.hide()},t.show=function(e,t,o){document.body.style.cursor="pointer",this.element.style.position="fixed",this.element.style.left=e+10+"px",this.element.style.top=t+10+"px",this.instance.setContent(o),this.instance.show()},e}(),M=function(){function e(e){var t,o,n,i=e.canvasElement,r=e.initialCameraDistanceRadiusScale,s=void 0===r?p.cameraDistanceRadiusScale:r,l=e.initialCoordinates,m=void 0===l?f:l,h=e.textures,b=void 0===h?{}:h,g=e.tooltipElement;this.callbacks=d,this.focus=null,this.isLocked=!1,this.markers=[],this.options=p,this.textures=b,this.previousFocus=null,this.tooltip=new w(g),this.renderer=new a.WebGLRenderer({alpha:!0,antialias:!0,canvas:i}),this.camera=function(e,t){var o=new a.PerspectiveCamera;o.name="camera",o.far=3e5,o.fov=45,o.near=1;var n=k(e,300*t);return o.position.set(n[0],n[1],n[2]),o}(m,s),this.earth=function(){var e=new a.Mesh;e.geometry=new a.SphereGeometry(300,50,50),e.name="earth";var t=new a.Mesh;t.geometry=new a.SphereGeometry(301,50,50),t.name="clouds";var o=new a.Mesh;return o.name="background",o.geometry=new a.SphereGeometry(3e4,50,50),{clouds:t,globe:e,background:o}}(),this.lights=(t=new a.AmbientLight("white"),o=new a.PointLight("white"),t.name="ambientLight",o.name="pointLight",{ambient:t,point:o}),this.markerObjects=((n=new a.Group).name="markers",n),this.orbitControls=new c.OrbitControls(this.camera,this.renderer.domElement),this.scene=function(e){var t=e.camera,o=e.earth,n=e.lights,i=e.markerObjects,r=e.renderer,s=e.defocus,c=new a.Scene;return t.add(n.ambient),t.add(n.point),c.add(t),c.add(o.globe),c.add(i),new u.Interaction(r,c,t),c.on("click",s),c}({camera:this.camera,earth:this.earth,lights:this.lights,markerObjects:this.markerObjects,renderer:this.renderer,defocus:this.defocus.bind(this)}),this.updateOptions(),this.updateCallbacks(),this.updateMarkers()}var t=e.prototype;return t.animate=function(){this.render(),this.animationFrameId=requestAnimationFrame(this.animate.bind(this))},t.animateClouds=function(){var e=this;["x","y","z"].forEach(function(t){e.earth.clouds.rotation[t]+=Math.random()/1e4})},t.applyAnimations=function(e){var t=this,o=0,n=[];return e.forEach(function(a,i){var r=a.coordinates,s=a.focusAnimationDuration,c={focusAnimationDuration:s,focusDistanceRadiusScale:a.focusDistanceRadiusScale,focusEasingFunction:a.focusEasingFunction},u=i===e.length-1,l=setTimeout(function(){t.unlock(),t.updateFocus(r,c,u)},o);n.push(l),o+=s}),function(){n.forEach(function(e){clearTimeout(e)})}},t.defocus=function(){!this.isLocked&&this.previousFocus&&this.options.enableDefocus&&(this.updateFocus(null),this.callbacks.onDefocus(this.previousFocus))},t.destroy=function(){cancelAnimationFrame(this.animationFrameId),this.tooltip.destroy(),this.renderer.domElement.remove()},t.lock=function(){this.isLocked=!0,this.orbitControls.enabled=!1,this.orbitControls.autoRotate=!1},t.render=function(){this.renderer.sortObjects=!1,this.renderer.render(this.scene,this.camera),this.orbitControls.update(),this.animateClouds(),n.update()},t.resize=function(e){var t=e.height,o=e.width;this.renderer.setSize(o,t),this.camera.aspect=o/t,this.camera.updateProjectionMatrix(),this.render()},t.saveFocus=function(e){this.previousFocus=e},t.unlock=function(){this.isLocked=!1,this.orbitControls.enabled=!0,this.orbitControls.autoRotate=!0},t.updateCallbacks=function(e){void 0===e&&(e={}),this.callbacks=g(e,d)},t.updateFocus=function(e,t,o){void 0===t&&(t={}),void 0===o&&(o=!0),this.isLocked||(this.focus=e,function(e,t,o){var n=o.options,a=o.previousFocus,i=o.shouldUnlockAfterFocus,r=o.lock,s=o.unlock,c=o.saveFocus,u=n.cameraDistanceRadiusScale,l=n.focusAnimationDuration,d=n.focusEasingFunction;if(e){var m=[t.position.x,t.position.y,t.position.z],h=k(e,300*n.focusDistanceRadiusScale);c(e),r(),v({from:m,to:h,animationDuration:l,easingFunction:d,onUpdate:function(){t.position.set(m[0],m[1],m[2])},onEnd:function(){i&&s()}})}else if(a){var f=[t.position.x,t.position.y,t.position.z],p=k(a,300*u);r(),v({from:f,to:p,animationDuration:l,easingFunction:d,onUpdate:function(){t.position.set(f[0],f[1],f[2])},onEnd:function(){c(null),s()}})}}(this.focus,this.camera,{shouldUnlockAfterFocus:o,options:g(t,this.options),previousFocus:this.previousFocus,lock:this.lock.bind(this),unlock:this.unlock.bind(this),saveFocus:this.saveFocus.bind(this)}))},t.updateMarkers=function(e){var t=this;void 0===e&&(e=[]),this.markers=e,function(e,t){var o=t.callbacks,n=t.markers,i=t.options,c=i.markerExitAnimationDuration,u=i.markerExitEasingFunction,l=i.markerRadiusScaleRange,d=n.map(function(e){return e.value}),m=new Set(n.map(function(e){return e.id})),h=l[0],f=l[1],p=s.scaleLinear().domain([Math.min.apply(null,d),Math.max.apply(null,d)]).range([300*h,300*f]);n.forEach(function(t){var o=t.id,n=p(t.value),s=e.children.find(function(e){return e.marker.id===t.id});s||((s=function(e,t,o){var n,i,s=t.enableMarkerGlow,c=t.markerEnterAnimationDuration,u=t.markerEnterEasingFunction,l=t.markerGlowCoefficient,d=t.markerGlowPower,m=t.markerGlowRadiusScale,h=t.markerOffsetRadiusScale,f=t.markerRenderer,p=t.markerType;if(f)i=f(e);else{var b=e.color||"gold",g={size:0},w={size:o},M=new a.Mesh;v({from:g,to:w,animationDuration:c,easingFunction:u,onUpdate:function(){switch(p){case"bar":M.geometry=new a.BoxGeometry(3,3,g.size),M.material=new a.MeshLambertMaterial({color:b});break;case"dot":default:if(M.geometry=new a.SphereGeometry(g.size,10,10),M.material=new a.MeshBasicMaterial({color:b}),s){var e=r.createGlowMesh(M.geometry,{backside:!1,coefficient:l,color:b,power:d,size:g.size*m});M.children=[],M.add(e)}}}}),i=M}var x=k(e.coordinates,300+(h?300*h:"dot"===p?o*(1+m)/2:0));return(n=i.position).set.apply(n,x),i.lookAt(new a.Vector3(0,0,0)),i.name=e.id,i}(t,i,n)).name=o,e.add(s)),s.marker=t}),e.children.forEach(function(t){if(!m.has(t.marker.id)){var n=t.scale.toArray();v({from:n,to:[0,0,0],animationDuration:c,easingFunction:u,onUpdate:function(){var e;t&&(e=t.scale).set.apply(e,n)},onEnd:function(){e.remove(t)}})}!function(e,t){var o=e.marker;e._listeners={},e.on("click",function(n){t.onClickMarker(o,e,n.data.originalEvent)}),e.on("mousemove",function(n){t.onMouseOverMarker(o,e,n.data.originalEvent)}),e.on("mouseout",function(n){t.onMouseOutMarker(o,e,n.data.originalEvent)})}(t,o)})}(this.markerObjects,{options:this.options,markers:e,callbacks:{onClickMarker:function(e,o,n){t.updateFocus(e.coordinates),t.callbacks.onClickMarker(e,o,n)},onMouseOutMarker:function(e,o,n){t.tooltip.hide(),t.callbacks.onMouseOutMarker(e,o,n)},onMouseOverMarker:function(e,o,n){t.options.enableMarkerTooltip&&t.tooltip.show(n.clientX,n.clientY,t.options.markerTooltipRenderer(o.marker)),t.callbacks.onMouseOverMarker(e,o,n)}}})},t.updateOptions=function(e){void 0===e&&(e={}),this.options=g(e,p),function(e,t){var o=t.callbacks,n=t.options,i=t.textures,s=n.globeCloudsOpacity,c=o.onGlobeBackgroundTextureLoaded,u=o.onGlobeCloudsTextureLoaded,l=o.onGlobeTextureLoaded,d=i.globeBackgroundTexture,f=void 0===d?"https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/background.png":d,p=i.globeCloudsTexture,b=void 0===p?m:p,k=i.globeTexture,g=void 0===k?h:k,v=e.clouds,w=e.globe,M=e.glow,x=e.background;n.enableGlobeGlow&&((M=r.createGlowMesh(w.geometry,{backside:!0,coefficient:n.globeGlowCoefficient,color:n.globeGlowColor,power:n.globeGlowPower,size:300*n.globeGlowRadiusScale})).name="glow"),g&&(new a.TextureLoader).load(g,function(e){w.material=new a.MeshLambertMaterial({map:e}),w.remove(w.getObjectByName("glow")),w.add(M),l()},function(){},l),f&&((new a.TextureLoader).load(f,function(e){x.material=new a.MeshBasicMaterial({map:e,side:a.BackSide}),c()},function(){},c),w.remove(w.getObjectByName("background")),w.add(x)),b&&((new a.TextureLoader).load(b,function(e){v.material=new a.MeshLambertMaterial({map:e,transparent:!0}),v.material.opacity=s,u()},function(){},u),w.remove(w.getObjectByName("clouds")),w.add(v))}(this.earth,{callbacks:this.callbacks,options:this.options,textures:this.textures}),function(e,t){var o=t.ambientLightIntensity,n=t.pointLightColor,i=t.pointLightIntensity,r=t.pointLightPositionRadiusScales,s=e.ambient,c=e.point,u=r[0],l=r[1],d=r[2];s.color=new a.Color(t.ambientLightColor),s.intensity=o,c.color=new a.Color(n),c.intensity=i,c.position.set(300*u,300*l,300*d)}(this.lights,this.options),function(e,t){var o=t.cameraAutoRotateSpeed,n=t.cameraMaxDistanceRadiusScale,a=t.cameraMaxPolarAngle,i=t.cameraMinPolarAngle,r=t.cameraRotateSpeed,s=t.cameraZoomSpeed,c=t.enableCameraRotate,u=t.enableCameraZoom;e.autoRotate=t.enableCameraAutoRotate,e.autoRotateSpeed=o,e.dampingFactor=.1,e.enableDamping=!0,e.enablePan=!1,e.enableRotate=c,e.enableZoom=u,e.maxDistance=300*n,e.maxPolarAngle=a,e.minDistance=330,e.minPolarAngle=i,e.rotateSpeed=r,e.zoomSpeed=s}(this.orbitControls,this.options),this.updateFocus.bind(this,this.focus),this.updateMarkers.bind(this,this.markers)},e}();exports.Globe=M,exports.default=function(e){var n=e.animations,a=void 0===n?[]:n,r=e.focus,s=e.height,c=void 0===s?"100%":s,u=e.globeBackgroundTexture,l=e.globeCloudsTexture,d=e.globeTexture,m=e.initialCameraDistanceRadiusScale,h=e.initialCoordinates,f=e.markers,b=e.options,k=void 0===b?p:b,g=e.width,v=void 0===g?"100%":g,w=e.onClickMarker,x=e.onDefocus,y=e.onGetGlobe,C=e.onGlobeBackgroundTextureLoaded,R=e.onGlobeCloudsTextureLoaded,G=e.onGlobeTextureLoaded,E=e.onMouseOutMarker,S=e.onMouseOverMarker,L=t.useRef(null),O=t.useRef(null),T=t.useRef(null),D=t.useRef(null);return t.useEffect(function(){var e=new M({canvasElement:L.current,initialCameraDistanceRadiusScale:m||k.cameraDistanceRadiusScale,initialCoordinates:h,textures:{globeBackgroundTexture:u,globeCloudsTexture:l,globeTexture:d},tooltipElement:T.current});return e.animate(),D.current=e,y&&y(e),function(){return e.destroy()}},[u,l,d,m,k.cameraDistanceRadiusScale,h,y]),t.useEffect(function(){var e,t,o,n=D.current;return e=O.current,t=n.resize.bind(n),(o=new i(function(e){if(e&&0!==e.length){var o=e[0].contentRect;t({height:o.height,width:o.width})}})).observe(e),function(){return o.unobserve(e)}},[]),t.useEffect(function(){D.current.updateCallbacks({onClickMarker:w,onDefocus:x,onGlobeBackgroundTextureLoaded:C,onGlobeCloudsTextureLoaded:R,onGlobeTextureLoaded:G,onMouseOutMarker:E,onMouseOverMarker:S})},[w,x,C,R,G,E,S]),t.useEffect(function(){D.current.updateOptions(k)},[k]),t.useEffect(function(){D.current.updateMarkers(f)},[f]),t.useEffect(function(){D.current.updateFocus(r)},[r]),t.useEffect(function(){return D.current.applyAnimations(a)},[a]),o.createElement("div",{ref:O,style:{height:c,width:v}},o.createElement("canvas",{ref:L}),o.createElement("div",{ref:T}))},exports.defaultBarMarkerOptions={enableMarkerGlow:!1,markerRadiusScaleRange:[.2,.5],markerType:"bar"},exports.defaultCallbacks=d,exports.defaultDotMarkerOptions={enableMarkerGlow:!0,markerRadiusScaleRange:[.005,.02],markerType:"dot"},exports.defaultGlobeBackgroundTexture="https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/background.png",exports.defaultGlobeCloudsTexture=m,exports.defaultGlobeTexture=h,exports.defaultInitialCoordinates=f,exports.defaultOptions=p,exports.tween=v;
//# sourceMappingURL=index.js.map