---
title: "How to find relative coordinates for annotations | Geosplats sdk"
description: "Find model-relative coordinates for annotations using an interactive keyboard target pin and bounding box."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# How to find relative coordinates for annotations

This example provides an interactive developer tool to find, calibrate, and copy model-relative annotation coordinates (`{ x, z, y }`) directly from any 3D Gaussian splat model.

**Controls:** Click inside the map and use your keyboard’s **Arrow keys** to move the target pin across the model (hold **Shift** for faster steps, **PageUp/PageDown** for height, and press **Enter** to copy coordinates). You can also click the 🎯 **Coordinate Finder** button in the top-left corner to open the on-screen panel.

### NPM module setup

```bash
npm install --save @maptiler/geosplats
```

#### main.js

```js
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: [3.16689, 39.76162],
  zoom: 19,
  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);
});

let pos = { x: 0, z: 0, y: 0 };
let targetPin;

function updateTargetUI() {
  const elX = document.getElementById("coordX");
  const elZ = document.getElementById("coordZ");
  const elY = document.getElementById("coordY");

  if (elX) elX.textContent = pos.x.toFixed(3);
  if (elZ) elZ.textContent = pos.z.toFixed(3);
  if (elY) elY.textContent = pos.y.toFixed(5);

  if (targetPin) {
    targetPin.setPosition(pos);
    targetPin.setLabel(`${pos.x.toFixed(2)}, ${pos.z.toFixed(2)}`);
  }
}

function getFormattedJSON() {
  const p = {
    x: +pos.x.toFixed(3),
    z: +pos.z.toFixed(3),
    ...(pos.y !== 0 ? { y: +pos.y.toFixed(6) } : {}),
  };
  return JSON.stringify(p);
}

// Collapsible toolbox toggle logic (starts collapsed)
const toolPanel = document.getElementById("toolPanel");
const panelToggle = document.getElementById("panelToggle");
if (panelToggle && toolPanel) {
  panelToggle.addEventListener("click", () => {
    toolPanel.classList.toggle("collapsed");
    panelToggle.setAttribute("aria-expanded", !toolPanel.classList.contains("collapsed"));
  });
}

map.on("splatmodel:load", () => {
  // 1. Enable visual yellow bounding box to see model volume
  splatModel.setBoundingBox(true, "yellow");

  // 2. Add reference markers along corners and edges
  const edgeMarkers = [
    { pos: { x: 1, z: 0 }, label: "+X (1, 0)" },
    { pos: { x: -1, z: 0 }, label: "-X (-1, 0)" },
    { pos: { x: 0, z: 1 }, label: "+Z (0, 1)" },
    { pos: { x: 0, z: -1 }, label: "-Z (0, -1)" },
    { pos: { x: 1, z: 1 }, label: "(1, 1)" },
    { pos: { x: -1, z: 1 }, label: "(-1, 1)" },
    { pos: { x: 1, z: -1 }, label: "(1, -1)" },
    { pos: { x: -1, z: -1 }, label: "(-1, -1)" },
  ];

  for (const m of edgeMarkers) {
    splatModel.addAnnotation({
      pos: m.pos,
      label: m.label,
      color: [100, 116, 139, 0.75],
    });
  }

  // 3. Create the interactive red target pin at { x: 0, z: 0, y: 0 }
  targetPin = splatModel.addAnnotation({
    pos,
    icon: "🎯",
    label: "0.00, 0.00",
    color: "#e63946",
    popup: `<h3>🎯 Target Pin</h3><p>Active pin for calibrating annotation coordinates.</p>`,
  });

  updateTargetUI();
});

// Auto-expand tool panel if user clicks the target pin directly
map.on("splatmodel:annotation:active", ({ annotation }) => {
  if (annotation === targetPin && toolPanel && toolPanel.classList.contains("collapsed")) {
    toolPanel.classList.remove("collapsed");
    panelToggle?.setAttribute("aria-expanded", "true");
  }
});

// Keyboard navigation listener
window.addEventListener("keydown", (e) => {
  const step = e.shiftKey ? 0.1 : 0.01;

  if (e.key === "ArrowRight") pos.x -= step;
  else if (e.key === "ArrowLeft") pos.x += step;
  else if (e.key === "ArrowUp") pos.z += step;
  else if (e.key === "ArrowDown") pos.z -= step;
  else if (e.key === "PageUp") pos.y += 0.00005;
  else if (e.key === "PageDown") pos.y -= 0.00005;
  else if (e.key === "Enter") {
    const jsonStr = getFormattedJSON();
    console.log("Copied annotation pos:", jsonStr);
    navigator.clipboard?.writeText(jsonStr);
    const btn = document.getElementById("copyBtn");
    if (btn) {
      btn.textContent = "Copied to Clipboard!";
      setTimeout(() => {
        btn.textContent = "Copy JSON Coordinate";
      }, 1500);
    }
    return;
  } else {
    return;
  }

  e.preventDefault();
  updateProbeUI();
});

// On-screen D-Pad buttons
document.getElementById("btnUp")?.addEventListener("click", () => {
  pos.z += 0.02;
  updateProbeUI();
});
document.getElementById("btnDown")?.addEventListener("click", () => {
  pos.z -= 0.02;
  updateProbeUI();
});
document.getElementById("btnLeft")?.addEventListener("click", () => {
  pos.x += 0.02;
  updateProbeUI();
});
document.getElementById("btnRight")?.addEventListener("click", () => {
  pos.x -= 0.02;
  updateProbeUI();
});
document.getElementById("btnCenter")?.addEventListener("click", () => {
  pos = { x: 0, z: 0, y: 0 };
  updateTargetUI();
});

// Copy button
document.getElementById("copyBtn")?.addEventListener("click", () => {
  const jsonStr = getFormattedJSON();
  console.log("Copied annotation pos:", jsonStr);
  navigator.clipboard?.writeText(jsonStr);
  const btn = document.getElementById("copyBtn");
  if (btn) {
    btn.textContent = "Copied to Clipboard!";
    setTimeout(() => {
      btn.textContent = "Copy JSON Coordinate";
    }, 1500);
  }
});
```

