Visualize.Hooks (Visualize v0.2.35)

Copy Markdown View Source

Phoenix LiveView JavaScript hooks for interactive visualizations.

This module bundles ten hooks:

TooltipHook and CrosshairHook share hover, and BrushHook the brushed window, across the charts of a sync group over one bus, VisualizeSync (Visualize.Hooks.Sync), which the bundle defines before all three and does not export.

Installation

  1. Write the JavaScript file:

    File.write!("assets/js/visualize_hooks.js", Visualize.Hooks.js_code())

or Visualize.Hooks.install!/0, which writes it to default_path/0.

  1. Import in your app.js:

    import Hooks from "./visualize_hooks"

    let liveSocket = new LiveSocket("/live", Socket, { hooks: Hooks })

Usage Examples

Zoom/Pan

<svg phx-hook="ZoomHook" id="zoomable-chart" data-min-zoom="0.5" data-max-zoom="5">
  <g class="zoom-container">
    <!-- Chart content -->
  </g>
</svg>

# Handle zoom events
def handle_event("zoom", %{"k" => scale, "x" => x, "y" => y}, socket) do
  {:noreply, assign(socket, transform: %{k: scale, x: x, y: y})}
end

Brush Selection

<svg phx-hook="BrushHook" id="brush-chart" data-brush-type="x">
  <g class="chart-content">
    <!-- Chart content -->
  </g>
</svg>

# Handle brush events
def handle_event("brush_select", %{"x0" => x0, "x1" => x1} = params, socket) do
  # Filter data or zoom to selection
  {:noreply, socket}
end

Canvas

<div id="chart" phx-hook="CanvasBinaryChart" phx-update="ignore"
     data-binary={@binary} data-width="800" data-height="600">
  <canvas width="800" height="600"></canvas>
</div>

See Visualize.Hooks.Canvas, Visualize.Hooks.CanvasBinary and Visualize.Hooks.CanvasIncremental for the attributes and events of each.

Resize

<div id="panel" phx-hook="ResizeHook">
  <!-- the chart, rendered at the pushed width and height -->
</div>

def handle_event("resize", %{"width" => width, "height" => height}, socket) do
  {:noreply, assign(socket, width: width, height: height)}
end

See Visualize.Hooks.Resize.

Tooltip

<svg id="chart" phx-hook="TooltipHook">
  <g class="mark" data-tooltip-template="{t}: {v}">
    <circle cx="10" cy="20" r="3" data-datum="t v" data-datum-t="1" data-datum-v="4"/>
  </g>
</svg>

The attributes are what Visualize.IR.Element.datum/2 writes, and what a mark with a tooltip node writes on every element. See Visualize.Hooks.Tooltip.

Crosshair

<div id="chart" phx-hook="CrosshairHook" {@crosshair} data-crosshair-event="hover">
  {Phoenix.HTML.raw(@svg)}
</div>

crosshair = Visualize.Hooks.Crosshair.attrs(applied.frame, applied.sources)

The arrays are computed once on the server and the hook snaps to them, so it works over a canvas as over an SVG. See Visualize.Hooks.Crosshair.

Legend

<svg id="chart" phx-hook="LegendHook" data-legend-event="legend_toggle">
  <!-- a frame with a legend: every legend-item and every element a series draws carry data-series -->
</svg>

A click on an entry hides the series it names with display="none" and shows it again on the next; the event is optional. See Visualize.Hooks.Legend.

Builder

<ol id="layers" phx-hook="BuilderHook" data-builder-target={@myself}>
  <li data-builder-layer="0" draggable="true">…</li>
</ol>

The chart builder's two browser gestures: a layer dragged onto another pushes reorder, and a click on an inspector row pushes inspect. See Visualize.Hooks.Builder.

Summary

Functions

default_path()

Returns the path where hooks should be installed.

filter_selection(data, selection, opts)

See Visualize.Hooks.Brush.filter_selection/3.

identity_transform()

See Visualize.Hooks.Zoom.identity_transform/0.

install!()

Writes the hooks JavaScript to the default location.

inverse_transform_point(point, transform)

See Visualize.Hooks.Zoom.inverse_transform_point/2.

js_code()

Returns the complete JavaScript code for all hooks.

Write this to a file in your assets directory.

scale_transform(transform, scale, center)

See Visualize.Hooks.Zoom.scale_transform/3.

selection_to_domain(selection, opts)

See Visualize.Hooks.Brush.selection_to_domain/2.

transform_point(point, transform)

See Visualize.Hooks.Zoom.transform_point/2.

translate_transform(transform, dx, dy)

See Visualize.Hooks.Zoom.translate_transform/3.