Rasterex APINPM Package/docs/components/measurement/tools

Tools

Activate length, area, count, snapping, and navigation fitting measurement actions.

Tool Activation

Measurement tools are activated programmatically using the tools API surface on the viewer instance.

Call the set method with the desired measurement action and await the promise resolution to ensure the Canvas has initialized drawing surfaces.

  • Ready State Requirement: Ensure the document is loaded and viewer.ready() has resolved before enabling measurement modes.
  • Promise Resolution: Navigation and tools APIs resolve as soon as Canvas confirms tool control setup.

Quick Examples

Activate measurement tools and customize behaviors using these examples:

Activate length measurement

await viewer.tools.set({
  action: "MEASURE_LENGTH",
  enabled: true
});

Toggle snap behavior

// Toggle snap ON to latch onto vector line endpoints
await viewer.tools.set({
  action: "SNAP",
  enabled: true
});

Clear active measurement tools

// Disable a specific tool action
await viewer.tools.set({
  action: "MEASURE_LENGTH",
  enabled: false
});

// Clear active tools and return to selection mode
viewer.tools.clear();

Supported Measurement Actions

Pass any of these action keys to viewer.tools.set:

  • `MEASURE_LENGTH`: Distance measurement between two selected points.
  • `MEASURE_AREA`: Region area measurement calculation.
  • `MEASURE_PATH`: Multi-segmented continuous distance tracking.
  • `MEASURE_ARC`: Three-point arc circumference and radius tracking.
  • `MEASURE_ANGLE_CCLOCKWISE`: Angular rotation measurement.
  • `MEASURE_RECTANGULAR_AREA`: Fast rectangle area calculation.
  • `COUNT`: Location count point markers.
  • `SNAP`: Vector snap override toggle.

Navigation Controls

Common viewport fitting operations are available on the navigation tools API surface:

typescript
// Fit document view to container width
await viewer.tools.navigation.set({
  action: "FIT_WIDTH",
  enabled: true
});
Navigation Controls

Vanilla Integration

Copy these project setup files to configure mounting, measurement buttons, and tool clearing:

import { createViewer } from "@rasterex/viewer";
import "./style.css";

const viewer = createViewer({
  container: "#viewer"
});

const statusEl = document.querySelector("#status");

function setStatus(message) {
  if (statusEl) statusEl.textContent = message;
}

async function startViewer() {
  await viewer.mount();
  await viewer.ready();
  
  await viewer.documents.open({
    url: "https://pdfobject.com/pdf/sample.pdf",
    displayName: "sample.pdf"
  });

  setStatus("Viewer ready");
}

async function enableTool(action) {
  setStatus(`Activating ${action}...`);
  try {
    const result = await viewer.tools.set({
      action,
      enabled: true
    });

    if (result.success) {
      setStatus(`${action} activated`);
    } else {
      setStatus(`Failed: ${result.error}`);
    }
  } catch (error) {
    setStatus("Tool activation error");
  }
}

async function fitWidth() {
  try {
    await viewer.tools.navigation.set({
      action: "FIT_WIDTH",
      enabled: true
    });
    setStatus("Fitted width");
  } catch (error) {
    setStatus("Failed to fit view");
  }
}

document.querySelectorAll("[data-action]").forEach((button) => {
  button.addEventListener("click", () => {
    enableTool(button.dataset.action).catch(console.error);
  });
});

document.querySelector("#fit-btn")?.addEventListener("click", () => {
  fitWidth().catch(console.error);
});

document.querySelector("#clear-btn")?.addEventListener("click", () => {
  viewer.tools.clear();
  setStatus("Tools cleared, selection mode active");
});

startViewer().catch(console.error);
Vanilla Integration

React Integration

Trigger length, area, snap, and fit-view actions inside a React component:

import { useEffect, useRef, useState } from "react";
import { createViewer, type RasterexViewer, type ToolAction } from "@rasterex/viewer";
import "./style.css";

const toolsList: Array<{ label: string; action: ToolAction }> = [
  { label: "Length", action: "MEASURE_LENGTH" },
  { label: "Area", action: "MEASURE_AREA" },
  { label: "Count", action: "COUNT" },
  { label: "Snap", action: "SNAP" }
];

export function MeasurementExample() {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const viewerRef = useRef<RasterexViewer | null>(null);
  const [activeTool, setActiveTool] = useState<ToolAction | null>(null);
  const [status, setStatus] = useState("Starting viewer...");

  useEffect(() => {
    if (!containerRef.current) return undefined;

    const viewer = createViewer({ container: containerRef.current });
    viewerRef.current = viewer;

    async function start(): Promise<void> {
      await viewer.mount();
      await viewer.ready();
      await viewer.documents.open({
        url: "https://pdfobject.com/pdf/sample.pdf",
        displayName: "sample.pdf"
      });
      setStatus("Viewer ready");
    }

    void start().catch(console.error);

    return () => {
      viewer.destroy();
      viewerRef.current = null;
    };
  }, []);

  async function activateTool(action: ToolAction): Promise<void> {
    setStatus(`Activating ${action}...`);
    const result = await viewerRef.current?.tools.set({
      action,
      enabled: true
    });

    if (result?.success) {
      setActiveTool(action);
      setStatus(`${action} activated`);
    } else {
      setStatus(`Failed: ${result?.error ?? "error"}`);
    }
  }

  async function fitWidth(): Promise<void> {
    await viewerRef.current?.tools.navigation.set({
      action: "FIT_WIDTH",
      enabled: true
    });
    setStatus("Fitted width");
  }

  function clearTools(): void {
    viewerRef.current?.tools.clear();
    setActiveTool(null);
    setStatus("Tools cleared, selection mode active");
  }

  return (
    <div>
      <div className="toolbar">
        {toolsList.map((tool) => (
          <button
            key={tool.action}
            type="button"
            aria-pressed={activeTool === tool.action}
            onClick={() => void activateTool(tool.action)}
          >
            {tool.label}
          </button>
        ))}
        <button type="button" onClick={() => void fitWidth()}>Fit Width</button>
        <button type="button" onClick={clearTools}>Clear tools</button>
      </div>
      <div ref={containerRef} style={{ height: 600 }} />
      <pre>{status}</pre>
    </div>
  );
}
React Integration