#### index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="robots" content="noindex" />
    <title>How to find relative coordinates for annotations</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div class="tool-panel collapsed" id="toolPanel">
      <div
        class="panel-header"
        id="panelToggle"
        role="button"
        aria-expanded="false"
        title="Toggle coordinate finder"
      >
        <div class="header-title">
          <span>🎯</span>
          <h3>Coordinate Finder</h3>
        </div>
        <button class="toggle-btn" id="toggleBtn" aria-label="Toggle panel">▲</button>
      </div>
      <div class="panel-content" id="panelContent">
        <div class="help-text">
          Use <strong>Arrow Keys</strong> to move the target pin.<br />
          Hold <strong>Shift</strong> for faster steps.<br />
          <strong>PageUp/Down</strong> for vertical height.
        </div>
        <div class="coord-display">
          <div><span>x:</span><span id="coordX">0.000</span></div>
          <div><span>z:</span><span id="coordZ">0.000</span></div>
          <div><span>y:</span><span id="coordY">0.00000</span></div>
        </div>
        <button class="btn-copy" id="copyBtn">Copy JSON Coordinate</button>
        <div class="dpad">
          <div></div>
          <button id="btnUp" title="Move North (-Z)">▲</button>
          <div></div>
          <button id="btnLeft" title="Move West (-X)">◀</button>
          <button id="btnCenter" title="Center (0,0)">•</button>
          <button id="btnRight" title="Move East (+X)">▶</button>
          <div></div>
          <button id="btnDown" title="Move South (+Z)">▼</button>
          <div></div>
        </div>
      </div>
    </div>
    <div id="map"></div>
    <script type="module" src="./main.js"></script>
  </body>
</html>
```

#### style.css

```css
body {
  font-family: Inter, sans-serif;
  margin: 0;
  overflow: hidden;
}

#map {
  width: 100%;
  height: 100vh;
}

