DEV Community

Cover image for Working with 3D globe in frontend
shrey vijayvargiya
shrey vijayvargiya

Posted on • Edited on

Working with 3D globe in frontend

Under the Hood

Yesterday when I wrote this blog, I stumbled upon react-globe.gl library for maps in the front end.

This simple library provides a 3D globe using Three.js under the hood.

If you are new to three.js, a library that works on canva HTML elements to provide 3D object rendering in the front end.

Once I found this library I couldn’t wait to create something stunning using react-glove.gl.

Project Idea

This makes sense, what does a globe show as the data?

The first idea that came to our mind was locating/marking the cities or countries.

So I collect the country's data along with latitude and longitude, we need latitude and longitude to mark the location on the map.

The Google Maps used by react-globe are rendered on an object known as a sphere using sphereGeometry mesh.

If you are new to these mesh and three.js objects, you can google out or watch the below YouTube playlist for a better understanding.

Go ahead and start your journey with 3d objects in front, this is so cool and fun 😄

Moving ahead, below is the sample list of props for markers on the google map.

const countries = [
 {
  latitude: "",
  longitude: "",
  country: "",
  name: ""
 }
]

Enter fullscreen mode Exit fullscreen mode

Rendering Globe

Once the data is collected, we will first render the globe or 3D map.

<Globe
    ref={globeEl}
    height={800}
    backgroundColor="rgba(0,0,0,0)"
    labelsData={COUNTRIES_DATA.map((item) => {
     return {
      lat: item.latitude,
      lng: item.longitude,
      name: item.name,
      country: item.country,
     };
    })}
    onLabelClick={({ lat, lng, name, country }) => {
     setActiveCountry({
      label: name,
      latitude: lat,
      longitude: lng,
      country,
     });
    }}
    atmosphereColor={colors.gray[800]}
    showAtmosphere={false}
    labelText={"name"}
    labelSize={1}
    labelColor={() => colors[labelTheme][200]}
    labelDotRadius={0.2}
    labelAltitude={0.05}
    arcColor={colors.orange[600]}
    hexPolygonsData={hex.features}
    hexPolygonResolution={3}
    hexPolygonMargin={0.62}
    hexPolygonColor={useCallback(() => colors.gray[800], [])}
   />
Enter fullscreen mode Exit fullscreen mode

You can see so many props in one go, do not worry as I’ll explain them one by one.

  • width: width of the globe
  • height: height of the globe
  • backgroundColour: The background colour of the globe
  • atmosphereColor: the colour of the glove atmosphere
  • showAtmosphere: boolean to show atmosphere or not
  • onLabelClick: Event handler when the label is clicked
  • label styling: such as label, text size, colour, dot radius and altitude
  • polygon styling: CSS for styling polygons used to cover the continents
  • arc styling: CSS for styling arc on the globe
  • path styling: CSS for styling and adding paths on the globe
  • ring styling: CSS for adding and styling rings on the globe

npm module

React globe renders on canva element and it requires the browser window object, basically rendering on the client side, so importing the above globe component in next.js or server-side won’t work. But don’t worry next.js has a solution for side effects and that is using dynamic importing.

Importing the components without ssr or once the client-side rendering is over, stop the server-side rendering of the corresponding component imported dynamically using the next dynamic module.

import dynamic from "next/dynamic";

const Globe = dynamic(import("./customGlobe"), { ssr:false });
Once this is done, our Globe is ready to render in the front end.

Enter fullscreen mode Exit fullscreen mode

Cool so far it looks good, you can extend the styling part via the props by using Tailwind CSS colours.

I prefer Tailwind every time and the main reason it’s because of its compatibility and it is accepted as the universal styling library.

Select & Mark Countries

We have the country data along with latitude and longitude.

What extra we can do is add a select component mentioning all the countries in the select dropdown.

As soon as the user selects the country, we will rotate to the globe using a globe reference pointer to the active country position.

const [active, setActive] = useState();

<Select data={countries.map(item) => ({ value: item.country, lable: itme.country })} 
  onChange={val => setActive(countries.filter(item => item === val)[0])}
/>
Enter fullscreen mode Exit fullscreen mode

In the custom globe components, we want to rotate the globe to the active country position and this can be done by passing the active country location object as the props and rotating the globe to the active country position.

const globeEl = useRef();

 useEffect(() => {
  const MAP_CENTER = { lat: 0, lng: 0, altitude: 1.5 };
  globeEl.current.pointOfView(MAP_CENTER, 0);
 }, [globeEl]);

 useEffect(() => {
  const countryLocation = {
   lat: activeCountry.latitude,
   lng: activeCountry.longitude,
   altitude: 1.5,
  };
  globeEl.current.pointOfView(countryLocation, 1000);
 }, [activeCountry]);
Enter fullscreen mode Exit fullscreen mode

Easy, within 10 lines of code our 3D globe is ready to rotate to the centre and even have markers to all the countries we have provided as the data.

A total of 200 lines of code are added along

  • Tailwind CSS styling
  • Methods to rotate the globe to the active country
  • Select the country from the dropdown
  • Dropdown styling
  • Dynamic importing of the custom globe
  • Adding country's data along with latitude and longitude and our 3D world map is ready!!

Feel free to subscribe to my newsletter, I share such interesting stories over email also along with news on Programming, Jobs, and AI that will be very helpful for you.

Subscribe to my FREE Newsletter

Until next time, have a good day
Shrey

Top comments (0)