For AI agents: a documentation index is available at /llms.txt. Markdown versions of all pages are available by appending .md to any URL.
Customize annotation pins and colors
This example shows how to customize the appearance of annotations on a 3D Gaussian splat model using custom colors, pin shapes, numbered step badges, and prioritized popup placement.
NPM module setup
npm install --save @maptiler/geosplats
import { SplatModel, Map, config } from "@maptiler/geosplats";
import "@maptiler/geosplats/dist/maptiler-geosplats.css";
config.apiKey = "YOUR_MAPTILER_API_KEY_HERE";
const map = new Map({
apiKey: config.apiKey,
container: "map",
center: [-80.27822, 25.74077],
zoom: 17.5,
pitch: 50,
bearing: -15,
});
let splatModel;
map.on("load", () => {
splatModel = new SplatModel({
model: "YOUR_MAPTILER_SPLAT_MODEL_ID_HERE",
revealParams: { enabled: true },
});
map.addSplatModel(splatModel);
});
map.on("splatmodel:load", () => {
// 1. Single character label creates a round circular badge (ideal for numbered tours)
splatModel.addAnnotation({
pos: { x: -0.06, z: -0.26 },
label: "1",
color: "#3174ff",
popup: "<h3>Tour Stop 1</h3><p>Main hotel lobby and reception.</p>",
});
splatModel.addAnnotation({
pos: { x: -0.4, z: -0.2 },
label: "2",
color: "#2bb673",
popup: "<h3>Tour Stop 2</h3><p>Outdoor heated swimming pool and terrace.</p>",
});
// 2. Icon-only round pin: an emoji without label text
splatModel.addAnnotation({
pos: { x: 0.1, z: 0.2 },
icon: "π",
color: [77, 77, 77],
popup: "<h3>Valet Parking</h3><p>Underground secure parking garage.</p>",
});
// 3. Hex color and customized popup placement preference
splatModel.addAnnotation({
pos: { x: -0.6, z: 0.5 },
icon: "β³",
label: "Golf Course",
color: "#e69439",
popupPlacement: ["top", "bottom", "right", "left"],
popup: "<h3>Golf Course</h3><p>18-hole championship green.</p>",
});
// 4. Color defined as an RGB object
splatModel.addAnnotation({
pos: { x: 0.35, z: -0.25 },
icon: "π",
label: "Luxury Spa",
color: { r: 180, g: 60, b: 180 },
popupPlacement: ["left", "right"],
popup: "<h3>Luxury Spa</h3><p>Full wellness, massage, and sauna treatments.</p>",
});
// 5. Named color
splatModel.addAnnotation({
pos: { x: 0.6, z: 0.46 },
icon: "πΎ",
label: "Tennis Club",
color: "red",
popup: "<h3>Tennis Club</h3><p>10 floodlit championship courts.</p>",
});
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="robots" content="noindex" />
<title>Customize annotation pins and colors</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div id="map"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
body {
font-family: Inter, sans-serif;
margin: 0;
overflow: hidden;
}
#map {
width: 100%;
height: 100vh;
}
Pin geometry and sizing
The pin automatically adjusts its shape depending on the length of its content:
- Single character or emoji: Produces a circular pin. This layout is ideal for numbered tour sequences (
"1","2","3") or standalone icon symbols ("π","β³"). - Longer text: From three characters onward, the pin renders as a rounded rectangular badge with an arrow pointer centered on the coordinate.
- Active state collapsing: When a pin with a popup is clicked, it collapses into a compact circular pin displaying only its icon, preventing visual overlap with the popup card.
// Circular numbered tour pin
splatModel.addAnnotation({
pos: { x: -0.06, z: -0.26 },
label: "1",
color: "#3174ff",
});
// Icon-only circular pin
splatModel.addAnnotation({
pos: { x: 0.1, z: 0.2 },
icon: "π",
color: [77, 77, 77],
});
Color formats and categorization
The color property configures the pin background fill color (the white label text and white border remain consistent). It accepts:
- Hexadecimal strings:
#RGB,#RGBA,#RRGGBB,#RRGGBBAA(e.g."#e69439"). - RGB arrays:
[r, g, b]or[r, g, b, a]with components from0to255(and alpha from0to1). - RGB objects:
{ r, g, b, a? }with numerical values. - Supported named colors:
"black","white","red","green","blue","yellow","magenta","cyan", and"transparent".
const CATEGORY_COLORS = {
leisure: "#2bb673",
dining: "#e69439",
services: "#3174ff",
};
splatModel.addAnnotation({
pos: { x: -0.4, z: -0.2 },
icon: "ποΈ",
label: "Pool",
color: CATEGORY_COLORS.leisure,
});
Controlling popup placement
Use popupPlacement to define an ordered list of preferred sides where the popup can open relative to the pin:
- Available values:
"top","bottom","left", and"right". - Every frame, the SDK selects the first side with sufficient screen clearance on the map.
- If none of the sides have sufficient space, the side with the most available room is chosen.
// Prefer opening above or below, falling back to sides
splatModel.addAnnotation({
pos: { x: -0.6, z: 0.5 },
label: "Golf Course",
popup: "<h3>Golf Course</h3><p>Championship green.</p>",
popupPlacement: ["top", "bottom", "right", "left"],
});
Learn more
Check out the MapTiler GeoSplats SDK reference for full documentation on AnnotationOptions, AnnotationPopupPlacement, and Color.
Related examples
Model vs geographic positioning
ExamplesPlace annotations using model-relative bounding box coordinates or geographic coordinates.
Rich HTML popups
ExamplesDisplay custom HTML cards in annotation popups with images, tables, and custom widths.
Capture events
ExamplesLearn how to capture both global map events and specific splats events like load, update, mouseover, and click.