.tool-panel {
  position: absolute;
  top: 12px;
  left: 12px;
  width: 250px;
  max-width: calc(100% - 24px);
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border-radius: 10px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
  z-index: 10;
  overflow: hidden;
  transition: box-shadow 0.25s ease;
  user-select: none;
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  cursor: pointer;
  background: transparent;
  transition: background 0.15s ease;
}

.panel-header:hover {
  background: rgba(0, 0, 0, 0.04);
}

.header-title {
  display: flex;
  align-items: center;
  gap: 6px;
}

.tool-panel h3 {
  font-size: 13.5px;
  font-weight: 700;
  margin: 0;
  color: #222;
  white-space: nowrap;
}

.toggle-btn {
  background: transparent;
  border: none;
  font-size: 10px;
  color: #666;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  cursor: pointer;
  transition: transform 0.25s ease;
}

.tool-panel.collapsed .toggle-btn {
  transform: rotate(180deg);
}

.panel-content {
  padding: 0 12px 12px 12px;
  max-height: 280px;
  overflow-y: auto;
  transition:
    max-height 0.25s ease,
    opacity 0.2s ease,
    padding 0.25s ease;
}

.tool-panel.collapsed .panel-content {
  max-height: 0;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  pointer-events: none;
}

.coord-display {
  background: #f1f5f9;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  padding: 8px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 12px;
  margin: 8px 0;
  color: #0f172a;
}

.coord-display div {
  display: flex;
  justify-content: space-between;
}

.help-text {
  font-size: 11px;
  color: #64748b;
  line-height: 1.4;
  margin-bottom: 8px;
}

.btn-copy {
  background: #e63946;
  color: #fff;
  border: none;
  width: 100%;
  padding: 6px 12px;
  border-radius: 6px;
  font-weight: 600;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.btn-copy:hover {
  background: #d62828;
}

.dpad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  margin-top: 8px;
}

.dpad button {
  background: #f8f9fa;
  border: 1px solid #ced4da;
  padding: 4px 0;
  font-size: 11px;
  font-weight: 600;
  border-radius: 4px;
  cursor: pointer;
}

