HoloMap.Marker (HoloMap v0.1.0)

Copy Markdown View Source

A pin at a coordinate, rendered as a DOM element above the map.

<HoloMap.Marker id="office" lng_lat={{-70.66, 19.45}} color="#ef4444" />

With custom markup, given as slot content:

<HoloMap.Marker id="office" lng_lat={{-70.66, 19.45}} on_click={:office_clicked}>
  <div class="rounded-full bg-white px-2 py-1 shadow">Head office</div>
</HoloMap.Marker>

Markers versus symbol layers

A marker is a DOM node. That makes it easy to style with your own CSS and cheap to reason about, and expensive at scale. A few dozen is comfortable, a few thousand is not. Past that, put the points in a HoloMap.Source.GeoJSON and draw them with HoloMap.Layer.Circle or HoloMap.Layer.Symbol, which render on the GPU. HoloMap.Image is what lets that symbol layer use an icon of your own.

Props

PropTypeNotes
idstringRequired. Identity across re-renders
lng_lat{lng, lat}Required. Where the marker sits
colorstringFill colour of the default pin. Ignored when slot content is given
scalenumberSize multiplier for the default pin
draggablebooleanLet the user move the marker
rotationnumberRotation in degrees
offset[x, y]Pixel offset from the anchor point
anchorstring"center", "top", "bottom", "left", "right" and the corners
pitch_alignment / rotation_alignmentstring"map", "viewport" or "auto"
opacitystringCSS opacity
class_namestringExtra classes on the marker element
popup_htmlstringAttach a popup that opens when the marker is clicked
popup_optionsmapOptions for that popup, in HoloMap.Popup's vocabulary

Raw HTML must arrive through an expression

Hologram HTML-escapes literal text attributes before they ever reach a component, so popup_html="<b>hi</b>" written directly in a template arrives as the characters <b>hi</b> and renders as visible text. Pass it as an expression instead (popup_html={@html}, or a value from state) and the markup survives. Slot content has no such caveat.

Events

on_click, on_drag_start, on_drag, on_drag_end. Handlers receive lng_lat, which for the drag events is the position the marker moved to:

def action(:pin_moved, params, component) do
  [lng, lat] = params.lng_lat
  put_state(component, coords: {lng, lat})
end

Dragging

Set draggable and the user can move the marker. on_drag_start fires once, on_drag on every pointer move, on_drag_end once at the finish.

Writing the position back into state from on_drag is safe, and is the usual way to keep a coordinate readout live. It looks like it should not be: each event is a state update, a re-render, and a setLngLat back into the marker MapLibre is in the middle of dragging. It works because the value going back is the one MapLibre just reported, so the write is a no-op. The marker stays locked to the cursor, measured at zero pixels of drift.

<HoloMap.Marker id="pin" lng_lat={@pin} draggable
                on_drag={:pin_moved} on_drag_end={:pin_settled} />

Use on_drag_end alone when only the final position matters; there is no reason to re-render on every frame for a value nothing reads until the drag is over.

Slot content is cloned

MapLibre moves a marker's element into its own overlay container. Handing it the node Hologram rendered would take that node out from under the virtual DOM and corrupt the next patch, so HoloMap gives MapLibre a clone instead. The markup renders and restyles normally, but Hologram event bindings inside the slot never fire. Use on_click on the marker itself. See the Limitations guide.

Summary

Functions

Returns true to indicate that the callee module is a component module (has "use Hologram.Component" directive).

Returns the list of property definitions for the compiled component.

Functions

__is_hologram_component__()

@spec __is_hologram_component__() :: boolean()

Returns true to indicate that the callee module is a component module (has "use Hologram.Component" directive).

Examples

iex> __is_hologram_component__()
true

__props__()

@spec __props__() :: [{atom(), atom(), keyword()}]

Returns the list of property definitions for the compiled component.