File: README.md
Quick Start
<canvas
id="cobe"
style="width: 500px; height: 500px;"
width="1000"
height="1000"
></canvas>import createGlobe from 'cobe'
let phi = 0
let canvas = document.getElementById("cobe")
const globe = createGlobe(canvas, {
devicePixelRatio: 2,
width: 1000,
height: 1000,
phi: 0,
theta: 0,
dark: 0,
diffuse: 1.2,
scale: 1,
mapSamples: 16000,
mapBrightness: 6,
baseColor: [0.3, 0.3, 0.3],
markerColor: [1, 0.5, 1],
glowColor: [1, 1, 1],
offset: [0, 0],
markers: [
{ location: [37.7595, -122.4367], size: 0.03 },
{ location: [40.7128, -74.006], size: 0.1, color: [1, 0, 0] }, // custom color
],
arcs: [
{
from: [37.7595, -122.4367],
to: [40.7128, -74.006],
color: [1, 0.5, 0.5], // custom color (optional)
},
],
arcColor: [1, 0.5, 1],
arcWidth: 0.5,
arcHeight: 0.3,
markerElevation: 0.02,
onRender: (state) => {
// Called on every animation frame.
// `state` will be an empty object, return updated params.
state.phi = phi
phi += 0.01
},
})
// To destroy the instance and bindings:
// `globe.destroy()`Arcs
Arcs connect two locations on the globe:
arcs: [
{
from: [37.7595, -122.4367],
to: [35.6762, 139.6503],
color: [1, 0.5, 0.5], // optional, uses arcColor if not set
},
]Bindable Markers & Arcs
Markers and arcs can have an id property for CSS Anchor Positioning:
markers: [
{ location: [37.7595, -122.4367], size: 0.03, id: 'sf' },
],
arcs: [
{ from: [37.7595, -122.4367], to: [35.6762, 139.6503], id: 'sf-tokyo' },
].marker-label {
position: absolute;
position-anchor: --cobe-sf;
bottom: anchor(top);
left: anchor(center);
opacity: var(--cobe-visible-sf, 0);
filter: blur(calc((1 - var(--cobe-visible-sf, 0)) * 8px));
transition: opacity 0.3s, filter 0.3s;
}
.arc-label {
position: absolute;
position-anchor: --cobe-arc-sf-tokyo;
bottom: anchor(top);
left: anchor(center);
opacity: var(--cobe-visible-arc-sf-tokyo, 0);
}The globe exposes:
--cobe-{id}/--cobe-arc-{id}โ CSS anchor names for positioning--cobe-visible-{id}/--cobe-visible-arc-{id}โ visibility variable (0 when behind globe, 1 when visible)
Use the visibility variable to drive opacity, blur, scale, or any CSS property for smooth transitions.
Acknowledgment
This project is inspired & based on the great work of:
- Spherical Fibonacci Mapping, Benjamin Keinert et al.
- https://www.shadertoy.com/view/lllXz4, Inigo Quilez
- https://github.blog/2020-12-21-how-we-built-the-github-globe
- https://github.com/vaneenige/phenomenon
- https://github.com/evanw/glslx
World map asset from:
License
The MIT License.
File: package.json
{
"name": "cobe",
"version": "2.0.1",
"type": "module",
"main": "./dist/index.esm.js",
"files": [
"dist/**"
],
"types": "./dist/index.d.ts",
"repository": "shuding/cobe",
"license": "MIT",
"scripts": {
"build": "node scripts/build.js && cp src/index.d.ts dist/index.d.ts",
"chrome:debug": "open -na "Google Chrome" --args --new-window --disable-frame-rate-limit --user-data-dir="/tmp/chrome_dev_session" --disable-web-security http://localhost:3000/playground"
},
"devDependencies": {
"esbuild": "^0.13.14",
"glslx": "^0.3.0",
"next": "^12.2.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"terser": "^5.46.0",
"typescript": "^4.5.4"
},
"packageManager": "[email protected]+sha512.1d61f8c10e8a5a5dbfbddea0f1f5efb7dbd5177223073aec953cf230aa46416884b9427a6421dba78f28ad0f93fbede38ba57083237b350243de6b1e3a8ce71d"
}
File: pnpm-workspace.yaml
packages:
- 'website'
File: tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"lib": ["ESNext", "DOM"],
"module": "CommonJS",
"moduleResolution": "Node",
"strict": true,
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"allowJs": true,
"declaration": true,
"sourceMap": true,
"outDir": "dist",
"rootDir": "src"
},
"exclude": ["dist", "node_modules", "scripts"]
}
File: website/package.json
{
"name": "cobe-site",
"version": "1.0.0",
"description": "",
"dependencies": {
"cobe": "workspace:*",
"geist": "^1.4.1",
"leva": "^0.9.34",
"next": "^16.1.6",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-spring": "^9.4.4",
"sugar-high": "^0.9.5"
},
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"typescript": "^5.0.0"
},
"scripts": {
"build": "next build",
"dev": "next dev",
"start": "next start"
},
"author": "Shu Ding [email protected]",
"license": "MIT"
}
File: website/tsconfig.json
{
"compilerOptions": {
"target": "ES2017",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"/*.ts",
"/.tsx",
".next/types/**/.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}