Skip to content

Commit

Permalink
Add PMTiles and Three.js demo
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscorn committed Nov 29, 2024
1 parent 6978e97 commit 6d0816a
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 127 deletions.
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svelte-maplibre-gl",
"version": "0.0.9",
"version": "0.0.10",
"license": "(MIT OR Apache-2.0)",
"description": "Svelte library for using MapLibre GL JS as reactive components",
"repository": {
Expand Down Expand Up @@ -54,10 +54,11 @@
"@sveltejs/adapter-auto": "^3.3.1",
"@sveltejs/kit": "^2.8.5",
"@sveltejs/package": "^2.3.7",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.2",
"@tailwindcss/typography": "^0.5.15",
"@types/eslint": "^9.6.1",
"@types/geojson": "^7946.0.14",
"@types/three": "^0.170.0",
"autoprefixer": "^10.4.20",
"bits-ui": "1.0.0-next.64",
"clsx": "^2.1.1",
Expand All @@ -75,13 +76,14 @@
"prettier-plugin-svelte": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"publint": "^0.2.12",
"shiki": "^1.23.1",
"svelte": "^5.2.9",
"shiki": "^1.24.0",
"svelte": "^5.2.10",
"svelte-check": "^4.1.0",
"tailwind-merge": "^2.5.5",
"tailwind-variants": "^0.3.0",
"tailwindcss": "^3.4.15",
"tailwindcss-animate": "^1.0.7",
"three": "^0.170.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.16.0",
"vite": "^5.4.11",
Expand Down
276 changes: 162 additions & 114 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/content/CodeBlock.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
</script>

<div class="my-6 subpixel-antialiased">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{#if shiki}
{#await shiki then shiki}
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html shiki.codeToHtml(_content, { lang: 'svelte', theme: 'github-dark-default' })}
{/await}
{:else}
Expand Down
24 changes: 18 additions & 6 deletions src/content/examples/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,38 @@
'/examples/plain': 'Plain Map',
'/examples/complex': 'Complex',
'/examples/basestyle': 'Change Base Style',
'/examples/side-by-side': 'Side by Side',
'/examples/terrain': '3D Terrain',
'/examples/hover-styles': 'Hover Styles',
'/examples/terrain': '3D Terrain',
'/examples/clusters': 'Clusters',
'/examples/limit-interaction': 'Limit Map Interactions',
'/examples/dynamic-image': 'Dynamic Image',
'/examples/animate-images': 'Animate a Series of Images',
'/examples/video-on-a-map': 'Video on a Map',
'/examples/canvas-source': 'Canvas Source',
'/examples/image-loader': 'Load Images from URLs',
'/examples/fullscreen': 'Fullscreen',
'/examples/geolocate': 'Locate the User',
'/examples/image-loader': 'Load Images from URLs',
'/examples/canvas-source': 'Canvas Source'
}
},
{
title: 'Techniques',
items: {
'/examples/side-by-side': 'Side by Side'
}
},
{
title: 'Advanced',
items: {
'/examples/custom-control': 'Custom Control',
'/examples/custom-protocol': 'Custom Protocols',
'/examples/custom-layer': 'Custom Layer'
'/examples/custom-layer': 'Custom Layer',
'/examples/dynamic-image': 'Dynamic Image',
'/examples/threejs-model': '3D model with three.js'
}
},
{
title: 'Extensions',
items: {
'/examples/pmtiles': 'PMTiles Protocol',
'/examples/deckgl-overlay': 'deck.gl Overlay',
'/examples/contour': 'Contour Lines'
}
Expand Down
39 changes: 39 additions & 0 deletions src/content/examples/pmtiles/PMTiles.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script lang="ts">
import { MapLibre, PMTilesProtocol } from 'svelte-maplibre-gl';
import type { LayerSpecification } from 'maplibre-gl';
// Get the layers spec from the OSM style
let layers: LayerSpecification[] = $state.raw([]);
$effect(() => {
fetch('https://tile.openstreetmap.jp/styles/openmaptiles/style.json')
.then((response) => response.json())
.then((data) => {
layers = data['layers'].filter(
(layer: LayerSpecification) => !('source' in layer) || layer.source === 'openmaptiles'
);
});
});
</script>

<!-- Add pmtiles:// Protocol -->
<PMTilesProtocol />

<!-- Use custom protocols -->
<MapLibre
class="h-[55vh] min-h-[200px]"
zoom={3}
center={[138.0, 36.5]}
style={{
version: 8,
glyphs: 'https://tile.openstreetmap.jp/fonts/{fontstack}/{range}.pbf',
sprite: 'https://tile.openstreetmap.jp/styles/openmaptiles/sprite',
sources: {
openmaptiles: {
type: 'vector',
url: 'pmtiles://https://tile.openstreetmap.jp/static/planet.pmtiles',
attribution: '© OpenMapTiles © OpenStreetMap contributors'
}
},
layers
}}
></MapLibre>
14 changes: 14 additions & 0 deletions src/content/examples/pmtiles/content.svelte.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: PMTiles Protocol
description: Uses the PMTiles plugin and protocol to present a map.
---

<script lang="ts">
import Demo from "./PMTiles.svelte";
import demoRaw from "./PMTiles.svelte?raw";
import CodeBlock from "../../CodeBlock.svelte";
</script>

<Demo />

<CodeBlock content={demoRaw} />
78 changes: 78 additions & 0 deletions src/content/examples/threejs-model/CustomLayer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script lang="ts">
import { MapLibre, CustomLayer } from 'svelte-maplibre-gl';
import maplibregl from 'maplibre-gl';
import * as THREE from 'three';
import { Matrix4, Vector3 } from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
let map: maplibregl.Map | undefined = $state.raw();
const modelOrigin: [number, number] = [148.9819, -35.39847];
const modelAltitude = 0;
const modelRotate = [Math.PI / 2, 0, 0];
const modelAsMercatorCoordinate = maplibregl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude);
class CustomLayerImpl implements Omit<maplibregl.CustomLayerInterface, 'id' | 'type'> {
camera = new THREE.Camera();
scene = new THREE.Scene();
renderer: THREE.WebGLRenderer | null = null;
renderingMode = '3d' as const;
onAdd(map: maplibregl.Map, gl: WebGL2RenderingContext) {
// create two three.js lights
const directionalLight1 = new THREE.DirectionalLight(0xffffff);
directionalLight1.position.set(0, -70, 100).normalize();
this.scene.add(directionalLight1);
const directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(0, 70, 100).normalize();
this.scene.add(directionalLight2);
// load a glTF model
const loader = new GLTFLoader();
loader.load('https://maplibre.org/maplibre-gl-js/docs/assets/34M_17/34M_17.gltf', (gltf) => {
this.scene.add(gltf.scene);
});
// use the MapLibre GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map!.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
}
render(_gl: WebGL2RenderingContext | WebGLRenderingContext, options: maplibregl.CustomRenderMethodInput) {
const scale = modelAsMercatorCoordinate.meterInMercatorCoordinateUnits();
const world = new Matrix4().fromArray(options.defaultProjectionData.mainMatrix);
const local = new Matrix4()
.makeTranslation(modelAsMercatorCoordinate.x, modelAsMercatorCoordinate.y, modelAsMercatorCoordinate.z)
.scale(new Vector3(scale, -scale, scale))
.multiply(new Matrix4().makeRotationX(modelRotate[0]))
.multiply(new Matrix4().makeRotationY(modelRotate[1]))
.multiply(new Matrix4().makeRotationZ(modelRotate[2]));
this.camera.projectionMatrix = world.multiply(local);
this.renderer!.resetState();
this.renderer!.render(this.scene, this.camera);
map!.triggerRepaint();
}
}
const customLayerImpl = new CustomLayerImpl();
</script>

