Skills/Editor Toolkit/Overlay Item Element

ef-overlay-item

Attributes

element-id
string

Element ID to track (searches data-element-id or data-timegroup-id)

target
string | HTMLElement

CSS selector or element reference to track

Methods

updatePosition(): void

Update position based on target element (called by parent layer)

Individual overlay that tracks and follows a target element's position.

Basic Usage

Track an element with an overlay:

<div class="relative w-[600px] h-[400px] border border-gray-300 rounded overflow-hidden">
<ef-overlay-layer class="absolute inset-0 pointer-events-none">
<ef-overlay-item target="#box-1" class="border-2 border-blue-500 pointer-events-auto">
<div class="absolute -top-6 left-0 bg-blue-500 text-white text-xs px-2 py-1 rounded whitespace-nowrap">
Selected Box
</div>
</ef-overlay-item>
</ef-overlay-layer>
<div id="box-1" class="absolute top-12 left-12 w-40 h-32 bg-blue-100 border-2 border-blue-300 rounded"></div>
<div id="box-2" class="absolute top-48 left-48 w-40 h-32 bg-green-100 border-2 border-green-300 rounded"></div>
</div>

Target Selection

Overlay items support multiple ways to specify targets:

CSS Selector

Use any valid CSS selector:

<ef-overlay-item target="#my-element"></ef-overlay-item>
<ef-overlay-item target=".selected"></ef-overlay-item>
<ef-overlay-item target="ef-video[src*='intro']"></ef-overlay-item>

Element Reference

Pass element directly via JavaScript:

const overlay = document.querySelector('ef-overlay-item');
const element = document.getElementById('my-element');
overlay.target = element;

Element ID Attribute

Use element-id for canvas elements with data attributes:

<ef-canvas>
<div data-element-id="element-1"></div>
<ef-timegroup data-timegroup-id="group-1"></ef-timegroup>
</ef-canvas>
<ef-overlay-layer>
<ef-overlay-item element-id="element-1"></ef-overlay-item>
<ef-overlay-item element-id="group-1"></ef-overlay-item>
</ef-overlay-layer>

Overlay Content

Add any content inside the overlay item:

Selection Border

<ef-overlay-item target="#element" class="border-2 border-blue-500 rounded"></ef-overlay-item>

Labels and Badges

<div class="relative w-[600px] h-[400px] border border-gray-300 rounded overflow-hidden bg-gray-50">
<ef-overlay-layer class="absolute inset-0 pointer-events-none">
<ef-overlay-item target="#video-element" class="pointer-events-none">
<div class="absolute -top-7 left-0 bg-purple-600 text-white text-xs px-2 py-1 rounded-t flex items-center gap-1">
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
<path d="M2 6a2 2 0 012-2h6a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6zm12.553 1.106A1 1 0 0014 8v4a1 1 0 00.553.894l2 1A1 1 0 0018 13V7a1 1 0 00-1.447-.894l-2 1z" />
</svg>
Video
</div>
<div class="absolute -bottom-6 right-0 bg-gray-800 text-white text-xs px-2 py-1 rounded">
320x240
</div>
</ef-overlay-item>
</ef-overlay-layer>
<div id="video-element" class="absolute top-16 left-16 w-64 h-48 bg-black rounded shadow-lg flex items-center justify-center text-gray-400">
Video Player
</div>
</div>

Handles and Controls

<ef-overlay-item target="#element" class="pointer-events-auto">
<button class="absolute top-0 right-0 w-4 h-4 bg-blue-500 rounded-full -mt-2 -mr-2"></button>
<button class="absolute bottom-0 right-0 w-4 h-4 bg-blue-500 rounded-full -mb-2 -mr-2"></button>
</ef-overlay-item>

Position Updates

Overlay items are updated by their parent layer's RAF loop:

const overlay = document.querySelector('ef-overlay-item');
// Listen for position changes
overlay.addEventListener('position-changed', (e) => {
const { x, y, width, height, rotation } = e.detail;
console.log('Overlay moved to:', x, y);
console.log('Size:', width, height);
console.log('Rotation:', rotation);
});

Rotation Support

Overlay items automatically track element rotation:

<div class="relative w-[600px] h-[400px] border border-gray-300 rounded overflow-hidden bg-gray-50">
<ef-overlay-layer class="absolute inset-0 pointer-events-none">
<ef-overlay-item target="#rotated-box" class="border-2 border-red-500"></ef-overlay-item>
</ef-overlay-layer>
<div id="rotated-box" class="absolute top-24 left-24 w-40 h-32 bg-red-100 rounded shadow" style="transform: rotate(15deg)">
<div class="p-4 text-center">Rotated Element</div>
</div>
</div>

The overlay automatically rotates to match its target.

Visibility

Overlay items automatically hide when target is not found:

const overlay = document.querySelector('ef-overlay-item');
// Target exists - overlay visible
overlay.target = '#existing-element';
// Target not found - overlay hidden (display: none)
overlay.target = '#nonexistent-element';
// Target removed - overlay hidden
const element = document.getElementById('existing-element');
element.remove();

Pointer Events

Enable pointer events for interactive overlays:

<ef-overlay-item target="#element" class="pointer-events-auto cursor-move">
<!-- Interactive content -->
</ef-overlay-item>

Overlay layer has pointer-events: none, so explicitly enable on items that need interaction.

Coordinate System

Overlay items use absolute positioning relative to their parent overlay layer:

  • x, y: Top-left position in layer coordinates
  • width, height: Match target element dimensions
  • rotation: Parsed from target element's transform

The parent layer handles transform synchronization with pan/zoom.

Update Frequency

Position updates happen every animation frame (60fps) via the parent layer's RAF loop. No throttling or change detection - updates are always fresh.

Performance

Overlay items are passive - they don't run their own RAF loops. The parent layer manages all updates in a single synchronized loop, preventing RAF proliferation.

Target Validation

Overlay items verify target is still in the DOM:

const overlay = document.querySelector('ef-overlay-item');
const element = document.getElementById('my-element');
overlay.target = element; // Works - element in DOM
element.remove(); // Element removed
// Overlay automatically hides
document.body.appendChild(element); // Element re-added
// Overlay reappears on next frame

CSS Styling

Style the overlay item container:

ef-overlay-item {
/* Border and background */
border: 2px solid blue;
background: rgba(0, 0, 255, 0.1);
/* Pointer interaction */
pointer-events: auto;
cursor: pointer;
/* Transform origin (rotation center) */
transform-origin: center;
}

Position Change Event

The position-changed event provides:

interface OverlayItemPosition {
x: number; // Left position relative to OverlayLayer
y: number; // Top position relative to OverlayLayer
width: number; // Element width
height: number; // Element height
rotation: number; // Element rotation in degrees
}

Important Notes

  • Must be a child of an ef-overlay-layer element
  • Updates position continuously in sync with parent's RAF loop
  • Automatically handles element rotation transforms
  • Hidden when target element is not found
  • Position is relative to the overlay layer container
  • Use element-id for canvas elements with data attributes
  • Use target for custom DOM elements