Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate legend on demand #632

Merged
merged 73 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
797e60c
Added shield legend
1ec5 Dec 14, 2022
e3c2311
Label networks using Wikidata
1ec5 Dec 15, 2022
48cd578
Link image instead of definition
1ec5 Dec 15, 2022
f27586a
Factored out templates, helper functions
1ec5 Dec 15, 2022
fd26362
Link to Wikidata query
1ec5 Dec 15, 2022
6469334
Added place labels to legend
1ec5 Dec 15, 2022
60afc3e
Group shields by country
1ec5 Dec 16, 2022
dca9edd
Sort Other shields to bottom; scroll legend
1ec5 Dec 16, 2022
ae3d13e
Refactored symbol legends
1ec5 Dec 16, 2022
4381cd2
Generate legend sections dynamically
1ec5 Dec 16, 2022
aa124e7
Cleaned up legend layout
1ec5 Dec 16, 2022
d00cb6e
Documented Wikidata network item usage
1ec5 Dec 16, 2022
4187c2c
Added urbanized areas to legend
1ec5 Dec 17, 2022
de8f96c
Added state, country, continent to legend
1ec5 Dec 17, 2022
52839a1
Added parks to legend
1ec5 Dec 17, 2022
f0a916c
Added lakes to legend
1ec5 Dec 17, 2022
f772f7b
Added low-zoom lakes to legend
1ec5 Dec 17, 2022
4ee4fea
Added waterways to legend
1ec5 Dec 17, 2022
8e029a4
Added ferry lines to legend
1ec5 Dec 18, 2022
32dabdd
Fixed water confusion in legend
1ec5 Dec 18, 2022
d12f52b
Added airport details to legend
1ec5 Dec 18, 2022
6f56dfe
Added buildings to legend
1ec5 Dec 18, 2022
2946303
Simplified park layers
1ec5 Dec 18, 2022
0ddcb52
Removed debugging
1ec5 Dec 18, 2022
835ba14
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Dec 19, 2022
be04d1b
Streamlined feature querying
1ec5 Dec 19, 2022
b2811be
Simplified entry matching
1ec5 Dec 19, 2022
5e61cae
Added borders to legend
1ec5 Dec 20, 2022
1c4dd26
Added disputed borders to legend
1ec5 Dec 20, 2022
5e1b50e
Added freeways, toll roads to legend
1ec5 Dec 20, 2022
646c82c
Added highway exits to legend
1ec5 Dec 20, 2022
e1b3140
Moved international shield category to top
1ec5 Dec 20, 2022
5282ca8
Fixed text halo
1ec5 Dec 20, 2022
bbaa6a6
Fixed non-capital filter
1ec5 Dec 21, 2022
3fcbf6c
Added more road classes to legend
1ec5 Dec 21, 2022
80bacdb
Added remaining road classes
1ec5 Dec 21, 2022
dc1dd88
Added driveways to legend
1ec5 Dec 21, 2022
565635b
Added unpaved roads to legend
1ec5 Dec 21, 2022
4ede3c3
Added roads under construction to legend
1ec5 Dec 21, 2022
e121186
Added railroads to legend
1ec5 Dec 21, 2022
14adfd9
Moved legend config to separate file
1ec5 Dec 21, 2022
032eab7
Fixed build errors; sort shield rows
1ec5 Dec 21, 2022
4ae4dc6
Added shield variants to legend
1ec5 Dec 22, 2022
38f380d
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Dec 22, 2022
30299c2
Updated documentation
1ec5 Dec 22, 2022
ce37107
Locale-aware sort countries
1ec5 Dec 22, 2022
66a8be6
Singular descriptions in rail legend entries
1ec5 Dec 22, 2022
c2ee6e9
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Dec 22, 2022
929217a
Normalize country code case
1ec5 Dec 23, 2022
9eed73b
Sentence-case Wikidata labels
1ec5 Dec 23, 2022
21d026f
Made colon after country code optional
1ec5 Dec 23, 2022
664d84d
BAB is not a country
1ec5 Dec 23, 2022
0c230c5
More kinds of recreational route networks
1ec5 Dec 23, 2022
a09f1af
Typo in readme
1ec5 Dec 23, 2022
278c1a1
Treat fake OMT network prefixes like real country prefixes
1ec5 Dec 23, 2022
e13bfa5
Special-case UK route types
1ec5 Dec 24, 2022
50f92d8
Fetch UK network descriptions from Wikidata
1ec5 Dec 24, 2022
fc4cf79
Fixed error when text-field uses string interpolation syntax
1ec5 Dec 26, 2022
7434f95
Added comments
1ec5 Dec 26, 2022
debd697
Italicize labels in legend based on font layout property
1ec5 Dec 26, 2022
2257e37
Added comments, tests
1ec5 Dec 27, 2022
abe143b
Link networks to Wikidata
1ec5 Dec 27, 2022
82366fb
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Dec 27, 2022
cfb4d3a
Removed special case for TLA recreational route networks
1ec5 Dec 27, 2022
7d773dd
Removed unused UK label constants
1ec5 Dec 27, 2022
b8e5d89
Fixed coalescing of 0 values
1ec5 Dec 28, 2022
fc7aa4d
Omit fully transparent roads from legend
1ec5 Dec 28, 2022
48f7496
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Dec 31, 2022
8ed05a9
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Dec 31, 2022
6bb730c
Fixed typo in comment
1ec5 Dec 31, 2022
56c6a5d
Merge branch 'main' into 1ec5-legends-of-the-hidden-layer-75
1ec5 Jan 2, 2023
3a6cdd5
Deleted redundant Kosovo shield
1ec5 Jan 3, 2023
0cc9038
Simplified Australian shield assignment
1ec5 Jan 3, 2023
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
11 changes: 8 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,17 @@ boilerplate in `scripts/taginfo_template.json`.