<MapLibre
bind:map
class="h-[55vh] min-h-[300px]"
style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
zoom={18}
pitch={60}
center={[148.9819, -35.3981]}
antialias
>
<CustomLayer implementation={customLayerImpl} />
</MapLibre>
15 changes: 15 additions & 0 deletions src/content/examples/threejs-model/content.svelte.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: 3D model with three.js
description: Use a custom style layer with three.js to add a 3D model to the map.
original: https://maplibre.org/maplibre-gl-js/docs/examples/add-3d-model/
---

<script lang="ts">
import Demo from "./CustomLayer.svelte";
import demoRaw from "./CustomLayer.svelte?raw";
import CodeBlock from "../../CodeBlock.svelte";
</script>

<Demo />

<CodeBlock content={demoRaw} />
2 changes: 1 addition & 1 deletion src/routes/components/[slug]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</p>

<div class="prose max-w-none dark:prose-invert">
<data.Content shiki={data.shiki} />
<data.Content />
</div>
</div>
<aside class="sticky top-24 h-[calc(100vh-6rem)]">
Expand Down
2 changes: 1 addition & 1 deletion src/routes/examples/[slug]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</p>

<div class="prose max-w-none dark:prose-invert">
<data.Content shiki={data.shiki} />
<data.Content />
</div>
</div>
<aside class="sticky top-24 h-[calc(100vh-6rem)]">
Expand Down

0 comments on commit 6d0816a

Please sign in to comment.