vasturiano / globe.gl

UI component for Globe Data Visualization using ThreeJS/WebGL
https://vasturiano.github.io/globe.gl/example/world-population/
MIT License
1.97k stars 293 forks source link

Arc dash animation stops when labels are implemented #182

Open dangrunebaum opened 8 months ago

dangrunebaum commented 8 months ago

Describe the bug Arc dash animation halts when labels are implemented. (BTW thanks for your awesome library!)

To Reproduce

<script>
  import { getContext } from 'svelte'
  import { Html } from 'layercake'
  import Globe from 'globe.gl' //https://github.com/vasturiano/three-globe
  import { scalePow, scaleSequentialSqrt } from 'd3-scale'
  import connectionData from '../data/singapore-connections.csv'
  const { data, width, height } = getContext('LayerCake')

  let newData = []

  connectionData.forEach(d => {
    let startLat = +d.lat1
    let startLng = +d.long1
    let endLat = +d.lat2
    let endLng = +d.long2
    let count = +d.count
    let label = d.target
    let color = 'teal'
    newData.push({ startLat, startLng, endLat, endLng, count, label, color })
  })
  //   console.log(newData)

  let globeElm
  let world

  const powScale = scalePow().domain([0, 100]).range([0, 3]).exponent(0.5)

  const createGlobe = () => {
    if (globeElm) {
      world = Globe()
        // globe
        .globeImageUrl('./img-globe/color-version1.jpg')
        .bumpImageUrl('./img-globe/bump-map3.jpg')
        .backgroundColor('rgba(255,255,255,0)')
        .atmosphereColor('#222222')
        .atmosphereAltitude(0.01)(globeElm)
        .pointOfView({ lat: 1.29027, lng: 103.851959, altitude: 2 }) // aim at continental US centroid

        // arcs
        .arcsData(newData)
        .arcColor('color')
        .arcDashLength(0.9)
        .arcDashGap(0.01)
        .arcDashAnimateTime(4000)
        .arcStroke(d => powScale(d.count))
        .arcAltitude(d => (d.label === 'United States' || d.label === 'Iceland' || d.label === 'Canada' ? 0.35 : 0.15))
        .arcLabel(d => `${d.label}`)

        // labels
        .labelsData(newData)
        .labelLat(d => d.endLat)
        .labelLng(d => d.endLng)
        .labelText(d => d.label)
        .labelSize(1)
        .labelColor('black')

      // wait 1s for scene to be populated
      setTimeout(() => {
        // const ambientLight = scene.children.find(obj3d => obj3d.type === 'AmbientLight')

        // Controls
        const controls = world.controls()

        controls.enableZoom = false
        controls.enablePan = false
        controls.minDistance = 150
        controls.maxDistance = 250

        controls.rotateSpeed = 1
        controls.zoomSpeed = 0

        // controls.autoRotate = true
        controls.autoRotateSpeed = 1.0

        controls.minPolarAngle = Math.PI / 3.5
        controls.maxPolarAngle = Math.PI - Math.PI / 3

        // Material
        const globeMaterial = world.globeMaterial()
        globeMaterial.bumpScale = 12
        globeMaterial.transparent = true
        globeMaterial.opacity = 1

        const labelMaterial = world.scene()

        requestAnimationFrame(() =>
          (function animate() {
            requestAnimationFrame(animate)
          })()
        )
      }, 1000)
    }
  }

  const updateGlobe = () => {
    if (world) {
      world.width($width).height($height)
    }
  }

  $: globeElm, createGlobe()
  $: $width, $data, updateGlobe()
</script>

<Html>
  <div id="globe" bind:this={globeElm} style="width:{$width}px; height:{$height}px" />
</Html>

Expected behavior Labels are expected to coexist with arc animation.

Screenshots (https://github.com/dangrunebaum/dangrunebaum.github.io/blob/master/label-issue.mp4)

Desktop (please complete the following information):

vasturiano commented 7 months ago

@dangrunebaum thanks for reaching out.

The issue here is that you're passing the same data object to two different layers. I.e. newData is being passed to the arcs and labels layer.

In order to avoid conflicts between the two layers it's better if you clone each of your data objects and pass them as separate items.

dangrunebaum commented 7 months ago

Thanks that did the trick!

dangrunebaum commented 7 months ago

And by the way, do you happen to know of any other globe images aside from the ones on Natural Earth? Specifically, I'm looking for one that simply shows oceans and land masses in different colors (e.g. blue for oceans, gray for land)?

vasturiano commented 7 months ago

@dangrunebaum NASA has a Blue Marble collection that might have something like that: https://visibleearth.nasa.gov/collection/1484/blue-marble

dangrunebaum commented 7 months ago

@vasturiano Thanks, very helpful!