JavaScript is required

Element Lines

This example renders a list of interest-group cards and a map of matching markers inside `RGSlotOnCanvas`, then redraws one animated fake line between the selected pair. It is a focused reference for connecting ordinary HTML elements with relation-graph rather than connecting graph nodes.

Connecting HTML Cards to Map Markers with Fake Lines

What This Example Builds

This example builds a two-panel interface inside a relation-graph canvas. The left side shows a list of interest groups, and the right side shows fixed map markers on a background image. Selecting either side redraws one animated connector between the matching card and marker.

The main point is not node rendering. The visible endpoints are ordinary HTML elements placed in RGSlotOnCanvas, then registered as connectable targets so relation-graph can draw a line between them. A floating helper window adds canvas settings and image export, but the core lesson is the DOM-to-DOM connection pattern.

How the Data Is Organized

The example uses a small in-memory InterestGroup[] array. Each record contains:

  • groupId
  • groupName
  • location: { x, y }

loadDataFromRemote() populates six records, then the same array is projected twice during rendering:

  • once into left-side group-* targets
  • once into right-side location-* targets

That projection is what makes the one-to-one connection pattern simple. A real application could replace this data with store locations, departments on a floor map, devices on a topology image, or matched records across two panels.

How relation-graph Is Used

  • The graph uses a fixed layout because the meaningful positions come from absolutely positioned HTML in the canvas slot, not from automatic node layout.
  • RelationGraph provides the canvas host, and RGProvider enables hook-based utilities such as the floating settings panel.
  • RGSlotOnCanvas holds the entire list-and-map scene, so relation-graph acts as the connective layer under a custom UI composition.
  • Every card and every marker is wrapped in RGConnectTarget, which gives each HTML element a stable targetId.
  • RGHooks.useGraphInstance() is used for startup viewport work, fake-line replacement, runtime option changes, and export preparation.
  • RGHooks.useGraphStore() is used in the shared settings panel so the UI reflects current drag and wheel modes.
  • The key instance APIs are moveToCenter(), zoomToFit(), setEditingLine(null), clearFakeLines(), and addFakeLines(...).
  • The shared helper window also uses prepareForImageGeneration(), getOptions(), and restoreAfterImageGeneration() to export the current graph view.
  • Styling is mostly handled outside relation-graph through SCSS classes: purple list cards, selected halos, pulsing markers, and the animated curved connector.

Key Interactions

  • After mount, the example loads six groups, centers the viewport, fits the canvas, and auto-selects group a.
  • Clicking a group card highlights that card and redraws the connector to its matching map marker.
  • Clicking a map marker triggers the same selection flow from the opposite panel.
  • The floating description window can be dragged, minimized, and expanded.
  • The settings overlay can switch wheel behavior between scroll, zoom, and none.
  • The same overlay can switch drag behavior between selection, move, and none.
  • The Download Image action captures the current graph canvas as an image.

Key Code Fragments

This fragment shows that the graph is configured as a fixed-layout host for canvas-slot content.

const graphOptions: RGOptions = {
    debug: false,
    defaultJunctionPoint: RGJunctionPoint.border,
    wheelEventAction: 'zoom',
    dragEventAction: 'move',
    layout: {
        layoutName: 'fixed'
    }
};

This fragment is the core selection logic: one active group id is converted into one fake line between two HTML target ids.

const myFakeLines: JsonLine[] = [{
    id: `fl-${groupId}`,
    from: 'group-' + groupId,
    to: 'location-' + groupId,
    color: 'rgba(159,23,227,0.65)',
    lineWidth: 3,
    lineShape: RGLineShape.StandardCurve,
    fromJunctionPoint: RGJunctionPoint.lr,
    toJunctionPoint: RGJunctionPoint.border,
    animation: 2
}];

This fragment shows how the previous connector is cleared and replaced instead of keeping a persistent multi-edge graph.

graphInstance.setEditingLine(null);
graphInstance.clearFakeLines();
graphInstance.addFakeLines(myFakeLines);

This fragment shows the left-side HTML endpoints being registered as connect targets inside the canvas slot.

<RGConnectTarget
    key={group.groupId}
    targetId={`group-${group.groupId}`}
    junctionPoint={RGJunctionPoint.lr}
    disableDrag={true}
    disableDrop={true}
>
    <div
        className={`w-full pointer-events-auto c-i-group cursor-point ${activeGroupId === group.groupId ? 'c-i-group-checked' : ''}`}
        onClick={() => onGroupClick(group.groupId)}
    >

This fragment shows that wheel and drag behavior are changed at runtime through the graph instance instead of rebuilding the example.

<SettingRow
    label="Wheel Event:"
    options={[
        { label: 'Scroll', value: 'scroll' },
        { label: 'Zoom', value: 'zoom' },
        { label: 'None', value: 'none' },
    ]}
    value={wheelMode}
    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}
/>

What Makes This Example Distinct

Compared with nearby examples, this one is a focused reference for connecting ordinary HTML elements to other ordinary HTML elements. It does not convert the destination into a graph node, and it does not keep a larger editable relationship model alive.

  • Compared with element-connect-to-node, both endpoints stay in HTML through RGConnectTarget instead of mixing DOM endpoints with node-backed anchors.
  • Compared with element-line-edit, the map markers are not graph nodes, so the example reads more as a viewer-style matching pattern than a node-anchor adjustment demo.
  • Compared with interest-group, the scope is intentionally narrower: one selected group id, one selected marker, and one active connector.
  • Compared with scene-network-use-canvas-slot, the emphasis is not on a static dashboard board. It is on click-driven focus transfer across two UI regions.

The rare combination is the important part: a fixed-layout canvas slot, paired DOM endpoints, one animated curved fake line, synchronized selection state, and a shared floating utility panel. That makes this example a practical starting point when relation-graph needs to connect interface elements rather than visualize a traditional node-link dataset.

Where Else This Pattern Applies

  • Linking a list of stores, classrooms, booths, or rooms to pins on a floor plan or campus map.
  • Showing one selected asset in both a summary panel and a spatial backdrop without turning the backdrop markers into graph nodes.
  • Building master-detail dashboards where one selected row should highlight a matching element in a custom canvas scene.
  • Connecting ordinary DOM cards, badges, or chips across separate UI regions while keeping the visible scene fully custom.