.dpad button:hover {
  background: #e2e8f0;
}
```

### Basic JavaScript setup

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>How to find relative coordinates for annotations</title>
    <link
      rel="stylesheet"
      href="https://cdn.maptiler.com/maptiler-geosplats/v1.2.1/maptiler-geosplats.css"
    />
    <style>
      body {
        font-family: Inter, sans-serif;
        margin: 0;
        overflow: hidden;
      }

      #map {
        width: 100%;
        height: 100vh;
      }

      .tool-panel {
        position: absolute;
        top: 12px;
        left: 12px;
        width: 250px;
        max-width: calc(100% - 24px);
        background: rgba(255, 255, 255, 0.95);
        backdrop-filter: blur(8px);
        border-radius: 10px;
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
        z-index: 10;
        overflow: hidden;
        transition: box-shadow 0.25s ease;
        user-select: none;
      }

      .panel-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 10px 12px;
        cursor: pointer;
        background: transparent;
        transition: background 0.15s ease;
      }

      .panel-header:hover {
        background: rgba(0, 0, 0, 0.04);
      }

      .header-title {
        display: flex;
        align-items: center;
        gap: 6px;
      }

      .tool-panel h3 {
        font-size: 13.5px;
        font-weight: 700;
        margin: 0;
        color: #222;
        white-space: nowrap;
      }

      .toggle-btn {
        background: transparent;
        border: none;
        font-size: 10px;
        color: #666;
        width: 20px;
        height: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px;
        cursor: pointer;
        transition: transform 0.25s ease;
      }

      .tool-panel.collapsed .toggle-btn {
        transform: rotate(180deg);
      }

      .panel-content {
        padding: 0 12px 12px 12px;
        max-height: 280px;
        overflow-y: auto;
        transition:
          max-height 0.25s ease,
          opacity 0.2s ease,
          padding 0.25s ease;
      }

      .tool-panel.collapsed .panel-content {
        max-height: 0;
        opacity: 0;
        padding-top: 0;
        padding-bottom: 0;
        pointer-events: none;
      }

      .coord-display {
        background: #f1f5f9;
        border: 1px solid #cbd5e1;
        border-radius: 6px;
        padding: 8px 10px;
        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        font-size: 12px;
        margin: 8px 0;
        color: #0f172a;
      }

      .coord-display div {
        display: flex;
        justify-content: space-between;
      }

      .help-text {
        font-size: 11px;
        color: #64748b;
        line-height: 1.4;
        margin-bottom: 8px;
      }

      .btn-copy {
        background: #e63946;
        color: #fff;
        border: none;
        width: 100%;
        padding: 6px 12px;
        border-radius: 6px;
        font-weight: 600;
        font-size: 12px;
        cursor: pointer;
        transition: background 0.15s ease;
      }

      .btn-copy:hover {
        background: #d62828;
      }

      .dpad {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 4px;
        margin-top: 8px;
      }

      .dpad button {
        background: #f8f9fa;
        border: 1px solid #ced4da;
        padding: 4px 0;
        font-size: 11px;
        font-weight: 600;
        border-radius: 4px;
        cursor: pointer;
      }

      .dpad button:hover {
        background: #e2e8f0;
      }
    </style>
  </head>

  <body>
    <div class="tool-panel collapsed" id="toolPanel">
      <div
        class="panel-header"
        id="panelToggle"
        role="button"
        aria-expanded="false"
        title="Toggle coordinate finder"
      >
        <div class="header-title">
          <span>🎯</span>
          <h3>Coordinate Finder</h3>
        </div>
        <button class="toggle-btn" id="toggleBtn" aria-label="Toggle panel">▲</button>
      </div>
      <div class="panel-content" id="panelContent">
        <div class="help-text">
          Use <strong>Arrow Keys</strong> to move the target pin.<br />
          Hold <strong>Shift</strong> for faster steps.<br />
          <strong>PageUp/Down</strong> for vertical height.
        </div>
        <div class="coord-display">
          <div><span>x:</span><span id="coordX">0.000</span></div>
          <div><span>z:</span><span id="coordZ">0.000</span></div>
          <div><span>y:</span><span id="coordY">0.00000</span></div>
        </div>
        <button class="btn-copy" id="copyBtn">Copy JSON Coordinate</button>
        <div class="dpad">
          <div></div>
          <button id="btnUp" title="Move North (-Z)">▲</button>
          <div></div>
          <button id="btnLeft" title="Move West (-X)">◀</button>
          <button id="btnCenter" title="Center (0,0)">•</button>
          <button id="btnRight" title="Move East (+X)">▶</button>
          <div></div>
          <button id="btnDown" title="Move South (+Z)">▼</button>
          <div></div>
        </div>
      </div>
    </div>
    <div id="map"></div>
    <script type="module">
      import {
        SplatModel,
        Map,
        config,
      } from "https://cdn.maptiler.com/maptiler-geosplats/v1.2.1/maptiler-geosplats.mjs";

      config.apiKey = "YOUR_MAPTILER_API_KEY_HERE";

      const map = new Map({
        apiKey: config.apiKey,
        container: "map",
        center: [3.16689, 39.76162],
        zoom: 19,
        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);
      });

      let pos = { x: 0, z: 0, y: 0 };
      let targetPin;

      function updateTargetUI() {
        const elX = document.getElementById("coordX");
        const elZ = document.getElementById("coordZ");
        const elY = document.getElementById("coordY");

        if (elX) elX.textContent = pos.x.toFixed(3);
        if (elZ) elZ.textContent = pos.z.toFixed(3);
        if (elY) elY.textContent = pos.y.toFixed(5);

        if (targetPin) {
          targetPin.setPosition(pos);
          targetPin.setLabel(`${pos.x.toFixed(2)}, ${pos.z.toFixed(2)}`);
        }
      }

      function getFormattedJSON() {
        const p = {
          x: +pos.x.toFixed(3),
          z: +pos.z.toFixed(3),
          ...(pos.y !== 0 ? { y: +pos.y.toFixed(6) } : {}),
        };
        return JSON.stringify(p);
      }

      // Collapsible toolbox toggle logic (starts collapsed)
      const toolPanel = document.getElementById("toolPanel");
      const panelToggle = document.getElementById("panelToggle");
      panelToggle.addEventListener("click", () => {
        toolPanel.classList.toggle("collapsed");
        panelToggle.setAttribute("aria-expanded", !toolPanel.classList.contains("collapsed"));
      });

      map.on("splatmodel:load", () => {
        // 1. Enable visual yellow bounding box to see model volume
        splatModel.setBoundingBox(true, "yellow");

        // 2. Add reference markers along corners and edges
        const edgeMarkers = [
          { pos: { x: 1, z: 0 }, label: "+X (1, 0)" },
          { pos: { x: -1, z: 0 }, label: "-X (-1, 0)" },
          { pos: { x: 0, z: 1 }, label: "+Z (0, 1)" },
          { pos: { x: 0, z: -1 }, label: "-Z (0, -1)" },
          { pos: { x: 1, z: 1 }, label: "(1, 1)" },
          { pos: { x: -1, z: 1 }, label: "(-1, 1)" },
          { pos: { x: 1, z: -1 }, label: "(1, -1)" },
          { pos: { x: -1, z: -1 }, label: "(-1, -1)" },
        ];

        for (const m of edgeMarkers) {
          splatModel.addAnnotation({
            pos: m.pos,
            label: m.label,
            color: [100, 116, 139, 0.75],
          });
        }

        // 3. Create the interactive red target pin at { x: 0, z: 0, y: 0 }
        targetPin = splatModel.addAnnotation({
          pos,
          icon: "🎯",
          label: "0.00, 0.00",
          color: "#e63946",
          popup: `<h3>🎯 Target Pin</h3><p>Active pin for calibrating annotation coordinates.</p>`,
        });

        updateTargetUI();
      });

      // Auto-expand tool panel if user clicks the target pin directly
      map.on("splatmodel:annotation:active", ({ annotation }) => {
        if (annotation === targetPin && toolPanel.classList.contains("collapsed")) {
          toolPanel.classList.remove("collapsed");
          panelToggle.setAttribute("aria-expanded", "true");
        }
      });

      // Keyboard navigation listener
      window.addEventListener("keydown", (e) => {
        const step = e.shiftKey ? 0.1 : 0.01;

        if (e.key === "ArrowRight") pos.x -= step;
        else if (e.key === "ArrowLeft") pos.x += step;
        else if (e.key === "ArrowUp") pos.z += step;
        else if (e.key === "ArrowDown") pos.z -= step;
        else if (e.key === "PageUp") pos.y += 0.00005;
        else if (e.key === "PageDown") pos.y -= 0.00005;
        else if (e.key === "Enter") {
          const jsonStr = getFormattedJSON();
          console.log("Copied annotation pos:", jsonStr);
          navigator.clipboard?.writeText(jsonStr);
          const btn = document.getElementById("copyBtn");
          if (btn) {
            btn.textContent = "Copied to Clipboard!";
            setTimeout(() => {
              btn.textContent = "Copy JSON Coordinate";
            }, 1500);
          }
          return;
        } else {
          return;
        }

        e.preventDefault();
        updateTargetUI();
      });

      // On-screen D-Pad buttons
      document.getElementById("btnUp").addEventListener("click", () => {
        pos.z += 0.02;
        updateTargetUI();
      });
      document.getElementById("btnDown").addEventListener("click", () => {
        pos.z -= 0.02;
        updateTargetUI();
      });
      document.getElementById("btnLeft").addEventListener("click", () => {
        pos.x += 0.02;
        updateTargetUI();
      });
      document.getElementById("btnRight").addEventListener("click", () => {
        pos.x -= 0.02;
        updateTargetUI();
      });
      document.getElementById("btnCenter").addEventListener("click", () => {
        pos = { x: 0, z: 0, y: 0 };
        updateTargetUI();
      });

      // Copy button
      document.getElementById("copyBtn").addEventListener("click", () => {
        const jsonStr = getFormattedJSON();
        console.log("Copied annotation pos:", jsonStr);
        navigator.clipboard?.writeText(jsonStr);
        const btn = document.getElementById("copyBtn");
        btn.textContent = "Copied to Clipboard!";
        setTimeout(() => {
          btn.textContent = "Copy JSON Coordinate";
        }, 1500);
      });
    </script>
  </body>
</html>
```

