Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions examples/globe-view/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>COGLayer Globe View Example</title>
<style>
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
#root {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
31 changes: 31 additions & 0 deletions examples/globe-view/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "deck.gl-cog-globe-example",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@deck.gl/core": "^9.2.7",
"@deck.gl/geo-layers": "^9.2.7",
"@deck.gl/layers": "^9.2.7",
"@deck.gl/mesh-layers": "^9.2.7",
"@deck.gl/react": "^9.2.7",
"@developmentseed/geotiff": "workspace:^",
"@developmentseed/deck.gl-geotiff": "workspace:^",
"@developmentseed/deck.gl-raster": "workspace:^",
"@luma.gl/core": "9.2.6",
"@luma.gl/shadertools": "9.2.6",
"proj4": "^2.20.2",
"react": "^19.2.4",
"react-dom": "^19.2.4"
},
"devDependencies": {
"@types/react": "^19.2.10",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2",
"vite": "^7.3.1"
}
}
175 changes: 175 additions & 0 deletions examples/globe-view/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import { _GlobeView as GlobeView } from "@deck.gl/core";
import { GeoJsonLayer, SolidPolygonLayer } from "@deck.gl/layers";
import { DeckGL } from "@deck.gl/react";
import { COGLayer } from "@developmentseed/deck.gl-geotiff";
import { useCallback, useState } from "react";

// New Zealand imagery (NZTM2000 projection)
const COG_URL =
"https://nz-imagery.s3-ap-southeast-2.amazonaws.com/new-zealand/new-zealand_2024-2025_10m/rgb/2193/CC11.tiff";

// Antarctic sea ice (polar stereographic)
// const COG_URL =
// "https://data.source.coop/ausantarctic/ghrsst-mur-v2/2020/12/12/20201212090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1_sea_ice_fraction.tif";

export default function App() {
const [debug, setDebug] = useState(false);
const [debugOpacity, setDebugOpacity] = useState(0.25);

// Use initialViewState (uncontrolled) so deck.gl manages view state internally.
// Updating the object reference triggers deck.gl to transition to the new view.
const [initialViewState, setInitialViewState] = useState({
longitude: 0,
latitude: 0,
zoom: 1,
});

const onGeoTIFFLoad = useCallback(
(
_tiff: unknown,
options: {
geographicBounds: {
west: number;
south: number;
east: number;
north: number;
};
},
) => {
const { west, south, east, north } = options.geographicBounds;
const lonSpan = east - west;
const latSpan = north - south;
const maxSpan = Math.max(lonSpan, latSpan);
// At zoom N, ~360/2^N degrees are visible; subtract 1 for padding
const zoom = Math.log2(360 / maxSpan) - 1;
setInitialViewState({
longitude: (west + east) / 2,
latitude: (south + north) / 2,
zoom,
});
},
[],
);

const layers = [
// Dark background sphere
new SolidPolygonLayer({
id: "background",
data: [
[
[-180, 90],
[0, 90],
[180, 90],
[180, -90],
[0, -90],
[-180, -90],
],
],
getPolygon: (d) => d,
stroked: false,
filled: true,
getFillColor: [10, 20, 40],
}),
// Land masses basemap (Natural Earth via deck.gl CDN)
new GeoJsonLayer({
id: "basemap",
data: "https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_admin_0_scale_rank.geojson",
stroked: true,
filled: true,
lineWidthMinPixels: 1,
getLineColor: [40, 60, 90],
getFillColor: [25, 40, 70],
}),
new COGLayer({
id: "cog-layer",
geotiff: COG_URL,
debug,
debugOpacity,
onGeoTIFFLoad,
}),
];

return (
<div style={{ position: "relative", width: "100%", height: "100%" }}>
<DeckGL
views={new GlobeView()}
initialViewState={initialViewState}
controller={true}
layers={layers}
/>

{/* UI Controls */}
<div
style={{
position: "absolute",
top: "20px",
left: "20px",
background: "white",
padding: "16px",
borderRadius: "8px",
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
maxWidth: "300px",
zIndex: 1000,
}}
>
<h3 style={{ margin: "0 0 8px 0", fontSize: "16px" }}>
COGLayer Globe View
</h3>
<p style={{ margin: "0 0 12px 0", fontSize: "14px", color: "#666" }}>
Displaying COG imagery on a 3D globe
</p>

<div
style={{
padding: "12px 0",
borderTop: "1px solid #eee",
marginTop: "12px",
}}
>
<label
style={{
display: "flex",
alignItems: "center",
gap: "8px",
fontSize: "14px",
cursor: "pointer",
marginBottom: "12px",
}}
>
<input
type="checkbox"
checked={debug}
onChange={(e) => setDebug(e.target.checked)}
style={{ cursor: "pointer" }}
/>
<span>Show Debug Mesh</span>
</label>

{debug && (
<div style={{ marginTop: "8px" }}>
<label
style={{
display: "block",
fontSize: "12px",
color: "#666",
marginBottom: "4px",
}}
>
Debug Opacity: {debugOpacity.toFixed(2)}
<input
type="range"
min="0"
max="1"
step="0.01"
value={debugOpacity}
onChange={(e) => setDebugOpacity(parseFloat(e.target.value))}
style={{ width: "100%", cursor: "pointer" }}
/>
</label>
</div>
)}
</div>
</div>
</div>
);
}
9 changes: 9 additions & 0 deletions examples/globe-view/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>,
);
24 changes: 24 additions & 0 deletions examples/globe-view/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
10 changes: 10 additions & 0 deletions examples/globe-view/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
plugins: [react()],
base: "/deck.gl-raster/examples/globe-view/",
server: {
port: 3001,
},
});
Loading