Vue Integration

Trigger length, area, snap, and fit-view actions inside a Vue composition component:

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, shallowRef } from "vue";
import { createViewer, type RasterexViewer, type ToolAction } from "@rasterex/viewer";
import "./style.css";

const containerRef = ref<HTMLElement | null>(null);
const viewerRef = shallowRef<RasterexViewer | null>(null);
const activeTool = ref<ToolAction | null>(null);
const status = ref("Starting viewer...");

const toolsList: Array<{ label: string; action: ToolAction }> = [
  { label: "Length", action: "MEASURE_LENGTH" },
  { label: "Area", action: "MEASURE_AREA" },
  { label: "Count", action: "COUNT" },
  { label: "Snap", action: "SNAP" }
];

onMounted(async () => {
  if (!containerRef.value) return;

  const viewer = createViewer({ container: containerRef.value });
  viewerRef.value = viewer;

  try {
    await viewer.mount();
    await viewer.ready();
    await viewer.documents.open({
      url: "https://pdfobject.com/pdf/sample.pdf",
      displayName: "sample.pdf"
    });
    status.value = "Viewer ready";
  } catch (error) {
    status.value = "Viewer failed to start";
  }
});

onBeforeUnmount(() => {
  viewerRef.value?.destroy();
  viewerRef.value = null;
});

async function activateTool(action: ToolAction) {
  status.value = `Activating ${action}...`;
  try {
    const result = await viewerRef.value?.tools.set({
      action,
      enabled: true
    });

    if (result?.success) {
      activeTool.value = action;
      status.value = `${action} activated`;
    } else {
      status.value = `Failed: ${result?.error ?? "error"}`;
    }
  } catch (error) {
    status.value = "Tool error";
  }
}

async function fitWidth() {
  try {
    await viewerRef.value?.tools.navigation.set({
      action: "FIT_WIDTH",
      enabled: true
    });
    status.value = "Fitted width";
  } catch (error) {
    status.value = "Navigation error";
  }
}

function clearTools() {
  viewerRef.value?.tools.clear();
  activeTool.value = null;
  status.value = "Tools cleared, selection mode active";
}
</script>

<template>
  <div>
    <div class="toolbar">
      <button
        v-for="tool in toolsList"
        :key="tool.action"
        type="button"
        :aria-pressed="activeTool === tool.action"
        @click="activateTool(tool.action)"
      >
        {{ tool.label }}
      </button>
      <button type="button" @click="fitWidth">Fit Width</button>
      <button type="button" @click="clearTools">Clear tools</button>
    </div>
    <div ref="containerRef" style="height: 600px" />
    <pre>{{ status }}</pre>
  </div>
</template>
Vue Integration

Angular Integration

Trigger length, area, snap, and fit-view actions inside an Angular component:

import {
  AfterViewInit,
  Component,
  ElementRef,
  OnDestroy,
  ViewChild
} from "@angular/core";
import { createViewer, type RasterexViewer, type ToolAction } from "@rasterex/viewer";

@Component({
  selector: "app-measurement",
  templateUrl: "./measurement.component.html"
})
export class MeasurementComponent implements AfterViewInit, OnDestroy {
  @ViewChild("viewerContainer", { static: true })
  viewerContainer!: ElementRef<HTMLElement>;

  status = "Starting viewer...";
  activeTool: ToolAction | null = null;

  toolsList: Array<{ label: string; action: ToolAction }> = [
    { label: "Length", action: "MEASURE_LENGTH" },
    { label: "Area", action: "MEASURE_AREA" },
    { label: "Count", action: "COUNT" },
    { label: "Snap", action: "SNAP" }
  ];

  private viewer: RasterexViewer | null = null;

  async ngAfterViewInit(): Promise<void> {
    const viewer = createViewer({
      container: this.viewerContainer.nativeElement
    });

    this.viewer = viewer;

    try {
      await viewer.mount();
      await viewer.ready();
      await viewer.documents.open({
        url: "https://pdfobject.com/pdf/sample.pdf",
        displayName: "sample.pdf"
      });
      this.status = "Viewer ready";
    } catch (error) {
      console.error(error);
      this.status = "Viewer failed to start";
    }
  }

  async activateTool(action: ToolAction): Promise<void> {
    this.status = `Activating ${action}...`;
    const result = await this.viewer?.tools.set({
      action,
      enabled: true
    });

    if (result?.success) {
      this.activeTool = action;
      this.status = `${action} activated`;
    } else {
      this.status = result?.error ?? "Tool activation failed";
    }
  }

  async fitWidth(): Promise<void> {
    try {
      await this.viewer?.tools.navigation.set({
        action: "FIT_WIDTH",
        enabled: true
      });
      this.status = "Fitted width";
    } catch (error) {
      this.status = "Navigation error";
    }
  }

  clearTools(): void {
    this.viewer?.tools.clear();
    this.activeTool = null;
    this.status = "Tools cleared, selection mode active";
  }

  ngOnDestroy(): void {
    this.viewer?.destroy();
  }
}
Angular Integration

Live Preview

Test measurement tools in real-time.

Interactive Workbench

Live Canvas Preview

Launch the interactive preview to explore the Canvas capabilities. Use the dashboard within the modal to test different tools and configurations.

Additional Resources

Continue with related measurement workflows and API references.