Most of a map belongs in props. Some of it does not.
When to reach for it
"Fly to the result the user just picked" is an event, not a value.
Re-rendering the same centre twice should not re-animate, and animating is the
whole point. That is the category HoloMap.API exists for.
| Situation | Use |
|---|---|
| The camera reflects application state | HoloMap.Map's center / zoom props |
| The camera should animate in response to an event | fly_to/2, ease_to/2 |
| A layer's paint reflects state | HoloMap.Layer.*'s paint prop |
| A one-off highlight that should not survive a re-render | set_paint_property/4 |
| Hover and selection styling | set_feature_state/3 |
Anything set imperatively is overwritten the next time the declarative specification for that object changes. The reconciler treats rendered props as the source of truth.
Calling it
Always from an action, always with the map's cid first:
def action(:show_parcel, params, component) do
HoloMap.API.fly_to("explorer", center: {params.lng, params.lat}, zoom: 17)
put_state(component, :selected, params.id)
endActions only
These calls compile to no-ops on the server. They work in
action/3and in functions an action reaches; they do nothing ininit/3orcommand/3.To move the camera at mount time, chain an action from
init:def init(_params, component, _server) do component |> put_state(:style, @style_url) |> put_action(:frame_data) end
Calls made before the style finishes loading are queued and replayed, so an
action scheduled from init is not lost.
Camera
HoloMap.API.fly_to("explorer", center: {-70.66, 19.45}, zoom: 14, duration: 1_200)
HoloMap.API.ease_to("explorer", bearing: 45, pitch: 60)
HoloMap.API.jump_to("explorer", center: {-70.66, 19.45})
HoloMap.API.fit_bounds("explorer", [-71.0, 19.0, -70.0, 20.0], padding: 48)
HoloMap.API.resize("explorer")fly_to/2 arcs out and back in, which reads well over long distances.
ease_to/2 travels in a straight line, which reads better over short ones.
jump_to/2 does not animate, which is what a center prop change does.
fit_bounds/3 accepts any shape HoloMap.Spec.bounds/1 understands: a pair of
corners, or a flat [west, south, east, north] list.
resize/1 is almost never needed. MapLibre observes its own container, so a map
whose container changes size follows along by itself and this call does nothing.
The one case where it is required is a map built with track_resize={false},
which switches that observer off; the demo's camera page has one set up that way
so the difference is visible.
Layers
HoloMap.API.set_filter("explorer", "parcels-fill", ["==", ["get", "zone"], "R1"])
HoloMap.API.set_paint_property("explorer", "parcels-fill", :fill_color, "#ef4444")
HoloMap.API.set_layout_property("explorer", "parcels-fill", :visibility, "none")Property names may be atoms in Elixir style or MapLibre specification names; both reach MapLibre as the latter.
These duplicate what the paint, layout and filter props already do, and in
almost every case the props are the better choice, because they survive a re-render.
Reach here for something genuinely transient.
Feature state
Feature state is the mechanism behind hover and selection styling, and it has no declarative equivalent: it belongs to a feature, not to a component.
HoloMap.API.set_feature_state("explorer", %{source: "parcels", id: 12}, %{hover: true})
HoloMap.API.remove_feature_state("explorer", %{source: "parcels", id: 12}, "hover")
HoloMap.API.remove_feature_state("explorer", %{source: "parcels", id: 12})Add :source_layer for a vector source. Every feature needs an id, which GeoJSON
features often lack. Set generate_id on the source, or point promote_id at
a property that is already unique. There is a worked example in
Events.
Anything else
HoloMap.Runtime.call/3 reaches any method on the underlying maplibregl.Map:
HoloMap.Runtime.call("explorer", "setRenderWorldCopies", [false])It queues against style readiness like everything else, but it does not normalise its arguments. They are passed to MapLibre as given.
From JavaScript
A MapLibre plugin (a draw control, a geocoder, a deck.gl overlay) needs the
raw map object, and Hologram's interop cannot hand one to a third-party script.
Every booted map is published on window:
window.HoloMap.map("explorer") // the maplibregl.Map, or null
window.HoloMap.cids() // every live map's cid
window.HoloMap.destroy("explorer") // release its WebGL contextPrefer HoloMap.API from Elixir: it queues correctly against the style's
readiness, which a raw handle does not.