Three-globe markers do not relocate accordingly while resizing the globe with the window

43 views Asked by At

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>

0

There are 0 answers