## Why use model-relative coordinates

Model-relative coordinates (`pos: { x, z, y }`) are normalized to the 3D bounding box of the splat model:

-   `{ x: 0, z: 0 }`: Represents the exact horizontal center of the model.
-   `x` axis: Ranges from `-1.0` (western/left edge) to `+1.0` (eastern/right edge).
-   `z` axis: Ranges from `-1.0` (southern/front edge) to `+1.0` (northern/back edge).
-   `y`: Optional vertical height offset above the collision mesh or terrain.

Using model-relative coordinates ensures that pins stay perfectly attached to architectural features even if the model is rotated, dragged, or repositioned on the map.

## Enabling the model bounding box and corner pins

Visualizing the model’s bounding box and corner landmarks helps establish a reference grid:

```js
map.on("splatmodel:load", () => {
  // Show yellow 3D bounding box wireframe
  splatModel.setBoundingBox(true, "yellow");

  // Place reference markers on corner extremes
  const corners = [
    { pos: { x: 1, z: 1 }, label: "(1, 1)" },
    { pos: { x: -1, z: 1 }, label: "(-1, 1)" },
    { pos: { x: 1, z: -1 }, label: "(1, -1)" },
    { pos: { x: -1, z: -1 }, label: "(-1, -1)" },
  ];

  corners.forEach((c) => splatModel.addAnnotation(c));
});
```

