Print maps are documents
@nika-js/onlymap/cartograph is a separate entry for composing print-ready map sheets
in HTML. A cartograph is measured in millimetres, not browser layout units. It combines
live OnlyMap scenes and static georeferenced rasters with legends, scale bars, north
indicators, graticules, text, shapes, and images.
The cartograph entry is lazy and separate from the interactive-map entry. It does not
increase the core map bundle, and a sheet containing only static frames never loads the
map runtime.
Frames and cartographic furniture
<om-frame> shows a picture from one of three kinds of source:
- A live frame contains an inline
<om-map>or references a map document withsrc. The frame owns its camera, so the same map can appear at different extents on one sheet. Export captures it again at the requested print resolution. - A static frame uses
mode="static", a raster image,crs, and four geographiccorners. Scale bars, grids, and north indicators use that georeference without loading the interactive map runtime. - Ordered sources new in 0.10.6: a live frame can list several places its
picture may come from, as
<om-source>children, and shows the first that actually renders. See Fallback sources below.
for="frame-id". A live-frame legend derives its
rows from the map’s resolved symbology, including classified breaks, raster ramps, and
flat colours 0.10.5, so the map and legend cannot drift apart. Static frames
can use literal <om-legend-row> entries with derived="false".
Colours by attribute new in 0.10.10
A sheet has five themes (theme="default|dark|sepia|blueprint|minimal"), and each
element’s look can now be set on the element itself, beside the theme:
Each override writes the same
--om-carto-* property the theme sets, scoped to that
element, so the sheet on screen, the printed page and the exported image agree. Nothing
else is styleable: an attribute outside these lists is a validator warning, not a quiet
no-op — writing background= on the page, for instance, warns and changes nothing.
Use overview-of="main" on a second frame to draw the main frame’s footprint as a
locator inset. Text supports page, frame, and atlas tokens such as {{title}},
{{date}}, {{frame.main.scale}}, and {{atlas.name}}.
A live frame follows its map since 0.8.3
A live frame georeferences whatever its map is showing. Pan, rotate or tilt the map inside a frame and, once it settles, the north arrow, scale bar, graticule, locator inset and{{frame.<id>.scale}} all describe the view on screen — not the camera the
document was saved with. Zoom out far enough and the world wraps inside the frame like
any web map: the graticule labels each copy, the scale bar measures its own row. The
frame never caps or rewrites the camera. max-pitch and min-zoom on <om-map> exist
as author-set controls for a kiosk-style map, and nothing applies them for you.
Projected plates new in 0.10.0
A live frame inherits the projection of the map it shows. Point it at a map whose<om-map> carries crs="EPSG:5070" and you get a properly projected plate — Albers,
UTM, a national grid — with the graticule, scale bar and north arrow all placed through
that plane. Choose the projection in the map, not the frame; see
Cartographic Maps for what a projected map can
and cannot carry.
Freeze a frame to vector new in 0.10.0
frame.freeze({ format: "svg" }) turns a live frame into editable artwork in place —
real <path> outlines and real <text> labels, with relief and imagery as images
underneath. The frozen sheet opens with no JavaScript at all and still reads correctly.
Freezing a projected frame writes the map’s CRS onto it.
Fallback sources new in 0.10.6
src= names one place a frame’s picture comes from and assumes it works. That holds in
the app that wrote the sheet and often nowhere else: a relative path into an app’s
storage, or layers served by an app-local protocol, both fail when the file is opened
elsewhere — and they fail silently. The map mounts, reports success, and draws an
empty box ringed by a perfectly correct legend, scale bar and title.
A frame can therefore declare several sources and show the first that renders:
src=on the frame is shorthand for the first<om-source>, so every existing sheet keeps working. An inline<om-map>child always outranks both.- One attribute,
src, for both kinds. The kind is read from the extension:.htmlis a map document;.png,.jpg,.jpeg,.webp,.avif,.gifor.svgis a capture. Anything else is a validation error naming both — never a guess. - “Rendered” means one drawable thing after the map settles — a basemap, or rows on any layer. Deliberately not “every layer loaded”: a sheet whose fifth layer 404s is degraded, not failed, and swapping it for a stale capture would be worse.
- A capture carries its own
cornersandcrs, because if it is what you are seeing, the live map did not load and there is nothing else to take coordinates from. Validation asks for them. - The frame says which source it settled on — a
data-om-carto-source="<index>"attribute and anom-frame-sourceevent — so an editor can say “showing a capture”. Furniture re-places itself against whichever source won.
A saved sheet renders in place; it is not portable. Capture paths are relative, so
moving the file alone breaks them, exactly as it already breaks a relative
src=.
Exporting is what produces a file that survives being sent to someone — it inlines the
map and embeds the pictures.Print and image export
Sheets print at their real physical size through CSS@page. Live WebGL frames are
re-rendered and temporarily replaced with print-resolution images before the print
dialog opens, avoiding blank or screen-resolution map canvases.
page.print({ dpi: 300 }) for print/PDF or renderCartograph(page, { dpi: 300 })
for PNG/JPEG. A hosted cartograph can opt into ?print=1 and
?export=png&dpi=300 automation by setting allow-url-actions on its root; for an
atlas, ?export=png&page=N (1-based) exports one page of the run.
Press-work attributes are available on <om-cartograph>:
bleedexpands the printable sheet beyond the trim box.crop-marksdraws trim marks inside that bleed.safe-zoneshows a screen-only guide and never appears in output.flattenrenders the final sheet as one raster for print workflows that mishandle SVG or CSS effects.
<om-effect> print finish exports as a single raster band, because
the finish treats the whole frame — see
Print Finishes.
One page per feature
<om-atlas> turns a layer into a run of sheets — one page per feature. Frames carrying
atlas-fit="feature" refit to the current feature, scale bars and tokens update for
that page, and renderCartographAtlas() writes the run to one ZIP.
Turning the pages new in 0.10.9
A reader can page an atlas anywhere the runtime runs — a plain browser, an embedding app’s preview, an exported file:- Keyboard:
←/→,PageUp/PageDown,Home,End, whenever focus is not in a form field. - An on-sheet pager,
‹ 3 / 49 · Alabama ›, at the sheet’s foot. It is screen-only: never printed, never in a PNG or JPEG, and stripped before a host saves the document.pager="none"on<om-atlas>removes it for a host that draws its own. - A host protocol, for an app that shows the sheet in a cross-origin iframe and so
cannot reach
seek(). On every page change the runtime posts{ source: "onlymap-cartograph", type: "atlas-page", index, count, name }to its parent window, and accepts{ source: "onlymap-cartograph-host", type: "atlas-seek", index }back. The index is 0-based, likeseek(i).
cartographEl.atlas with count, index,
current, seek(i), next(), filenames() and pageName(i), and fires
om-atlas-page.
Colour and validation
Setcvd="deuteranopia", protanopia, tritanopia, or achromatopsia to review the
whole page through a colour-vision-deficiency simulation. lintLegendColours() detects
legend entries that collapse under those simulations.
validateCartographString() checks the page without loading the map core.
validateCartographDeep() additionally validates inline live-map manifests when the
core is already available. Diagnostics use the same structured error and warning shape
as OmMap.validate().
Attribution on a sheet
Free non-commercial cartographs include an OnlyMap foot credit in print and image exports. An authored<om-text> credit mentioning OnlyMap satisfies the attribution
requirement; a verified commercial key on a live frame’s map removes it, and
<om-cartograph keep-badge> keeps it voluntarily 0.8.4. The sheet credits
itself once: a map inside a frame carries no badge of its own 0.10.8, so a
plate with a main map and two locator insets is credited once, not three times. See
Licensing & Telemetry.
Basemap credits move to the sheet too new in 0.11.3. A map inside a frame no
longer shows its own OpenStreetMap or CARTO attribution: the sheet credits every provider
once, at the page’s bottom-right, opposite the OnlyMap credit. A frozen frame records
its providers in an attribution attribute —
attribution="© OpenStreetMap contributors · © CARTO" — so a static or exported sheet still
credits its tiles with nothing loaded; set it yourself on a placed image whose tiles need
credit. A fallback capture <om-source> takes the same attribution, and the sheet credits it
while that capture is what the frame shows 0.11.4 — record it with the capture’s
corners, since a capture is only shown when the live map did not load. If your own
<om-text> already names a provider, the sheet leaves it out of its line.
Changes since 0.8.0
Behaviour fixes a sheet author may have worked around:- 0.8.1 — A frame switched from static back to live no longer shows its old capture
as a ghost behind the map.
max-pitchon<om-map>added. - 0.8.2 / 0.8.3 — The tilt cap a frame briefly imposed is gone; the frame now
handles any view the map can show, and its furniture follows the map’s settled view.
Sheets saved zoomed-out or steeply tilted open as authored.
min-zoomadded. - 0.10.0 — A projected frame is no longer placed upside down; relief reaches a projected sheet’s corners; contour lines stop re-downloading elevation on every edit.
- 0.10.7 — A sheet now shows the current version of the map it points at. It used to serve the copy it fetched first, so a restyled map never reached the sheet — and a sheet that seemed to work only after you opened the map first was this.
- 0.10.8 — One attribution credit per sheet, not one per frame.
- 0.11.3 — Basemap credits (OpenStreetMap, CARTO, …) move off the frames into one line in the page’s corner, and frozen frames keep them.
- 0.11.4 — A frame that falls back to its saved capture credits that capture’s providers.
- 0.11.5 — On a frame whose map uses a projected
crs, popups appear and a click on a feature reports its longitude and latitude. Popups used to stay hidden there, andzoom-to-featurewent to the wrong place. - 0.11.6 — Curved labels (
TextOnPathLayer) takepickable, and a click on one reports the river or road it names, so a{{name}}popup no longer comes up blank.