1. Please prettify all files prior to submission. Run `npm run code_format` to
format code files with [prettier][90] and SVG files with [SVGO][svgo].
2. If you are introducing a novel approach to depicting a layer or feature
2. If you are introducing a new kind of feature to the style, add a section to
`src/js/legend_config.js` or a legend entry in the corresponding file in
`src/layer/` that tells the Legend control how to find and render a
representative feature. Also try out the Samples button to catch any visual
conflicts.
3. If you are introducing a novel approach to depicting a layer or feature
property from the OpenMapTiles schema, document how the corresponding
OpenStreetMap key or tag is used in `scripts/taginfo_template.json`.
3. If any shield background icons are introduced, add lines to `src/shieldtest.js`
4. If any shield background icons are introduced, add lines to `src/shieldtest.js`
to demonstrate overlaid text on each of them.
4. If you are introducing new JavaScript code that can run independently of a
5. If you are introducing new JavaScript code that can run independently of a
browser environment, add automated unit tests for it to `test/spec/`, then
run `npm test` to ensure that they pass. This project structures unit tests
using [Chai](https://www.chaijs.com/guide/styles/) for assertions.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The Americana style is the first digital map to achieve concurrent, state-specif

## How to use

You can install the OpenStreetMap Americana package and [deploy it anywhere](CONTRIBUTING.md#Production%20builds) as a static webpage. For your convenience, we’ve deployed it [on GitHub Pages](https://zelonewolf.github.io/openstreetmap-americana/). To explore how the style depicts various features, click the Samples button.
You can install the OpenStreetMap Americana package and [deploy it anywhere](CONTRIBUTING.md#Production%20builds) as a static webpage. For your convenience, we’ve deployed it [on GitHub Pages](https://zelonewolf.github.io/openstreetmap-americana/). Click the Legend button to learn the meaning of each symbol, line, and color based on the features currently visible on the map.

The style tries to label places in [your browser’s preferred language](https://www.w3.org/International/questions/qa-lang-priorities). To change this preference, consult your browser’s documentation: [Chrome](https://support.google.com/chrome/answer/173424), [Firefox](https://support.mozilla.org/en-US/kb/use-firefox-another-language), [Safari for macOS](https://support.apple.com/guide/mac-help/change-the-system-language-mh26684/mac), [Safari for iOS](https://support.apple.com/en-us/HT204031). You can also override this preference by adding `&language=` to the URL, followed by a comma-separated list of [IETF language tags](https://www.w3.org/International/articles/language-tags/). For example, here’s a map labeled [in Portuguese, falling back to Spanish](https://zelonewolf.github.io/openstreetmap-americana/#language=pt,es). If we don’t have the name of a place in any of your preferred languages, the style shows the name in the local language as a last resort.

Expand Down Expand Up @@ -55,6 +55,8 @@ The OpenStreetMap Americana style is built upon the [OpenMapTiles schema](https:
- Translated name labels from [Wikidata](https://www.wikidata.org/wiki/Wikidata:Main_Page) for places, POIs, airports, roads, bodies of water, parks, and mountain peaks.
- Low-zoom ocean/water, boundary, and urbanized area data from [Natural Earth](https://www.naturalearthdata.com/).

The legend’s “Route markers” section is labeled using labels of Wikidata items that are tagged with the [corresponding OSM tag](https://www.wikidata.org/wiki/Property:P1282).

## Coverage

Americana is compatible with vector tiles covering the entire world.
Expand Down
33 changes: 9 additions & 24 deletions src/americana.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import config from "./config.js";

import * as Label from "./constants/label.js";

import * as Util from "./js/util.js";
import * as Shield from "./js/shield.js";
import * as ShieldDef from "./js/shield_defs.js";

Expand All @@ -31,6 +30,8 @@ import * as maplibregl from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";
import * as search from "./search.js";

import LegendControl from "./js/legend_control.js";
import * as LegendConfig from "./js/legend_config.js";
import SampleControl from "openmapsamples-maplibre/OpenMapSamplesControl.js";
import { default as OpenMapTilesSamples } from "openmapsamples/samples/OpenMapTiles/index.js";

Expand Down Expand Up @@ -205,28 +206,7 @@ function buildLayers() {
lyrOneway.bridgeLink,
];

//Render bridge without layer on the lowest bridge layer
bridgeLayers.forEach((layer) =>
layers.push(
Util.filteredClone(layer, ["!", ["has", "layer"]], "_layer_bottom")
)
);

//One layer at a time to handle stacked bridges
for (let i = 1; i <= 4; i++) {
bridgeLayers.forEach((layer) => layers.push(Util.restrictLayer(layer, i)));
}

//If layer is more than 5, just give up and render on a single layer.
bridgeLayers.forEach((layer) =>
layers.push(
Util.filteredClone(
layer,
[">=", ["coalesce", ["get", "layer"], 0], 5],
"_layer_top"
)
)
);
layers.push(...lyrRail.getLayerSeparatedBridgeLayers(bridgeLayers));

layers.push(
//The labels at the end of the list draw on top of the layers at the beginning.
Expand Down Expand Up @@ -326,14 +306,17 @@ map.on("styleimagemissing", function (e) {
Shield.missingIconHandler(map, e);
});

export function hotReloadMap() {
function hotReloadMap() {
map.setStyle(buildStyle());
}

export function updateLanguageLabel() {
languageLabel.displayLocales(Label.getLocales());
legendControl.onLanguageChange();
}

let legendControl = new LegendControl();
legendControl.sections = LegendConfig.sections;
window.addEventListener("languagechange", (event) => {
console.log(`Changed to ${navigator.languages}`);
hotReloadMap();
Expand Down Expand Up @@ -372,6 +355,8 @@ if (config.ATTRIBUTION_LOGO != undefined) {
map.addControl(new search.PhotonSearchControl(), "top-left");
map.addControl(new maplibregl.NavigationControl(), "top-left");

map.addControl(legendControl, "bottom-left");

// Add our sample data.
let sampleControl = new SampleControl({ permalinks: true });
OpenMapTilesSamples.forEach((sample, i) => {
Expand Down
86 changes: 86 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,49 @@
.openmapsamples-control-container {
margin-left: 70px !important;
}

#legend-container {
max-height: 60vh;
overflow-y: scroll;
}
.legend-section > summary {
background-color: #eee;
}
.legend-row,
.legend-row img {
vertical-align: middle;
}
.legend-row > .label,
.legend-row > .icon {
width: 0;
text-align: center;
}
.legend-row > .icon {
white-space: nowrap;
}
.legend-row .shield + .shield {
margin-left: 0.2em;
}
.legend-row > .swatch,
.legend-row > .line {
vertical-align: middle;
width: 4em;
}
.legend-row > .swatch {
border-style: solid;
}
.legend-row > .line > svg {
vertical-align: middle;
width: 100%;
}
.legend-source {
font-size: 80%;
text-align: right;
}
.legend-source,
.legend-source a {
color: #aaa;
}
</style>
<script type="module" src="americana.js"></script>
<link rel="stylesheet" href="americana.css" />
Expand All @@ -53,5 +96,48 @@
data-recalc-dims="1"
style="position: absolute; top: 0; right: 0; border: 0; z-index: 100"
/></a>
<template id="legend">
<h2>Legend</h2>
<div id="legend-container"></div>
</template>
<template id="legend-section">
<details class="legend-section" open>
<summary></summary>
<table>
<tbody></tbody>
<tfoot>
<tr>
<td class="legend-source" colspan="3"></td>
</tr>
</tfoot>
</table>
</details>
</template>
<template id="legend-rowgroup">
<tr class="legend-rowgroup">
<th colspan="3"></th>
</tr>
</template>
<template id="legend-row-symbol">
<tr class="legend-row legend-row-symbol">
<td class="label"></td>
<td class="icon"></td>
<td class="description"></td>
</tr>
</template>
<template id="legend-row-swatch">
<tr class="legend-row legend-row-swatch">
<td class="swatch" colspan="2"></td>
<td class="description"></td>
</tr>
</template>
<template id="legend-row-line">
<tr class="legend-row legend-row-line">
<td class="line" colspan="2">
<svg></svg>
</td>
<td class="description"></td>
</tr>
</template>
</body>
</html>
58 changes: 58 additions & 0 deletions src/js/legend_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"use strict";

import * as PlaceLayers from "../layer/place.js";
import * as LanduseLayers from "../layer/landuse.js";
import * as BoundaryLayers from "../layer/boundary.js";
import * as RoadLayers from "../layer/road.js";
import * as ConstructionLayers from "../layer/construction.js";
import * as HighwayExitLayers from "../layer/highway_exit.js";
import * as RailLayers from "../layer/rail.js";
import * as AerowayLayers from "../layer/aeroway.js";
import * as ParkLayers from "../layer/park.js";
import * as BuildingLayers from "../layer/building.js";
import * as WaterLayers from "../layer/water.js";
import * as FerryLayers from "../layer/ferry.js";

export const sections = [
{
name: "Populated places",
entries: PlaceLayers.legendEntries,
},
{
name: "Borders",
entries: BoundaryLayers.legendEntries,
},
{
name: "Roads",
entries: [
...RoadLayers.legendEntries,
...ConstructionLayers.legendEntries,
...HighwayExitLayers.legendEntries,
],
},
{
id: "shields",
name: "Route markers",
source: "Wikidata",
},
{
name: "Railroads",
entries: RailLayers.legendEntries,
},
{
name: "Aviation",
entries: AerowayLayers.legendEntries,
},
{
name: "Structures",
entries: BuildingLayers.legendEntries,
},
{
name: "Land use",
entries: [...LanduseLayers.legendEntries, ...ParkLayers.legendEntries],
},
{
name: "Water",
entries: [...WaterLayers.legendEntries, ...FerryLayers.legendEntries],
},
];
Loading