GitHub Globe Clone using Three.js
GitHub is where the world builds software. More than 56 million developers around the world build and work together on GitHub. With a new homepage, they wanted to show how open-source development transcends the borders they're living in and tell our product story through the lens of a developer’s journey.
Creating a GitHub Globe using three.js is a great way to visualize and explore the repositories on GitHub in a 3D environment. In this project, we'll walk you through the process of building a GitHub Globe from scratch.
GeoJSON
GeoJSON is a format for encoding a variety of geographic data structures. It is based on JavaScript Object Notation (JSON), a lightweight data interchange format, and is used to represent spatial features such as points, lines, and polygons, as well as their properties.
GeoJSON is a widely used format for storing and exchanging spatial data, and is supported by many software libraries, web APIs, and geospatial databases. It is especially popular in the context of web mapping and web services, where it is used to transfer data between the server and client.
GeoJSON data consists of a collection of features, each of which has a geometry (such as a point, line, or polygon) and a set of properties. The geometry is defined using longitude and latitude coordinates, and can be represented in various projections. The properties are a set of key-value pairs that describe the feature, and can include any information that is relevant to the feature.
Overall, GeoJSON is a simple and flexible format for storing and exchanging geographic data, and is widely used in the geospatial community.
You can download GeoJSON from here.
We aim at maintaining 60 FPS while rendering as beautiful a globe as we can, but finding that balance is tricky—there are thousands of devices out there, all performing differently depending on the browser they’re running and their mood. We constantly monitor the achieved FPS, and if we fail to maintain 55.5 FPS over the last 50 frames we start to degrade the quality of the scene.
Step 1: Set up a basic three.js scene
Before we can start rendering a globe, we need to set up a basic three.js scene. This involves creating a canvas element in our HTML file and initializing a camera, renderer, and scene in our JavaScript file.
Step 2: Render a globe
At the most fundamental level, the globe runs in a WebGL context powered by three.js. We feed it data of recent pull requests that have been created and merged around the world through a JSON file. The scene is made up of five layers: a halo, a globe, the Earth’s regions, blue spikes for open pull requests, and pink arcs for merged pull requests. We don’t use any textures: we point four lights at a sphere, use about 12,000 five-sided circles to render the Earth’s regions, and draw a halo with a simple custom shader on the backside of a sphere.
Step 3: Adding Data or Fetch repository data from the GitHub API
In this project I'm going to use a local JSON data in order to make the request so for that I'm going to create a new JSON file called maps.JSON
and lines.JSON
and you can add the following data over there or you can use the GitHub API to retrieve the location and language data for each repository. To do this, we'll need to create a personal access token to authenticate our API requests.
Once we have our access token, we can use the following code to fetch the repository data:
const accessToken = 'YOUR_ACCESS_TOKEN';
const baseUrl = 'https://api.github.com';
async function fetchRepositories() {
const response = await fetch(`${baseUrl}/repositories`, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return response.json();
}
const repositories = await fetchRepositories();
This code sends a GET request to the "/repositories" endpoint of the GitHub API, using our access token to authenticate the request. It then parses the response as JSON and stores it in the "repositories" variable.
Step 4: Plot the repository data on the globe
Now that we have our repository data, we can use the latitude and longitude data to position the repository markers on the globe.
three-globe
three-globe is a library for creating 3D globes with three.js, a powerful JavaScript library for creating 3D graphics and animations on the web.
With three-globe, you can easily create interactive globes that can be rotated, zoomed, and clicked or tapped on to display data. The library comes with several built-in features, such as markers, lines, labels, and gradients, that allow you to add visual elements to your globe.
To use three-globe, you'll need to have three.js installed and set up in your project. You can then install three-globe using npm or yarn:
npm install three-globe
yarn add three-globe
Once you have three-globe installed, you can import it into your project and use it to create a new globe instance:
import Globe from 'three-globe';
const globe = new Globe();
From there, you can use the various methods and properties of the Globe object to customize and interact with your globe. For example, you can use the "addMarker" method to add a marker to the globe, or the "setTime" method to change the globe's appearance based on a specific date.
Overall, three-globe is a useful tool for creating interactive 3D globes with three.js, and can save you a lot of time and effort when building globe-based visualizations.
Now we are creating a new Globe object using the ThreeGlobe constructor and setting some options for the globe.
Globe = new ThreeGlobe({
waitForGlobeReady: true,
animateIn: true,
})
The "waitForGlobeReady" option tells three-globe to wait until the globe has finished initializing before calling any other methods or rendering the globe.
The "animateIn" option tells three-globe to animate the globe as it appears on the screen, rather than showing it immediately.
We're going to add the "hexPolygonsData" method which is used to set the data for the hexagonal polygons that will be displayed on the globe. In this case, the data is passed as an argument to the method and is expected to be an array of features from a GeoJSON object.
Globe = new ThreeGlobe({
waitForGlobeReady: true,
animateIn: true,
})
.hexPolygonsData(countries.features)
.hexPolygonResolution(3)
.hexPolygonMargin(0.7)
.showAtmosphere(true)
.atmosphereColor("#3a228a")
.atmosphereAltitude(0.25)
The "hexPolygonResolution" method sets the resolution of the hexagonal polygons that will be displayed on the globe. A higher resolution will result in more detailed polygons, but will also require more processing power and may be slower to render.
The "hexPolygonMargin" method sets the margin around the hexagonal polygons. This can be used to adjust the spacing between the polygons and other elements on the globe.
The "showAtmosphere" method enables or disables the atmosphere effect, which is a semi-transparent layer that is rendered around the globe. In this case, the atmosphere is enabled by setting the parameter to "true".
The "atmosphereColor" method sets the color of the atmosphere effect. In this case, the color is set to "#3a228a", which is a deep purple color.
The "atmosphereAltitude" method sets the altitude of the atmosphere effect, which determines how far it extends from the surface of the globe. In this case, the altitude is set to 0.25.
Now we're going to create the "setTimeout" function to delay the execution of a callback function. The callback function uses the "arcsData" method of the Globe object to set the data for the arcs that will be displayed on the globe, and the "arcColor" method to set the color of the arcs based on the "status" property of the data.
setTimeout(() => {
Globe.arcsData(lines.pulls)
.arcColor((e) => {
return e.status ? "#9cff00" : "#FF4000";
})})
The "arcsData" method takes an array of data points as an argument and sets them as the data for the arcs. Each data point is expected to have a "latitude" and "longitude" property, which determine the starting and ending positions of the arc.
The "arcColor" method takes a callback function as an argument, which is called for each data point to determine the color of the arc. In this case, the callback function returns "#9cff00" (green) if the "status" property of the data point is "true", and "#FF4000" (red) if it is "false".
Globe.arcsData(lines.pulls)
.arcColor((e) => {
return e.status ? "#9cff00" : "#FF4000";
})
.arcAltitude((e) => {
return e.arcAlt;
})
.arcStroke((e) => {
return e.status ? 0.5 : 0.3;
})
.arcDashLength(0.9)
.arcDashGap(4)
.arcDashAnimateTime(1000)
.arcsTransitionDuration(1000)
.arcDashInitialGap((e) => e.order * 1)
.labelsData(map.maps)
.labelColor(() => "#ffcb21")
The "arcColor" method sets the color of the arcs based on a callback function that is called for each data point. In this case, the callback function returns "#9cff00" (green) if the "status" property of the data point is "true", and "#FF4000" (red) if it is "false".
The "arcAltitude" method sets the altitude of the arcs, which determines how far they extend from the surface of the globe. In this case, the altitude is determined by the "arcAlt" property of the data point.
The "arcStroke" method sets the width of the arcs. In this case, the width is determined by the "status" property of the data point, with a value of 0.5 for "true" and 0.3 for "false".
The "arcDashLength" method sets the length of the dashes that make up the arcs. The "arcDashGap" method sets the gap between the dashes. The "arcDashAnimateTime" method sets the time it takes for the dashes to animate from one end of the arc to the other.
The "arcsTransitionDuration" method sets the duration of the transition animation when the data for the arcs is updated.
The "arcDashInitialGap" method sets the initial gap between the first dash and the start of the arc. In this case, the gap is determined by the "order" property of the data point, multiplied by 1.
The "labelsData" method sets the data for the labels that will be displayed on the globe. In this case, the data is taken from the "maps" property of the "map" object.
The "labelColor" method sets the color of the labels. In this case, the color is set to "#ffcb21", which is a bright yellow color.
.labelDotRadius(0.3)
.labelSize((e) => e.size)
.labelText("city")
.labelResolution(6)
.labelAltitude(0.01)
.pointsData(map.maps)
.pointColor(() => "#ffffff")
.pointsMerge(true)
.pointAltitude(0.07)
.pointRadius(0.05);
The "labelDotRadius" method sets the radius of the dots that are displayed next to the labels. The "labelSize" method sets the size of the labels based on a callback function that is called for each data point. In this case, the size is determined by the "size" property of the data point.
The "labelText" method sets the property of the data point that will be used as the text for the labels. In this case, the "city" property will be used.
The "labelResolution" method sets the resolution of the labels, which determines how smoothly they are rendered. A higher resolution will result in smoother labels, but will also require more processing power and may be slower to render.
The "labelAltitude" method sets the altitude of the labels, which determines how far they extend from the surface of the globe.
The "pointsData" method sets the data for the points that will be displayed on the globe. In this case, the data is taken from the "maps" property of the "map" object.
The "pointColor" method sets the color of the points. In this case, the color is set to "#ffffff" (white).
The "pointsMerge" method enables or disables the merging of points that are close together. When enabled, points that are close enough will be merged into a single point to avoid clutter.
The "pointAltitude" method sets the altitude of the points, which determines how far they extend from the surface of the globe.
The "pointRadius" method sets the radius of the points.
Conclusion
In conclusion, the github globe project is a powerful tool for visualizing data on a 3D globe using three.js. With the help of libraries like three-globe, it's easy to create interactive globes with markers, lines, labels, and gradients, and customize them with a wide range of options and features.
Whether you're building a visualization for a business, a research project, or just for fun, the github globe project is a great choice for creating engaging and informative 3D graphics on the web. Thanks to the power of three.js and the simplicity of three-globe, anyone can create beautiful and interactive globes with just a little bit of code. So, it is a very useful tool for the data visualization purpose.
Source Code
Reference:
- https://github.com/
- https://github.blog/2020-12-21-how-we-built-the-github-globe/
- https://github.blog/2020-12-21-visualizing-githubs-global-community/
- https://github.blog/2021-01-29-making-githubs-new-homepage-fast-and-performant/
- https://github.blog/2021-02-04-how-we-illustrate-at-github/
- https://github.blog/2021-02-11-how-we-designed-and-wrote-the-narrative-for-our-homepage/