https://github.com/jcubic/ascii-globe
Zero dependencies isomorphic ASCII-Art globe renderer in JavaScript
https://github.com/jcubic/ascii-globe
3d animation ascii ascii-art ascii-art-generator cartography globe
Last synced: about 1 month ago
JSON representation
Zero dependencies isomorphic ASCII-Art globe renderer in JavaScript
- Host: GitHub
- URL: https://github.com/jcubic/ascii-globe
- Owner: jcubic
- License: mit
- Created: 2026-05-01T12:55:50.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2026-05-24T08:56:22.000Z (about 1 month ago)
- Last Synced: 2026-05-24T10:26:34.306Z (about 1 month ago)
- Topics: 3d, animation, ascii, ascii-art, ascii-art-generator, cartography, globe
- Language: TypeScript
- Homepage:
- Size: 231 KB
- Stars: 4
- Watchers: 0
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-ascii - ascii-globe
README
# 
[](https://www.npmjs.com/package/ascii-globe)
[](https://github.com/jcubic/ascii-globe)

[](https://www.jsdelivr.com/package/npm/ascii-globe)
[](https://github.com/jcubic/ascii-globe/blob/master/LICENSE)
Zero dependencies isomorphic ASCII-Art globe renderer in JavaScript.
See [Live Demo](https://codepen.io/jcubic/full/EaNaRVp)
## Installation
### npm
```bash
npm install ascii-globe
```
### CDN
```html
import Globe from 'https://esm.run/ascii-globe';
```
## Usage
### ES Module (Node.js / Vite / bundlers)
```javascript
import Globe from 'ascii-globe';
const globe = new Globe({ size: 1.4 });
console.log(globe.render(90));
```
### CommonJS (Node.js)
```javascript
const Globe = require('ascii-globe');
const globe = new Globe({ size: 1.4 });
console.log(globe.render(90));
```
### Browser (script tag)
```html
var globe = new Globe({ size: 1 });
document.getElementById('output').textContent = globe.render(0);
```
### Browser (ES Module)
```html
import Globe from 'https://esm.run/ascii-globe';
const globe = new Globe({ size: 1 });
document.getElementById('output').textContent = globe.render(0);
```
## API
### `new Globe(options?)`
Creates a new globe instance.
| Option | Type | Default | Description |
|----------------|----------|---------|-----------------------------------------------------|
| `size` | `number` | `1.4` | Scale factor. `1` produces a 120x60 character grid. |
| `map` | `string` | — | Base64-encoded map data. Defaults to the built-in Earth map. |
| `land` | `string` | `'#'` | Character used to render land masses. |
| `water` | `string` | `'-'` | Character used to render water/ocean. |
| `background` | `string` | `' '` | Character used for the area outside the globe disk. |
| `margin` | `number` | `0` | Number of characters around the globe disk. |
| `marginBlock` | `number` | `0` | Vertical margin (overrides `margin`). |
| `marginInline` | `number` | `0` | Horizontal margin (overrides `margin`). |
| `pin` | `string` | `'@'` | Default character for location pins. Can include ANSI escape codes. |
| `pinSize` | `number` | `1` | Default size multiplier for pin markers. |
| `pins` | `Pin[]` | `[]` | Array of pin locations. |
| `tilt` | `number` | `0` | Axial tilt in degrees (Earth's tilt is 23.5°). |
| `speed` | `number` | `0.7` | Rotation speed in degrees per frame. |
| `format` | `function` | — | Callback `(type, length) => string` for custom output (see below). |
#### Pin object
| Property | Type | Required | Description |
|----------|----------|----------|--------------------------------------------------------------------|
| `lat` | `number` | yes | Latitude in degrees (-90 to 90). |
| `long` | `number` | yes | Longitude in degrees (-180 to 180). |
| `char` | `string` | no | Override character for this pin. Can include ANSI escape codes. |
| `size` | `number` | no | Size multiplier for this pin (overrides `pinSize`). |
#### `format(type, length)`
When provided, `render()` calls this function for each run of consecutive cells of the same type instead of using the `land`/`water`/`background`/`pin` characters. This lets you wrap output in HTML tags, ANSI codes, or any other markup.
| Type value | Meaning |
|------------|------------|
| `0` | Background |
| `1` | Water |
| `2` | Land |
| `3+` | Pin (index `type - 3` in the `pins` array) |
Example — HTML colored output:
```javascript
const globe = new Globe({
size: 1,
pins: [{ lat: 52.23, long: 21.01 }],
format(type, length) {
const chars = [' ', ' ', '#', '@'];
const colors = ['', '', 'green', 'red'];
const text = chars[type].repeat(length);
if (!colors[type]) return text;
return `${text}`;
}
});
pre.innerHTML = globe.render(250);
```
#### Custom maps
The library ships with an Earth map by default, but you can use a different map by passing
the `map` option. The package includes a built-in Death Star map:
```javascript
import Globe from 'ascii-globe';
import deathStar from 'ascii-globe/maps/death-star';
const globe = new Globe({ map: deathStar, land: '#', water: ' ' });
console.log(globe.render(0));
```
With a script tag (no modules), load the map as a separate script. The load order doesn't matter:
```html
var globe = new Globe({ map: Globe.maps['death-star'], land: '#', water: ' ' });
document.getElementById('output').textContent = globe.render(0);
```
You can also generate your own map data from any equirectangular projection image
(see [Generating custom map data](#generating-custom-map-data) below).
### `globe.render(rotation)`
Returns a string with the ASCII globe rendered at the given rotation.
- `rotation` — a single number (horizontal angle in degrees) or a `[horizontal, vertical]` pair. Values wrap around automatically.
```javascript
globe.render(90); // horizontal rotation only
globe.render([90, 30]); // horizontal + vertical tilt
```
## CLI
```bash
npx ascii-globe --rotation 200
npx ascii-globe --animate
```
Or install globally:
```bash
npm install -g ascii-globe
globe --rotation 200
globe --animate
```
```
ASCII Globe v0.4.2 - Isomorphic ASCII globe renderer
Usage: globe <--rotation | --animate> [options]
Options:
--rotation Rotation angle (single number or h,v pair)
--animate Animate the globe in the terminal
--size Globe size multiplier (default: 1.4)
--map Path to a map data file (generated by extract-texture)
--land Character for land (default: #)
--water Character for water (default: -)
--background Character for background (default: " ")
--margin Characters around the globe (default: 0)
--margin-block Vertical margin (overrides --margin)
--margin-inline Horizontal margin (overrides --margin)
--pin Character for location pins (default: @)
--pin-size Size of pin markers (default: 1)
--pins Pin locations as lat,long pairs separated by ;
--tilt Axial tilt in degrees (default: 0)
--speed Rotation speed in degrees per frame (default: 0.7)
--help Show this help message
-v, --version Show version number
Either --rotation or --animate is required.
```
Example with pins (Warsaw and New York):
```bash
globe --rotation 250 --pins '52.23,21.01;40.71,-74.01'
globe --rotation 250 --pin '\x1b[31m@\x1b[m' --pins '52.23,21.01'
```
Example with a custom map:
```bash
globe --rotation 40,20 --map ./my-map.js --land '#' --water ' '
```
## Examples
### Node.js terminal animation
```javascript
import Globe from 'ascii-globe';
const globe = new Globe({ size: 1, land: '#', water: ' ', tilt: 23.5 });
let rotation = 0;
process.stdout.write('\x1B[?25l'); // hide cursor
setInterval(() => {
process.stdout.write('\x1B[2J\x1B[H'); // clear + home
process.stdout.write(globe.render(rotation));
rotation = (rotation + globe.speed) % 360;
}, 1000 / 30);
```
Run the included example:
```bash
npm run example:node
```
### Browser animation
```html
Pause
var globe = new Globe({ size: 1, land: '#', water: ' ' });
var pre = document.getElementById('globe');
var playing = true;
var rotation = 0;
function loop() {
pre.textContent = globe.render(rotation);
if (playing) {
rotation = (rotation + 0.7) % 360;
requestAnimationFrame(loop);
}
}
document.getElementById('toggle').addEventListener('click', function() {
playing = !playing;
if (playing) loop();
});
loop();
```
Open `examples/browser/index.html` via a local server to run the included browser demo.
## Generating custom map data
You can generate map data from any equirectangular projection image (2:1 aspect ratio PNG).
The extract script is included in the repository:
```bash
npx tsx scripts/extract-texture.ts --output
```
Options:
| Flag | Description |
|----------------|----------------------------------------------------------|
| `--output ` | Output file path (default: `src/maps/.ts`) |
| `--grayscale` | Use brightness instead of Earth-specific color detection |
| `--alpha` | Use the alpha channel as the mask (opaque = land) |
| `--invert` | Invert the mask (swap land and water) |
The default mode classifies pixels using Earth-specific color heuristics (blue → water,
dark → land). Use `--grayscale` or `--alpha` for non-Earth images.
The output file can be imported and passed to the `map` option:
```javascript
import Globe from 'ascii-globe';
import myMap from './my-map.ts';
const globe = new Globe({ map: myMap });
```
Or used with the CLI:
```bash
globe --rotation 90 --map ./my-map.ts
```
## Building from source
```bash
npm install
npm run extract # generate src/maps/ from globe.png and death-star.png
npm run build # compile TypeScript to dist/
```
## Acknowledgments
World map texture by Ebrahim; [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0); source [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Equirectangular_projection_world_map_without_borders.svg).
## License
Copyright (c) 2025 [Jakub T. Jankiewicz](https://jakub.jankiewicz.org/)
Released under the MIT License. See [LICENSE](https://github.com/jcubic/ascii-globe/blob/master/LICENSE) for details.