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

Shield Libary: generate three output formats for broad compatibility #905

Draft
wants to merge 23 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3b632ce
Expose shield generator as a global
1ec5 Jul 23, 2023
ba56ebf
Renamed build output file to something more descriptive
1ec5 Jul 23, 2023
3525f5e
Added HTML step to installation instructions
1ec5 Jul 23, 2023
73de43c
Updated entry point
1ec5 Jul 23, 2023
32e4890
shieldlib: output browser, esmodule, and commonjs format for compatib…
zekefarwell Jul 23, 2023
289c661
change shield generator import to source file to work around ts-node …
zekefarwell Jul 25, 2023
000bbdf
change shield test import to source file to work around ts-node modul…
zekefarwell Jul 25, 2023
f4d944c
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Aug 1, 2023
ae78e53
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Aug 1, 2023
fa625d1
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Aug 6, 2023
047e6d1
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Sep 19, 2023
8cff249
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Sep 22, 2023
c4dc2e9
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Sep 27, 2023
22d20a8
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Oct 4, 2023
176a879
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Oct 6, 2023
b52acf6
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Oct 24, 2023
a107d45
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Oct 30, 2023
faf59af
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Jan 12, 2024
706ded5
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Apr 22, 2024
5ca0457
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf Apr 22, 2024
0db4ab5
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf May 10, 2024
5bd42f4
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf May 19, 2024
3a075d1
Merge branch 'main' into zeke-shieldlib-iife-890
ZeLonewolf May 20, 2024
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
2 changes: 1 addition & 1 deletion scripts/taginfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { mkdir } from "node:fs/promises";
import {
ShieldRenderer,
InMemorySpriteRepository,
} from "@americana/maplibre-shield-generator";
} from "@americana/maplibre-shield-generator/src/index";
/**
* TODO - BUG
* Exporting HeadlessGraphicsFactory in shieldlib's index.ts causes an unexplained error in node-canvas
Expand Down
24 changes: 15 additions & 9 deletions shieldlib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ The Americana shield renderer is a library intended to draw highway shields on a

![Pictoral highway shields](https://wiki.openstreetmap.org/w/images/6/6d/Rendered_shields_americana.png)

## Shield rendering workflow
## Usage

Rendering shields requires the following compoments:
Rendering shields requires the following components:

1. **Encode shield information in vector tiles**. First, your tiles must contain the information which tells the shield renderer what shields to draw. In OpenMapTiles, shield information is encoded in the [`transportation_name`](https://openmaptiles.org/schema/#transportation_name) vector tile layer with a series of attributes named `route_1`, `route_2`, etc. Each attribute contains a text string which contains all of the information needed to determine which graphic to display, including numeric route number if the shield is numbered. However, this library allows you to specify how the shield information has been encoded, and it's possible to stitch together data from multiple fields when encoding shield data.

2. **Expose shield information in a style layer**. Next, route information must be exposed in a maplibre expression using [image](https://maplibre.org/maplibre-gl-js-docs/style-spec/expressions/#types-image) in a structured string containing the route information. For example, you might encode Interstate 95 as an image named `shield|US:I=95`. Normally, the image expression is used to point to pre-designated sprites in a sprite sheet, but in this case, we're pointing to a sprite which doesn't exist called `shield|US:I=95`. This will trigger a `styleimagemissing` event which allows the shield renderer to create the required graphic on the fly. As an example of how to encode shield information, see OSM Americana's [`highway_shield`](https://github.com/ZeLonewolf/openstreetmap-americana/blob/main/src/layer/highway_shield.js) style layer.

3. **Define a parser that describes how route information is encoded**. There are three parts to a route definition:
3. Import the library:

```html
<script type="text/javascript" src="maplibre-shield-generator.js"></script>
```

4. **Define a parser that describes how route information is encoded**. There are three parts to a route definition:

1. The `network` string, which defines a network with a common shield shape, graphic, and color
1. The `ref` string, which defines a text sequence that should be drawn on top of the shield graphic
Expand All @@ -36,7 +42,7 @@ Rendering shields requires the following compoments:
};
```

4. **(Optional) Create predicates that define which shields will be handled**. For example, if all sprite IDs in your style that need a shield begin with the string `shield|`, this would look like:
5. **(Optional) Create predicates that define which shields will be handled**. For example, if all sprite IDs in your style that need a shield begin with the string `shield|`, this would look like:

```typescript
let shieldPredicate = (imageID: string) => imageID.startsWith("shield");
Expand All @@ -51,25 +57,25 @@ Rendering shields requires the following compoments:
!/^[lrni][chimpw]n$/.test(network);
```

5. **Create shield definitions and artwork**. The shield definition is expressed as a JSON file along with a set of sprites containing any raster artwork used for the shields. It can be generated as an object or hosted as a JSON file accessible by URL. See the next section for how to create this definition.
6. **Create shield definitions and artwork**. The shield definition is expressed as a JSON file along with a set of sprites containing any raster artwork used for the shields. It can be generated as an object or hosted as a JSON file accessible by URL. See the next section for how to create this definition.

6. **Hook up the shield generator to a maplibre-gl-js map**. Pass either the URL of the JSON shield definition or create an object in javascript code. There are two separate classes for each approach.
7. **Hook up the shield generator to a maplibre-gl-js map**. Pass either the URL of the JSON shield definition or create an object in javascript code. There are two separate classes for each approach.

```typescript
new URLShieldRenderer("shields.json", routeParser)
new mapLibreShieldGenerator.URLShieldRenderer("shields.json", routeParser)
.filterImageID(shieldPredicate)
.filterNetwork(networkPredicate)
.renderOnMaplibreGL(map);
```

```typescript
new ShieldRenderer(shields, routeParser)
new mapLibreShieldGenerator.ShieldRenderer(shields, routeParser)
.filterImageID(shieldPredicate)
.filterNetwork(networkPredicate)
.renderOnMaplibreGL(map);
```

## Shield Definition
## Shield definition

The purpose of the shield definition is to define which graphics and text to draw for each network/ref/name combination that you wish to display. This can be created in javascript as an object, or as an HTTP-accessible JSON file.

Expand Down
10 changes: 9 additions & 1 deletion shieldlib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
"maplibre-gl-js"
],
"license": "CC0-1.0",
"main": "dist/index.js",
"main": "dist/maplibre-shield-generator-cjs.js",
"module": "dist/maplibre-shield-generator-esm.js",
"browser": {
"dist/maplibre-shield-generator-cjs.js": "dist/maplibre-shield-generator.js",
"dist/maplibre-shield-generator-esm.js": "dist/maplibre-shield-generator-esm.js"
},
"source": "src/index.ts",
"devDependencies": {
"@types/color-rgba": "^2.1.0",
Expand Down Expand Up @@ -53,6 +58,9 @@
"maplibre-gl": "^2.4.0",
"mocha": "^10.2.0"
},
"files": [
"dist/*"
],
"directories": {
"test": "test"
},
Expand Down
45 changes: 38 additions & 7 deletions shieldlib/scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,55 @@ const buildWith = async (key, buildOptions) => {
await mkdir("dist", { recursive: true });

const options = {
entryPoints: ["src/index.ts"],
format: "iife",
globalName: "mapLibreShieldGenerator",
bundle: true,
minify: true,
sourcemap: true,
outfile: "dist/maplibre-shield-generator.js",
logLevel: "info",
...buildOptions,
define: {
...buildOptions?.define,
},
};
const cjsOptions = {
entryPoints: ["src/index.ts"],
format: "cjs",
bundle: true,
minify: true,
sourcemap: true,
outfile: "dist/maplibre-shield-generator-cjs.js",
logLevel: "info",
...buildOptions,
define: {
...buildOptions?.define,
},
};
const esmOptions = {
entryPoints: ["src/index.ts"],
format: "esm",
bundle: true,
minify: true,
sourcemap: true,
outdir: "dist",
outfile: "dist/maplibre-shield-generator-esm.js",
logLevel: "info",
...buildOptions,
define: {
...buildOptions?.define,
},
};
return (
esbuild[key](options)
// esbuild will pretty-print its own error messages;
// suppress node.js from printing the exception.
.catch(() => process.exit(1))
);

// esbuild will pretty-print its own error messages;
// suppress node.js from printing the exception.
const suppressErrors = () => process.exit(1);

return ([
esbuild[key](options).catch(suppressErrors),
esbuild[key](cjsOptions).catch(suppressErrors),
esbuild[key](esmOptions).catch(suppressErrors),
]);
};

export const buildContext = (buildOptions = {}) =>
Expand Down
2 changes: 1 addition & 1 deletion test/spec/shield.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { loadShields } from "../../src/js/shield_defs";
import {
ShieldRenderer,
InMemorySpriteRepository,
} from "@americana/maplibre-shield-generator";
} from "@americana/maplibre-shield-generator/src/index";

import { HeadlessGraphicsFactory } from "@americana/maplibre-shield-generator/src/headless_graphics";

Expand Down
Loading