Skip to content

Smart Slide Implementation Detail

The Smart Slide system enables interactive features on top of rasterized images. This document describes the deep-level implementation of link preservation and coordinate normalization.


Coordinate Normalization

Typical PDF coordinates use "Points" where (0,0) is at the bottom-left or top-left depending on the PDF version. To ensure hyperlinks work on every device (Mobile, Ultra-wide, Tablet) regardless of the slide's resolution, we normalize all coordinates to Percentages (0.0 to 1.0).

Why use 0.0 - 1.0?

  • Responsiveness: The interactive overlay can be styled with top: 25.4%, left: 10.2% etc., ensuring the link box stays perfectly aligned with the visual element on the image.
  • Independence: The viewer doesn't need to know the original page dimensions or the current viewport pixel size.

extractPdfLinkHotspots() Algorithm

This utility, found in src/utils/pdfLinks.ts, is the "Eyes" of the system during browser-side processing.

  1. Extract Annotations: It uses the page.getAnnotations({ intent: 'display' }) method from pdfjs-dist.
  2. Filter Subtypes: It strictly looks for subtype === 'Link'.
  3. Coordinate Mapping: It converts the raw PDF rect array (4 numbers) into viewport coordinates using viewport.convertToViewportRectangle().
  4. Clamping: It uses a clamp01() helper to ensure that no coordinate ever falls outside the (0,1) range, preventing invisible overflows.
  5. Data Production: It returns an array of PdfLinkHotspot objects.
typescript
// extractPdfLinkHotspots Logic Snippet
const [x1, y1, x2, y2] = viewport.convertToViewportRectangle(annotation.rect);
const left = clamp01(Math.min(x1, x2) / viewport.width);
const top = clamp01(Math.min(y1, y2) / viewport.height);
const width = clamp01(Math.abs(x2 - x1) / viewport.width);
const height = clamp01(Math.abs(y2 - y1) / viewport.height);

Data Models

The following TypeScript interfaces from src/types/index.ts define how these interactive links are stored in the decks table:

PdfLinkHotspot

Stores a single interactive area on a slide.

typescript
export interface PdfLinkHotspot {
  href: string;   // The target URL
  rect: {
    x: number;     // Normalized Left (0-1)
    y: number;     // Normalized Top (0-1)
    width: number; // Normalized Width (0-1)
    height: number;// Normalized Height (0-1)
  };
}

SlidePage

Represents a single "Smart Slide".

typescript
export interface SlidePage {
  image_url: string;           // The rasterized slide (WebP/JPG)
  page_number: number;         // Index for sorting
  links?: PdfLinkHotspot[];    // Collection of hotspots (Optional)
}

Viewer Implementation

The ImageDeckViewer.tsx component iterates through the SlidePage.links array and renders them using a specialized LinkLayer.

  • Accessibility: Each link is a real <a> tag, allowing screen readers to "see" hyperlinks even in a purely image-based viewer.
  • Transparency: The links are invisible but receive hover/click events, giving the user a seamless, "native-document" experience.

Built with ❤️ for Founders