Categories Programming & Tech

Creating an Immersive 3D Weather Visualization with React Three Fiber


I’ve always been interested in data visualization using Three.js / R3F, and I thought a weather web app would be the perfect place to start. One of my favorite open-source libraries, @react-three/drei, already has a bunch of great tools like clouds, sky, and stars that fit perfectly into visualizing the weather in 3D.

This tutorial explores how to transform API data into a 3D experience, where we add a little flair and fun to weather visualization.

The Technology Stack

Our weather world is built on a foundation of some of my favorite technologies:

Weather Components

The heart of our visualization lies in conditionally showing a realistic sun, moon, and/or clouds based on the weather
results from your city or a city you search for, particles that simulate rain or snow, day/night logic, and some fun
lighting effects during a thunderstorm. We’ll start by building these weather components and then move on to displaying
them based on the results of the WeatherAPI call.

Sun + Moon Implementation

Let’s start simple: we’ll create a sun and moon component that’s just a sphere with a realistic texture wrapped
around it. We’ll also give it a little rotation and some lighting.

// Sun.js and Moon.js Component, a texture wrapped sphere
import React, { useRef } from 'react';
import { useFrame, useLoader } from '@react-three/fiber';
import { Sphere } from '@react-three/drei';
import * as THREE from 'three';

const Sun = () => {
  const sunRef = useRef();
  
  const sunTexture = useLoader(THREE.TextureLoader, '/textures/sun_2k.jpg');
  
  useFrame((state) => {
    if (sunRef.current) {
      sunRef.current.rotation.y = state.clock.getElapsedTime() * 0.1;
    }
  });

  const sunMaterial = new THREE.MeshBasicMaterial({
    map: sunTexture,
  });

  return (
    
      
      
      {/* Sun lighting */}
      
    
  );
};

export default Sun;

I grabbed the CC0 texture from here. The moon component is essentially the same; I used this image. The pointLight intensity is low because most of our lighting will come from the sky.