Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/asset/vendor/
/asset/vendor/*
!/asset/vendor/leaflet/
!/asset/vendor/leaflet-draw/
!/asset/vendor/leaflet-fullscreen/
!/asset/vendor/VERSIONS.md
/build/
/language/debug.po
/language/debug.mo
Expand Down
69 changes: 66 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,75 @@ and markers targets operate in a single SQL statement per batch and scale to
large collections; the Cartography target runs through the API and is paced
by the job dispatcher.

### Maps

A `geometry` or `geometric coordinates` value is displayed as a Leaflet map with
the geometry drawn on it, rather than as raw WKT. A `geometric position` is not:
its origin is the top left corner of an image, so it stays text.

In the resource form, a `geometry` or `geography` value can be drawn instead of
typed. Press **Ctrl+Alt+M** inside the field, or click the button beside it,
**Use geometry editor**. What you draw is written back into that field as WKT
and validated as if it had been typed, so nothing about how the value is stored
changes. One shape per field: drawing a second replaces the first, because a
value that needed `MULTIPOLYGON` would be rejected by this module's own
validation. Circles are not offered — WKT has no way to carry a radius. Closing
the editor without drawing leaves the value exactly as it was.

Everything the maps need is bundled in `asset/vendor`; nothing is fetched from a
CDN at runtime. Leaflet is loaded lazily in the resource form, and reused if
another module (such as [Mapping]) already put it on the page.

The maps are configured under the `datatypegeometry` key. The defaults live in
`config/module.config.php` and are overridden from Omeka's
`config/local.config.php`; arrays merge, so naming one key leaves the rest
alone:

```php
'datatypegeometry' => [
// Map defaults: height, center, zoom, max_zoom, fit_max_zoom, and the
// Leaflet path style the geometry is drawn in.
'map' => [
'height' => 400,
],
// Exactly one is active at a time, the first by default. Ships with
// OpenStreetMap so a stock installation draws something.
'base_layers' => [
'osm' => [
'label' => 'OpenStreetMap',
'type' => 'tile',
'url' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
'options' => ['maxZoom' => 19, 'attribution' => '…'],
],
],
// Any number may be switched on, all off until then. Empty by default:
// which historical maps are worth showing belongs to a collection, not to
// this module.
'extra_layers' => [
'hisgis' => [
'label' => 'HISGIS minuutplannen',
'type' => 'tile',
'url' => 'https://tileserver.huc.knaw.nl/{z}/{x}/{y}',
'options' => ['minZoom' => 10, 'maxZoom' => 21, 'attribution' => 'Tiles HUC KNAW'],
],
],
],
```

An entry's `type` is `tile` or `wms`, its `url` is used exactly as written — so
a caching or rewriting proxy in front of a tile server is simply part of the
url — and its `options` are passed straight to Leaflet.

To draw the same map from a theme template:
`echo $this->geometryMap('POINT (4.7027444 52.0097589)');`


TODO
----

- [x] Remove doctrine:lexer from composer vendor.
- [ ] Add a checkbox in resource form to append marker to map of module Mapping or a main option?
- [ ] Add a button "select on map" in resource form to specify coordinates directly.
- [x] Add a button "select on map" in resource form to specify coordinates directly.
- [ ] Add a js to convert wkt into svg icon (via geojson/d3 or directly).
- [ ] Upgrade terraformer to terraformer.js (need a precompiled js).
- [x] Rename api keys to "geometry", "geography", "geography:coordinates" for Omeka S v4.
Expand Down Expand Up @@ -393,8 +455,9 @@ of the CeCILL license and that you accept its terms.

### Libraries

This module uses many open source leaflet libraries. See `asset/vendor` for
details.
This module bundles Leaflet, Leaflet.draw, leaflet.fullscreen and
@terraformer/wkt. See [asset/vendor/VERSIONS.md](asset/vendor/VERSIONS.md) for
the exact versions, their licences, and how to check a copy against upstream.


Copyright
Expand Down
95 changes: 95 additions & 0 deletions asset/css/data-type-geometry.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,77 @@
.sidebar #advanced-search .inputs label.type-radio::after {
background: initial;
}

/* The map editor. */

.geometry-map-open {
margin-top: 6px;
}

/* Font Awesome 5.15.4 "map-marked-alt", from the solid face Omeka already
loads. The glyph itself is all this rule supplies: the font family and
weight come from core's [class*="o-icon-"]:before, which is why the class
has to keep the o-icon- prefix even though the name is this module's own.

Deliberately not "draw-polygon" (\f5ee) or "map-marker-alt" (\f3c5): those
two are already the icons for the geometry and geography data types, and
they sit a few pixels away in the same row. */
.o-icon-map-select:before {
content: "\f5a0";
}

.geometry-map-open:before {
margin-right: 6px;
}

#geometry-map-sidebar .geometry-map-canvas {
width: 100%;
height: 400px;
}

#geometry-map-sidebar .geometry-map-notice {
margin-bottom: 6px;
}

#geometry-map-sidebar .geometry-map-actions {
margin-top: 12px;
}

#geometry-map-sidebar .geometry-map-cancel {
background-color: transparent;
color: inherit;
}

/* The value being rendered on a public page. */
.datatype-geometry-map {
max-width: 100%;
}

/* Leaflet 1.9 composites tiles with `mix-blend-mode: plus-lighter`, to hide
the dark seam a tile would otherwise show while it fades in. It costs
more than it saves here.

The map sits at an integer zoom, so the tiles are not scaled by Leaflet.
They are still scaled by the browser: at 110% page zoom, or on a display
with fractional scaling, a 256px tile becomes 281.6 device pixels and
neighbouring tiles overlap by a fraction of a pixel. plus-lighter adds
both contributions, and on a base layer as light as OpenStreetMap the sum
clips to white, so every tile edge draws as a white line on a ~281px
grid. Measured on a flat OSM-coloured tile at 1.1: 1006 pure-white pixels
across the map interior with plus-lighter, none with normal. Compositing
normally is never worse at any scale factor tested (1, 1.1, 1.25, 1.5),
and strictly better at three of them.

Both of this module's maps: the value on a public page, and the editor's
canvas in the sidebar. Specific enough (0,3,1) to beat Leaflet's own
(0,2,1) without depending on stylesheet order, which matters because the
Mapping module may have loaded its Leaflet after ours. Scoped to this
module so other modules' maps keep whatever they chose. Keep it while any
Leaflet on the page sets plus-lighter; see asset/vendor/VERSIONS.md. */
.datatype-geometry-map.leaflet-container img.leaflet-tile,
.geometry-map-canvas.leaflet-container img.leaflet-tile {
mix-blend-mode: normal;
}
}

@media screen and (max-width:640px) {
Expand All @@ -99,3 +170,27 @@
text-align: initial;
}
}

/* Wider than Omeka's default 25%: drawing a shape in a narrow column means
panning instead of seeing where the shape is going.

Core couples the width to the offset — .sidebar is width:25% parked at
left:100%, and .active slides it to left:75% — so the two have to keep adding
up to 100%. Widening one alone pushes the panel's right edge past the
viewport, where .sidebar's own overflow-x:hidden crops it, and what gets
cropped is whatever sits at the right edge of the map: the layer switcher.
Hence left:60% alongside width:40%, and no min-width, which would break the
arithmetic again between 641px and 950px.

Kept above core's 640px breakpoint. Below it the sidebar is already full
width and positioned differently, and there is nothing to widen. */
@media screen and (min-width: 641px) {
#geometry-map-sidebar {
width: 40%;
}

#geometry-map-sidebar.active,
#geometry-map-sidebar.always-open {
left: 60%;
}
}
Loading