0

I have written a html with javascript to create a globe and place some markers on it. wheeler+ctrl does zooming in/out. But, When resize the window, the globe resizes accordingly but not the markers.

What I need is, When resizing the window, the globe alongwith its markers must relocate according. How can I fix this issue?

I read this: https://github.com/vasturiano/three-globe

JSFiddle Sample here to run and see

The code :

<html>
  <head>
    <style>
      body {
        margin: 0;
        height: auto;
        width: 100vw;
        overflow: hidden;
      }

      #globeViz > div:nth-child(2),
      #globeViz > canvas {
        width: 100% !important;
        height: auto !important;
        min-height: 100% !important;
        aspect-ratio: auto 943 / 714 !important;
      }
    </style>

    <script src="https://unpkg.com/three"></script>
    <script src="https://unpkg.com/three-globe"></script>
  </head>

  <body>
    <div id="globeViz"></div>

    <script type="importmap">
      { "imports": { "three": "https://unpkg.com/three/build/three.module.js" } }
    </script>
    <script type="module">
      import { TrackballControls } from 'https://unpkg.com/three/examples/jsm/controls/TrackballControls.js';
      import { CSS2DRenderer } from 'https://unpkg.com/three/examples/jsm/renderers/CSS2DRenderer.js';
      Object.assign(THREE, { TrackballControls, CSS2DRenderer });

      // marker pin icon
      const markerSvg = `<svg viewBox="-4 0 36 36">
      <path fill="currentColor" d="M14,0 C21.732,0 28,5.641 28,12.6 C28,23.963 14,36 14,36 C14,36 0,24.064 0,12.6 C0,5.641 6.268,0 14,0 Z"></path>
      <circle fill="black" cx="14" cy="14" r="7"></circle>
    </svg>`;

      // Gen random data
      const N = 20;

      const arcsData = [...Array(N).keys()].map(() => ({
        startLat: (Math.random() - 0.5) * 180,
        startLng: (Math.random() - 0.5) * 360,
        endLat: (Math.random() - 0.5) * 180,
        endLng: (Math.random() - 0.5) * 360,
        color: ['red', 'white', 'blue', 'green'][Math.round(Math.random() * 3)],
      }));

      const gData = [...Array(N).keys()].map(() => ({
        lat: (Math.random() - 0.5) * 180,
        lng: (Math.random() - 0.5) * 360,
        size: 7 + Math.random() * 30,
        color: ['red', 'white', 'blue', 'green'][Math.round(Math.random() * 3)],
      }));

      console.log(arcsData);

      const Globe = new ThreeGlobe()
        .globeImageUrl('https://unpkg.com/three-globe/example/img/earth-night.jpg')
        .bumpImageUrl('https://unpkg.com/three-globe/example/img/earth-topology.png')
        .arcsData(arcsData)
        .arcColor('color')
        .arcDashLength(0.4)
        .arcDashGap(4)
        .arcCurveResolution(1000)
        .arcDashInitialGap(() => Math.random() * 5)
        .arcDashAnimateTime(1000)
        .htmlElementsData(gData)
        .htmlElement((d) => {
          const el = document.createElement('div');
          el.innerHTML = markerSvg;
          el.style.color = d.color;
          el.style.width = `${d.size}px`;
          el.style.display = el.style.zIndex > 12 ? 'block' : 'none';
          return el;
        });


      // Initital appearance of the globe set to Sri Lanka
      const lat = 7.8731; // Latitude of Sri Lanka
      const lon = 80.7718; // Longitude of Sri Lanka
      // Convert latitude and longitude to radians
      const latRad = THREE.MathUtils.degToRad(lat);
      const lonRad = THREE.MathUtils.degToRad(lon);
      // Set the initial rotation to focus on Sri Lanka
      Globe.rotation.x = latRad; // Rotate along the x-axis (latitude)
      Globe.rotation.y = -lonRad; // Rotate along the y-axis (longitude)
      Globe.rotation.z = 0; // No rotation along the z-axis

      // Setup renderer
      const renderers = [new THREE.WebGLRenderer({ alpha: true }), new THREE.CSS2DRenderer()];
      renderers.forEach((r, idx) => {
        r.setSize(window.innerWidth, window.innerHeight);
        if (idx > 0) {
          // overlay additional on top of main renderer
          r.domElement.style.position = 'absolute';
          r.domElement.style.top = '0px';
          r.domElement.style.pointerEvents = 'none';
        }
        document.getElementById('globeViz').appendChild(r.domElement);
      });

      // Setup scene
      const scene = new THREE.Scene();
      scene.add(Globe);
      scene.add(new THREE.AmbientLight(0xcccccc));
      scene.add(new THREE.DirectionalLight(0xffffff, 0.6));

      // Setup camera
      const camera = new THREE.PerspectiveCamera();
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      camera.position.z = 268; // Zoom level

      // Add camera controls
      const tbControls = new THREE.TrackballControls(camera, renderers[0].domElement);
      tbControls.minDistance = 101;
      tbControls.rotateSpeed = 5;
      tbControls.zoomSpeed = 0.8;
      tbControls.object.zoom = 2;
      tbControls.noZoom = true;

      // Update pov when camera moves
      Globe.setPointOfView(camera.position, Globe.position);
      tbControls.addEventListener('change', () => Globe.setPointOfView(camera.position, Globe.position));

      // Zoom in out listen ( mousewheel + ctrl)
      window.addEventListener(
        'mousewheel',
        (e) => {
          if (e.ctrlKey) {
            e.preventDefault();
            e.stopPropagation();
            if (e.wheelDelta > 0) {
              camera.position.z = camera.position.z + 10; // Zoom out
            } else {
              camera.position.z = camera.position.z - 10; // Zoom in
            }
          }
        },
        { passive: false }
      );


      // Kick-off renderer
      (function animate() {
        // IIFE
        // Frame cycle
        tbControls.update();
        renderers.forEach((r) => r.render(scene, camera));
        requestAnimationFrame(animate);
      })();
    </script>
  </body>
</html>

Udith Indrakantha
  • 860
  • 11
  • 17
  • I'm seeing warnings from threeJS - could you correct those (deprecated versions being used and multiple copies). Also try to boil your code down to a minimal example that still shows the error . Perhaps with just one point on the globe? And make the runnable snippet within your question, not on an external site which may disappear rendering your question useless to future readers. Please read: https://stackoverflow.com/help/minimal-reproducible-example – A Haworth May 30 '23 at 12:57

0 Answers0