Rasterex APINPM Package/docs/components/annotation/arrows

Arrows

Facilitate technical design coordination with vector-based drawing arrows.

Overview

Vector arrows enable clear visual links between reference data, specifications, and project components on the drawing canvas.

Use the tools API surface to activate arrow drawing states and apply custom stroke weights, opacity, and line colors.

  • Single-End Arrow (`ARROW_SINGLE_END`): Point to specific parts, defects, or annotations.
  • Double-End Arrow (`ARROW_BOTH_ENDS`): Connect related structures or represent spans.
  • Filled Head (`ARROW_FILLED_SINGLE_END`): Use industrial-standard solid arrowheads.

Quick Examples

Activate arrow drawing states programmatically using the tools surface:

Activate single arrow drawing mode

await viewer.tools.set({
  action: "ARROW_SINGLE_END",
  enabled: true,
  style: {
    strokeColor: "#e11d48",
    strokeWidth: 3,
    opacity: 0.95
  }
});

Deactivate arrows tool

// Deactivate arrow drawing mode
await viewer.tools.set({
  action: "ARROW_SINGLE_END",
  enabled: false
});

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

Supported Arrow Actions

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

  • `ARROW_SINGLE_END`: Arrow with a line head at the final point.
  • `ARROW_FILLED_SINGLE_END`: Solid, filled arrowhead at the final point.
  • `ARROW_BOTH_ENDS`: Arrow heads at both start and end locations.
  • `ARROW_FILLED_BOTH_ENDS`: Solid, filled arrowheads at both start and end locations.

Vanilla Integration

Copy these project setup files to configure mounting, arrow tools selection 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 enableArrow(action) {
  setStatus(`Activating ${action}...`);
  try {
    const result = await viewer.tools.set({
      action,
      enabled: true,
      style: {
        strokeColor: "#e11d48",
        strokeWidth: 3,
        opacity: 0.95
      }
    });

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

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

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

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

React Integration

Trigger vector arrow drawing states inside a React component:

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

const arrowsList: Array<{ label: string; action: ToolAction }> = [
  { label: "Single Arrow", action: "ARROW_SINGLE_END" },
  { label: "Filled Single", action: "ARROW_FILLED_SINGLE_END" },
  { label: "Double Arrow", action: "ARROW_BOTH_ENDS" }
];

export function ArrowsExample() {
  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,
      style: {
        strokeColor: "#e11d48",
        strokeWidth: 3,
        opacity: 0.95
      }
    });

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

  function clearTools(): void {
    viewerRef.current?.tools.clear();
    setActiveTool(null);
    setStatus("Drawing tools cleared");
  }

  return (
    <div>
      <div className="toolbar">
        {arrowsList.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={clearTools}>Clear tools</button>
      </div>
      <div ref={containerRef} style={{ height: 600 }} />
      <pre>{status}</pre>
    </div>
  );
}
React Integration

Vue Integration

Trigger vector arrow drawing states inside a Vue Composition template:

<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 arrowsList: Array<{ label: string; action: ToolAction }> = [
  { label: "Single Arrow", action: "ARROW_SINGLE_END" },
  { label: "Filled Single", action: "ARROW_FILLED_SINGLE_END" },
  { label: "Double Arrow", action: "ARROW_BOTH_ENDS" }
];

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,
      style: {
        strokeColor: "#e11d48",
        strokeWidth: 3,
        opacity: 0.95
      }
    });

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

function clearTools() {
  viewerRef.value?.tools.clear();
  activeTool.value = null;
  status.value = "Drawing tools cleared";
}
</script>

<template>
  <div>
    <div class="toolbar">
      <button
        v-for="tool in arrowsList"
        :key="tool.action"
        type="button"
        :aria-pressed="activeTool === tool.action"
        @click="activateTool(tool.action)"
      >
        {{ tool.label }}
      </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 vector arrow drawing states inside an Angular component model:

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

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

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

  arrowsList: Array<{ label: string; action: ToolAction }> = [
    { label: "Single Arrow", action: "ARROW_SINGLE_END" },
    { label: "Filled Single", action: "ARROW_FILLED_SINGLE_END" },
    { label: "Double Arrow", action: "ARROW_BOTH_ENDS" }
  ];

  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,
      style: {
        strokeColor: "#e11d48",
        strokeWidth: 3,
        opacity: 0.95
      }
    });

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

  clearTools(): void {
    this.viewer?.tools.clear();
    this.activeTool = null;
    this.status = "Drawing tools cleared";
  }

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

Live Preview

Test the arrow 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

Connect arrow controls with core canvas setup steps.