## Navigating the interactive target pin

A target pin (`SplatAnnotation`) is placed at `{ x: 0, z: 0, y: 0 }`. Listening to keyboard events lets you nudge the pin in real time using `targetPin.setPosition(pos)`:

```js
let pos = { x: 0, z: 0, y: 0 };
let targetPin = splatModel.addAnnotation({
  pos,
  icon: "🎯",
  color: "#e63946",
});

window.addEventListener("keydown", (e) => {
  const step = e.shiftKey ? 0.1 : 0.01;

  if (e.key === "ArrowRight") pos.x -= step;
  else if (e.key === "ArrowLeft") pos.x += step;
  else if (e.key === "ArrowUp") pos.z += step;
  else if (e.key === "ArrowDown") pos.z -= step;
  else if (e.key === "PageUp") pos.y += 0.00005;
  else if (e.key === "PageDown") pos.y -= 0.00005;
  else return;

  e.preventDefault();
  targetPin.setPosition(pos);
  targetPin.setLabel(`${pos.x.toFixed(2)}, ${pos.z.toFixed(2)}`);
});
```

-   **Arrow keys**: Nudge the target pin horizontally by `0.01` units.
-   **Shift + Arrow keys**: Nudge the target pin by larger `0.1` steps.
-   **PageUp / PageDown**: Fine-tune vertical height `y` in world units.

## Copying coordinates into production code

Pressing **Enter** or clicking **Copy JSON Coordinate** formats the exact position into a JSON object ready to paste directly into your `splatModel.addAnnotation()` call:

```json
{ "x": 0.24, "z": -0.15 }
```

## Learn more

Check out the [MapTiler GeoSplats SDK reference](https://docs.maptiler.com/geosplats-sdk/api) to explore the full set of methods for `SplatAnnotation` and `SplatModel`.

## Related examples

### [Add annotations](https://docs.maptiler.com/geosplats-sdk/examples/add-annotations/)

Examples

Add interactive labelled pins and popups to a splat model.

### [Model vs geographic positioning](https://docs.maptiler.com/geosplats-sdk/examples/annotation-positioning/)

Examples

Place annotations using model-relative bounding box coordinates or geographic coordinates.

### [Pin styles and categories](https://docs.maptiler.com/geosplats-sdk/examples/annotation-styles/)

Examples

Style annotations with colors, icons, numbers, and custom popup placement.

### [Edit model in custom editor](https://docs.maptiler.com/geosplats-sdk/examples/custom-editor/)

Examples

Build a custom 3D editor to adjust the position, rotation, and scale of splat models and save their properties to a database.
