├── spritezero
├── .nvmrc
├── package.json
└── README.md
├── sprite.png
├── sprite@2x.png
├── sprite@3x.png
├── .gitignore
├── bin
└── styletool-cli
├── .prettierrc
├── cli
├── static
│ ├── near-bus-routes.json
│ ├── regular-stops.json
│ ├── near-bus-stops.json
│ ├── regular-routes.json
│ ├── 3d.json
│ ├── stops-with-route-info.json
│ ├── routes-with-departures-only.json
│ ├── text-sv.json
│ ├── print.json
│ ├── text-en.json
│ ├── text-fisv.json
│ ├── simplified.json
│ └── driver-info.json
├── reorder.js
├── index.js
├── render.js
├── extract_difference.js
├── fileMappings.js
└── split.js
├── style
├── hsl-map-theme-near-bus-routes.json
├── hsl-map-theme-near-bus-stops.json
├── hsl-map-theme-regular-stops.json
├── hsl-map-theme-regular-routes.json
├── hsl-map-template.json
├── hsl-map-theme-3d.json
├── hsl-map-style-park-and-ride.json
├── hsl-map-style-municipal-borders.json
├── hsl-map-style-ticket-zone-labels.json
├── hsl-map-theme-stops-with-route-info.json
├── hsl-map-style-ticket-zones.json
├── hsl-map-theme-routes-with-departures-only.json
├── hsl-map-style-citybikes.json
├── hsl-map-theme-text-sv.json
├── hsl-map-theme-print.json
├── hsl-map-theme-text-en.json
├── hsl-map-style-ticket-sales.json
├── hsl-map-theme-text-fisv.json
├── hsl-map-theme-simplified.json
├── hsl-map-theme-driver-info.json
├── hsl-map-style-subway-entrance.json
└── hsl-map-style-icon.json
├── .github
├── dependabot.yml
└── workflows
│ └── check_version.yml
├── .eslintrc
├── map-icons
├── icon-letter-I.svg
├── icon-one-way.svg
├── icon-entrance-subway.svg
├── icon-terminal-subway.svg
├── icon-terminal-aerodrome.svg
├── icon-letter-T.svg
├── icon-platform-bus.svg
├── icon-platform-tram.svg
├── icon-platform-train.svg
├── icon-letter-L.svg
├── icon-letter-D.svg
├── icon-direction1.svg
├── icon-letter-00.svg
├── icon-letter-Y.svg
├── icon-letter-U.svg
├── icon-letter-P.svg
├── icon-letter-V.svg
├── icon-letter-O.svg
├── icon-letter-H.svg
├── icon-letter-N.svg
├── icon-letter-Z.svg
├── icon-letter-J.svg
├── icon-letter-E.svg
├── icon-letter-A.svg
├── icon-letter-K.svg
├── icon-letter-W.svg
├── icon-zone-D.svg
├── icon-letter-F.svg
├── icon-letter-M.svg
├── icon-time1.svg
├── icon-time2.svg
├── icon-letter-X.svg
├── icon-letter-R.svg
├── icon-letter-C.svg
├── icon-letter-B.svg
├── icon-direction2.svg
├── icon-letter-G.svg
├── icon-zone-A.svg
├── icon-letter-S.svg
├── icon-zone-C.svg
├── icon-letter-Q.svg
├── icon-zone-B.svg
├── icon-terminal-bus.svg
├── icon-letter-Ö.svg
├── icon-letter-Å.svg
├── icon-letter-Ä.svg
├── icon-entrance-wheelchair.svg
├── icon-entrance-stairs.svg
├── icon-terminal-ferry.svg
├── icon-park-and-ride.svg
├── icon-citybike-station.svg
├── icon-entrance-lift.svg
├── icon-tickets-sales-point.svg
├── icon-tickets-service-point.svg
├── icon-stop-bus.svg
├── icon-wetland.svg
├── icon-stop-tram.svg
├── icon-terminal-train.svg
├── icon-stop-train.svg
├── icon-tickets-machine-parking.svg
├── icon-stop-ferry.svg
├── icon-citybike-station2.svg
├── icon-stop-hybrid.svg
└── icon-terminal-ship.svg
├── package.json
├── LICENSE.md
├── index.html
├── server.js
└── data
└── ticket-zone-labels.json
/spritezero/.nvmrc:
--------------------------------------------------------------------------------
1 | 16
2 |
--------------------------------------------------------------------------------
/sprite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HSLdevcom/hsl-map-style/HEAD/sprite.png
--------------------------------------------------------------------------------
/sprite@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HSLdevcom/hsl-map-style/HEAD/sprite@2x.png
--------------------------------------------------------------------------------
/sprite@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HSLdevcom/hsl-map-style/HEAD/sprite@3x.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | fontstack/
2 | Gotham Rounded OpenType/
3 | node_modules/
4 | master/
5 | fonts
6 | .DS_Store
--------------------------------------------------------------------------------
/bin/styletool-cli:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | ':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"
3 |
4 | const styletool = require('../cli/index')
5 | styletool()
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": false,
3 | "arrowParens": "always",
4 | "bracketSpacing": true,
5 | "printWidth": 85,
6 | "semi": true,
7 | "trailingComma": "es5"
8 | }
9 |
--------------------------------------------------------------------------------
/cli/static/near-bus-routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "routes": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/near-bus-routes/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/cli/static/regular-stops.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "stops": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/regular-stops/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/cli/static/near-bus-stops.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "stops": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/near-bus-stops/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/cli/static/regular-routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "routes": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/regular-routes/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-near-bus-routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "routes": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/near-bus-routes/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/style/hsl-map-theme-near-bus-stops.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "stops": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/near-bus-stops/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-regular-stops.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "stops": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/regular-stops/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-regular-routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": {
3 | "routes": {
4 | "url": "https://kartat.hsl.fi/jore/tiles/regular-routes/index.json",
5 | "type": "vector"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/style/hsl-map-template.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 8,
3 | "name": "HSL v2.0",
4 | "metadata": {
5 | "maputnik:renderer": "mbgljs",
6 | "mapbox-groups": {}
7 | },
8 | "sources": {},
9 | "sprite": "https://hslstoragekarttatuotanto.z6.web.core.windows.net/sprite",
10 | "glyphs": "https://hslstoragestatic.azureedge.net/mapfonts/{fontstack}/{range}.pbf",
11 | "layers": []
12 | }
13 |
--------------------------------------------------------------------------------
/spritezero/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spritezero-run",
3 | "scripts": {
4 | "icons": "spritezero ../sprite ../map-icons && spritezero --ratio=2 ../sprite@2x ../map-icons && spritezero --ratio=3 ../sprite@3x ../map-icons"
5 | },
6 | "devDependencies": {
7 | "@mapbox/spritezero-cli": "^2.1.0"
8 | },
9 | "resolutions": {
10 | "@mapbox/spritezero-cli/@mapbox/spritezero": "^8.0.0"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/cli/static/3d.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "building_shadow",
5 | "layout": {
6 | "visibility": "none"
7 | }
8 | },
9 | {
10 | "id": "building",
11 | "layout": {
12 | "visibility": "none"
13 | }
14 | },
15 | {
16 | "id": "building_3d",
17 | "layout": {
18 | "visibility": "visible"
19 | }
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-3d.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "building_shadow",
5 | "layout": {
6 | "visibility": "none"
7 | }
8 | },
9 | {
10 | "id": "building",
11 | "layout": {
12 | "visibility": "none"
13 | }
14 | },
15 | {
16 | "id": "building_3d",
17 | "layout": {
18 | "visibility": "visible"
19 | }
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Specify a non-default branch for pull requests for npm
2 |
3 | version: 2
4 | updates:
5 | - package-ecosystem: "npm"
6 | directory: "/"
7 | schedule:
8 | interval: "daily"
9 | # Raise pull requests for version updates
10 | # to npm against the `development` branch
11 | target-branch: "development"
12 | # Labels on pull requests for version updates only
13 | labels:
14 | - "NPM Dependencies"
15 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["airbnb-base", "plugin:prettier/recommended"],
3 | "plugins": ["import"],
4 | "rules": {
5 | "quotes": ["error", "double", {"avoidEscape": true}],
6 | "vars-on-top": "off",
7 | "global-require": "off",
8 | "import/order": "off",
9 | "no-plusplus": "off",
10 | "import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
11 | },
12 | "env": {
13 | "browser": true,
14 | "node": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.github/workflows/check_version.yml:
--------------------------------------------------------------------------------
1 | name: Check version
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | check_version:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v3
14 | - name: Check if version has been updated
15 | id: check
16 | uses: EndBug/version-check@v2
17 | - name: Fail if version is not changed
18 | if: steps.check.outputs.changed == 'false'
19 | uses: actions/github-script@v3
20 | with:
21 | script: |
22 | core.setFailed('No version number change found. Run `yarn version`-command to upgrade version before merge can be completed.')
23 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-I.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hsl-map-style",
3 | "version": "1.2.2",
4 | "description": "",
5 | "main": "index.js",
6 | "bin": {
7 | "styletool": "./bin/styletool-cli"
8 | },
9 | "scripts": {
10 | "start": "node server",
11 | "watch": "nodemon --watch . -e js,json,html server.js",
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "",
15 | "devDependencies": {
16 | "commander": "^11.0.0",
17 | "eslint": "^8.30.0",
18 | "eslint-config-airbnb-base": "^15.0.0",
19 | "eslint-config-prettier": "^8.5.0",
20 | "eslint-plugin-import": "^2.26.0",
21 | "eslint-plugin-prettier": "^4.2.1",
22 | "express": "^4.18.2",
23 | "fs-extra": "^11.1.0",
24 | "nodemon": "^2.0.20",
25 | "prettier": "^2.8.1"
26 | },
27 | "dependencies": {
28 | "lodash": "^4.17.4"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/map-icons/icon-one-way.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
--------------------------------------------------------------------------------
/style/hsl-map-style-park-and-ride.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "park-and-ride_icon_hub",
5 | "type": "symbol",
6 | "source": "parkandride",
7 | "source-layer": "vehicleParking",
8 | "minzoom": 14,
9 | "filter": [
10 | "==",
11 | [
12 | "get",
13 | "carPlaces"
14 | ],
15 | true
16 | ],
17 | "layout": {
18 | "icon-image": "icon-park-and-ride",
19 | "icon-allow-overlap": false,
20 | "icon-size": 1
21 | },
22 | "paint": {
23 | "icon-translate": [
24 | 0,
25 | -5.25
26 | ]
27 | }
28 | }
29 | ],
30 | "sources": {
31 | "parkandride": {
32 | "url": "https://api.digitransit.fi/map/v3/hsl/fi/vehicleParking/tilejson.json",
33 | "type": "vector"
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/map-icons/icon-entrance-subway.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/map-icons/icon-terminal-subway.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
--------------------------------------------------------------------------------
/style/hsl-map-style-municipal-borders.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "municipal_border",
5 | "type": "line",
6 | "source": "borders",
7 | "minzoom": 7,
8 | "layout": {
9 | "line-cap": "round",
10 | "line-join": "round"
11 | },
12 | "paint": {
13 | "line-color": "#ccc",
14 | "line-width": {
15 | "stops": [
16 | [
17 | 10,
18 | 3
19 | ],
20 | [
21 | 18,
22 | 6
23 | ]
24 | ]
25 | },
26 | "line-dasharray": [
27 | 2,
28 | 2
29 | ]
30 | }
31 | }
32 | ],
33 | "sources": {
34 | "borders": {
35 | "data": "https://hslstoragekarttatuotanto.z6.web.core.windows.net/kuntarajat.json",
36 | "type": "geojson"
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/style/hsl-map-style-ticket-zone-labels.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "ticket-zone-labels",
5 | "type": "symbol",
6 | "source": "ticketzone-labels",
7 | "minzoom": 8,
8 | "maxzoom": 13,
9 | "layout": {
10 | "icon-image": [
11 | "concat",
12 | "icon-zone-",
13 | [
14 | "get",
15 | "Zone"
16 | ]
17 | ],
18 | "icon-rotation-alignment": "map",
19 | "icon-size": 0.7,
20 | "icon-padding": 1,
21 | "symbol-avoid-edges": false,
22 | "icon-allow-overlap": true
23 | },
24 | "paint": {
25 | "icon-translate-anchor": "viewport"
26 | }
27 | }
28 | ],
29 | "sources": {
30 | "ticketzone-labels": {
31 | "data": "https://hslstoragekarttatuotanto.z6.web.core.windows.net/ticket-zone-labels.json",
32 | "type": "geojson"
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/map-icons/icon-terminal-aerodrome.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-T.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-platform-bus.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-platform-tram.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-platform-train.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/cli/reorder.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const fs = require("fs-extra");
3 | const get = require("lodash/get");
4 | const sortBy = require("lodash/sortBy");
5 |
6 | module.exports = async function(file, orderFile) {
7 | const filePath = path.resolve(process.cwd(), file);
8 | const orderFilePath = path.resolve(process.cwd(), orderFile);
9 |
10 | const fileJson = await fs.readJson(filePath);
11 | const orderFileJson = await fs.readJson(orderFilePath);
12 |
13 | const layers = get(fileJson, "layers", []);
14 |
15 | if (layers.length === 0) {
16 | throw new Error("No layers in file!");
17 | }
18 |
19 | const orderLayers = get(orderFileJson, "layers", []);
20 |
21 | if (orderLayers.length === 0) {
22 | throw new Error("No layers in order file!");
23 | }
24 |
25 | const newLayers = sortBy(layers, (layer) =>
26 | orderLayers.findIndex((ol) => ol.id === layer.id)
27 | );
28 |
29 | fileJson.layers = newLayers;
30 | await fs.writeJson(filePath, fileJson, { spaces: 2 });
31 |
32 | process.exit(0);
33 | };
34 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-L.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/cli/static/stops-with-route-info.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "stops_case",
5 | "source": "stops-by-routes"
6 | },
7 | {
8 | "id": "stops_rail_case",
9 | "source": "stops-by-routes"
10 | },
11 | {
12 | "id": "stops_rail",
13 | "source": "stops-by-routes"
14 | },
15 | {
16 | "id": "stops_bus",
17 | "source": "stops-by-routes"
18 | },
19 | {
20 | "id": "stops_trunk",
21 | "source": "stops-by-routes"
22 | },
23 | {
24 | "id": "stops_ferry",
25 | "source": "stops-by-routes"
26 | },
27 | {
28 | "id": "stops_tram",
29 | "source": "stops-by-routes"
30 | },
31 | {
32 | "id": "stops_lrail",
33 | "source": "stops-by-routes"
34 | },
35 | {
36 | "id": "stops_subway",
37 | "source": "stops-by-routes"
38 | },
39 | {
40 | "id": "stops_hub",
41 | "source": "stops-by-routes"
42 | },
43 | {
44 | "id": "stops_rail_hub",
45 | "source": "stops-by-routes"
46 | }
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-D.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-stops-with-route-info.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "stops_case",
5 | "source": "stops-by-routes"
6 | },
7 | {
8 | "id": "stops_rail_case",
9 | "source": "stops-by-routes"
10 | },
11 | {
12 | "id": "stops_rail",
13 | "source": "stops-by-routes"
14 | },
15 | {
16 | "id": "stops_bus",
17 | "source": "stops-by-routes"
18 | },
19 | {
20 | "id": "stops_trunk",
21 | "source": "stops-by-routes"
22 | },
23 | {
24 | "id": "stops_ferry",
25 | "source": "stops-by-routes"
26 | },
27 | {
28 | "id": "stops_tram",
29 | "source": "stops-by-routes"
30 | },
31 | {
32 | "id": "stops_lrail",
33 | "source": "stops-by-routes"
34 | },
35 | {
36 | "id": "stops_subway",
37 | "source": "stops-by-routes"
38 | },
39 | {
40 | "id": "stops_hub",
41 | "source": "stops-by-routes"
42 | },
43 | {
44 | "id": "stops_rail_hub",
45 | "source": "stops-by-routes"
46 | }
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/map-icons/icon-direction1.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-00.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/spritezero/README.md:
--------------------------------------------------------------------------------
1 | # Spritezero instructions
2 |
3 | ## Installation
4 |
5 | Requirements:
6 | - node v16
7 | - yarn package manager
8 |
9 | ```
10 | yarn install
11 | ```
12 |
13 | ## How to add new icons
14 |
15 | 1. Download new icons as svg to your machine. Rename them logically.
16 | 2. (Optional step) Resize the icons to match the current ones. You can use rsvg-convert to do it.
17 | ```
18 | # Installation
19 | sudo apt install librsvg2-bin
20 |
21 | # Resize to the size 16x16 (or somewhat similar, depending of the aspect ratio of the icon)
22 | rsvg-convert -w 16 -h 16 -f svg icon.svg > resized-icon.svg
23 |
24 | # The batch process example
25 | for i in $(find new-icons/*.svg -printf "%f\n"); do rsvg-convert -w 16 -h 16 -f svg new-icons/$i > test-icons/$i; done;
26 | ```
27 | 3. Place the icons in the root of `map-icons` directory
28 | 4. Run the script:
29 | ```
30 | yarn run icons
31 | ```
32 | 5. Check that new icons are in `sprite.png`
33 |
34 | Now the icons should be available through the sprite.
35 |
36 | 6. Upload the newest sprite into Karttatuotanto Azure blob storage, overwriting the older sprite files.
37 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-Y.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-U.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-P.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-V.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-O.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-H.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-N.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-Z.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-J.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-E.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-A.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/cli/index.js:
--------------------------------------------------------------------------------
1 | const program = require("commander");
2 | const split = require("./split");
3 | const render = require("./render");
4 | const reorder = require("./reorder");
5 | const extract_difference = require("./extract_difference");
6 |
7 | module.exports = function() {
8 | program.version("1.0.0");
9 |
10 | program
11 | .command("split ")
12 | .description(
13 | "Split a style json file into distinct parts. Splits file into partials and writes them into dir. Dir will be created if it doesn't exist."
14 | )
15 | .action(split);
16 |
17 | program
18 | .command("render")
19 | .description(
20 | "Render a complete style.json from parts. Toggle partials in cli/render.js."
21 | )
22 | .action(render);
23 |
24 | program
25 | .command("matchorder ")
26 | .description(
27 | "Match layer order between different style files. Rewrites fileA to have its layers in the same order as fileB."
28 | )
29 | .action(reorder);
30 |
31 | program
32 | .command("extract-diff ")
33 | .description(
34 | "Move layers out from fileA that don't exist in fileB. Modifies fileA."
35 | )
36 | .action(extract_difference);
37 |
38 | program.parse(process.argv);
39 | };
40 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-K.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-W.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-zone-D.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-F.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-M.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-time1.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-time2.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-X.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-R.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-C.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/style/hsl-map-style-ticket-zones.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "ticket-zones_case",
5 | "type": "line",
6 | "source": "ticketzones",
7 | "layout": {
8 | "line-join": "round",
9 | "line-cap": "round"
10 | },
11 | "paint": {
12 | "line-color": "#333333",
13 | "line-width": [
14 | "interpolate",
15 | [
16 | "exponential",
17 | 1.2
18 | ],
19 | [
20 | "zoom"
21 | ],
22 | 10,
23 | 4,
24 | 22,
25 | 80
26 | ],
27 | "line-opacity": 0.2
28 | }
29 | },
30 | {
31 | "id": "ticket-zones",
32 | "type": "line",
33 | "source": "ticketzones",
34 | "layout": {
35 | "line-join": "round",
36 | "line-cap": "round"
37 | },
38 | "paint": {
39 | "line-color": "#333333",
40 | "line-width": [
41 | "interpolate",
42 | [
43 | "exponential",
44 | 1.2
45 | ],
46 | [
47 | "zoom"
48 | ],
49 | 10,
50 | 1,
51 | 22,
52 | 6
53 | ]
54 | }
55 | }
56 | ],
57 | "sources": {
58 | "ticketzones": {
59 | "data": "https://hslstoragekarttatuotanto.z6.web.core.windows.net/ticket-zones.json",
60 | "type": "geojson"
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-B.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-direction2.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-G.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-zone-A.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-S.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-zone-C.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Code license: MIT License
2 |
3 | Copyright (c) 2018, HSL
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
24 | # Design license: CC-BY 4.0
25 |
26 | The visual design features of the style (also known as the "look and feel" of the map) are licensed under the Creative Commons Attribution 4.0 license.
27 |
28 | To view a copy of the license, visit https://creativecommons.org/licenses/by/4.0/.
29 |
30 | Attribution for the design defined in this repository does not need to be provided on map images, but should be reasonably accessible from maps based on this style (for example, in a webpage linked from copyright notice on the map).
31 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-Q.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-zone-B.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-terminal-bus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
20 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-Ö.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HSL Map Style
5 |
6 |
7 |
8 |
29 |
30 |
31 |
32 |
33 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-Å.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-letter-Ä.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-entrance-wheelchair.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/cli/static/routes-with-departures-only.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "route_bus_case",
5 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
6 | },
7 | {
8 | "id": "route_bus",
9 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
10 | },
11 | {
12 | "id": "route_bus_inner",
13 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
14 | },
15 | {
16 | "id": "route_tram_case",
17 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
18 | },
19 | {
20 | "id": "route_tram",
21 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
22 | },
23 | {
24 | "id": "route_tram_inner",
25 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
26 | },
27 | {
28 | "id": "route_lrail_case",
29 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
30 | },
31 | {
32 | "id": "route_lrail",
33 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
34 | },
35 | {
36 | "id": "route_lrail_inner",
37 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
38 | },
39 | {
40 | "id": "route_trunk_case",
41 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
42 | },
43 | {
44 | "id": "route_trunk",
45 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
46 | },
47 | {
48 | "id": "route_trunk_inner",
49 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
50 | },
51 | {
52 | "id": "route_ferry",
53 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
54 | }
55 | ]
56 | }
--------------------------------------------------------------------------------
/style/hsl-map-theme-routes-with-departures-only.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "route_bus_case",
5 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
6 | },
7 | {
8 | "id": "route_bus",
9 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
10 | },
11 | {
12 | "id": "route_bus_inner",
13 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
14 | },
15 | {
16 | "id": "route_tram_case",
17 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
18 | },
19 | {
20 | "id": "route_tram",
21 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
22 | },
23 | {
24 | "id": "route_tram_inner",
25 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
26 | },
27 | {
28 | "id": "route_lrail_case",
29 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
30 | },
31 | {
32 | "id": "route_lrail",
33 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
34 | },
35 | {
36 | "id": "route_lrail_inner",
37 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
38 | },
39 | {
40 | "id": "route_trunk_case",
41 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
42 | },
43 | {
44 | "id": "route_trunk",
45 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
46 | },
47 | {
48 | "id": "route_trunk_inner",
49 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
50 | },
51 | {
52 | "id": "route_ferry",
53 | "filter": ["!=", ["boolean", ["get", "hasRegularDayDepartures"]], false]
54 | }
55 | ]
56 | }
--------------------------------------------------------------------------------
/cli/render.js:
--------------------------------------------------------------------------------
1 | const style = require("../index");
2 |
3 | module.exports = () => {
4 | const styleJson = style.generateStyle({
5 | sourcesUrl: "https://api.digitransit.fi/",
6 | glyphsUrl: "",
7 | spriteUrl: "",
8 |
9 | queryParams: [
10 | {
11 | url: "https://api.digitransit.fi/",
12 | name: "digitransit-subscription-key",
13 | value: "my-secret-key",
14 | },
15 | ],
16 | components: {
17 | // Set each layer you want to include to true
18 | // Styles
19 | base: { enabled: true }, // Enabled by default
20 | municipal_borders: { enabled: false },
21 | routes: { enabled: false },
22 | text: { enabled: true }, // Enabled by default
23 | subway_entrance: { enabled: false },
24 | poi: { enabled: false },
25 | park_and_ride: { enabled: false },
26 | ticket_sales: { enabled: false },
27 | stops: { enabled: false },
28 | citybikes: { enabled: false },
29 | ticket_zones: { enabled: false },
30 | ticket_zone_labels: { enabled: false },
31 | // Themes
32 | text_sv: { enabled: false },
33 | text_fisv: { enabled: false },
34 | text_en: { enabled: false },
35 | regular_routes: { enabled: false },
36 | near_bus_routes: { enabled: false },
37 | routes_with_departures_only: { enabled: true }, // Enabled by default. Doesn't do anything until routes is enabled
38 | regular_stops: { enabled: false },
39 | near_bus_stops: { enabled: false },
40 | print: { enabled: false },
41 | greyscale: { enabled: false },
42 | simplified: { enabled: false },
43 | "3d": { enabled: false },
44 | driver_info: { enabled: false },
45 | },
46 | routeFilter: [],
47 | joreDate: null, // defaults to current date in API
48 | });
49 |
50 | process.stdout.write(JSON.stringify(styleJson, null, 2));
51 | process.exit(0);
52 | };
53 |
--------------------------------------------------------------------------------
/style/hsl-map-style-citybikes.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "citybike_stops_case",
5 | "type": "circle",
6 | "source": "citybike",
7 | "source-layer": "rentalStations",
8 | "minzoom": 13,
9 | "maxzoom": 14,
10 | "paint": {
11 | "circle-color": "#fff",
12 | "circle-radius": [
13 | "interpolate",
14 | [
15 | "exponential",
16 | 1.15
17 | ],
18 | [
19 | "zoom"
20 | ],
21 | 12,
22 | 1.5,
23 | 22,
24 | 26
25 | ]
26 | }
27 | },
28 | {
29 | "id": "citybike_stops",
30 | "type": "circle",
31 | "source": "citybike",
32 | "source-layer": "rentalStations",
33 | "minzoom": 13,
34 | "maxzoom": 14,
35 | "paint": {
36 | "circle-color": "#fcbc19",
37 | "circle-radius": [
38 | "interpolate",
39 | [
40 | "exponential",
41 | 1.15
42 | ],
43 | [
44 | "zoom"
45 | ],
46 | 12,
47 | 1,
48 | 22,
49 | 24
50 | ]
51 | }
52 | },
53 | {
54 | "id": "citybike_icon",
55 | "type": "symbol",
56 | "source": "citybike",
57 | "source-layer": "rentalStations",
58 | "minzoom": 14,
59 | "layout": {
60 | "icon-offset": [
61 | 0,
62 | -6
63 | ],
64 | "icon-image": "icon-citybike-station",
65 | "icon-allow-overlap": false,
66 | "icon-size": {
67 | "stops": [
68 | [
69 | 13,
70 | 0.8
71 | ],
72 | [
73 | 20,
74 | 1.2
75 | ]
76 | ]
77 | }
78 | }
79 | }
80 | ],
81 | "sources": {
82 | "citybike": {
83 | "url": "https://api.digitransit.fi/map/v3/hsl/fi/rentalStations/tilejson.json",
84 | "type": "vector"
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/cli/extract_difference.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const fs = require("fs-extra");
3 | const get = require("lodash/get");
4 | const differenceBy = require("lodash/differenceBy");
5 | const merge = require("lodash/merge");
6 |
7 | module.exports = async function(file, compareFile) {
8 | const filePath = path.resolve(process.cwd(), file);
9 | const compareFilePath = path.resolve(process.cwd(), compareFile);
10 |
11 | const fileJson = await fs.readJson(filePath);
12 | const compareFileJson = await fs.readJson(compareFilePath);
13 |
14 | const layers = get(fileJson, "layers", []);
15 |
16 | if (layers.length === 0) {
17 | throw new Error("No layers in file!");
18 | }
19 |
20 | const compareLayers = get(compareFileJson, "layers", []);
21 |
22 | if (compareLayers.length === 0) {
23 | throw new Error("No layers in order file!");
24 | }
25 |
26 | const diffLayers = differenceBy(layers, compareLayers, "id");
27 |
28 | const diffFilejson = {
29 | layers: diffLayers,
30 | };
31 |
32 | diffLayers.forEach((layer) => {
33 | const source = get(layer, "source");
34 | const mapboxGroup = get(layer, "metadata.mapbox:group", "");
35 |
36 | if (source) {
37 | merge(diffFilejson, {
38 | sources: { [source]: fileJson.sources[source] },
39 | });
40 | }
41 |
42 | if (mapboxGroup) {
43 | merge(diffFilejson, {
44 | metadata: {
45 | "mapbox:groups": {
46 | [mapboxGroup]: fileJson.metadata["mapbox:groups"][mapboxGroup],
47 | },
48 | },
49 | });
50 | }
51 | });
52 |
53 | const newLayers = layers.filter((layer) => {
54 | const isDiff = diffLayers.find((dl) => dl.id === layer.id);
55 | return !isDiff;
56 | });
57 |
58 | fileJson.layers = newLayers;
59 |
60 | await fs.writeJson(filePath, fileJson, { spaces: 2 });
61 | await fs.writeJson(
62 | path.resolve(path.dirname(filePath), `layerdiff_${path.basename(file)}`),
63 | diffFilejson,
64 | { spaces: 2 }
65 | );
66 |
67 | process.exit(0);
68 | };
69 |
--------------------------------------------------------------------------------
/map-icons/icon-entrance-stairs.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
25 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const express = require("express");
3 |
4 | const index = fs.readFileSync("index.html", "utf8");
5 |
6 | const style = require("./index").generateStyle({
7 | // Urls to replace
8 | sourcesUrl: "http://localhost:8080/",
9 | glyphsUrl: "",
10 | spriteUrl: "",
11 |
12 | queryParams: [
13 | {
14 | url: "https://dev-api.digitransit.fi/",
15 | name: "digitransit-subscription-key",
16 | value: "my-secret-key",
17 | },
18 | ],
19 | components: {
20 | // Set each layer you want to include to true
21 | // Styles
22 | base: { enabled: true }, // Enabled by default
23 | municipal_borders: { enabled: false },
24 | routes: { enabled: false },
25 | text: { enabled: true }, // Enabled by default
26 | subway_entrance: { enabled: false },
27 | poi: { enabled: false },
28 | park_and_ride: { enabled: false },
29 | ticket_sales: { enabled: false },
30 | stops: { enabled: false },
31 | citybikes: { enabled: false },
32 | ticket_zones: { enabled: false },
33 | ticket_zone_labels: { enabled: false },
34 | // Themes
35 | text_sv: { enabled: false },
36 | text_fisv: { enabled: false },
37 | text_en: { enabled: false },
38 | regular_routes: { enabled: false },
39 | near_bus_routes: { enabled: false },
40 | routes_with_departures_only: { enabled: true }, // Enabled by default. Doesn't do anything until routes is enabled.
41 | regular_stops: { enabled: false },
42 | near_bus_stops: { enabled: false },
43 | print: { enabled: false },
44 | greyscale: { enabled: false },
45 | simplified: { enabled: false },
46 | "3d": { enabled: false },
47 | },
48 | // optional property to show only listed routes by jore id
49 | routeFilter: [],
50 | });
51 |
52 | const app = express();
53 |
54 | app.get("/", (req, res) => {
55 | res.redirect("/index.html");
56 | });
57 |
58 | app.get("/index.html", (req, res) => {
59 | res.set("Content-Type", "text/html");
60 | res.send(index);
61 | });
62 |
63 | app.get("/style.json", (req, res) => {
64 | res.set("Content-Type", "application/json");
65 | res.send(style);
66 | });
67 |
68 | app.listen(3000, () => {
69 | console.log("Listening at localhost:3000");
70 | });
71 |
--------------------------------------------------------------------------------
/cli/static/text-sv.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "label_poi_general",
5 | "layout": {
6 | "text-field": "{name_sv}"
7 | }
8 | },
9 | {
10 | "id": "label_poi_park",
11 | "layout": {
12 | "text-field": "{name_sv}"
13 | }
14 | },
15 | {
16 | "id": "label_poi_harbour",
17 | "layout": {
18 | "text-field": "{name_sv}"
19 | }
20 | },
21 | {
22 | "id": "label_water_point",
23 | "layout": {
24 | "text-field": "{name_sv}"
25 | }
26 | },
27 | {
28 | "id": "label_water_line",
29 | "layout": {
30 | "text-field": "{name_sv}"
31 | }
32 | },
33 | {
34 | "id": "label_place_island",
35 | "layout": {
36 | "text-field": "{name_sv}"
37 | }
38 | },
39 | {
40 | "id": "label_road_path_cycleway_track_service",
41 | "layout": {
42 | "text-field": "{name_sv}"
43 | }
44 | },
45 | {
46 | "id": "label_road_street",
47 | "layout": {
48 | "text-field": "{name_sv}"
49 | }
50 | },
51 | {
52 | "id": "label_road_primary",
53 | "layout": {
54 | "text-field": "{name_sv}"
55 | }
56 | },
57 | {
58 | "id": "label_place_other",
59 | "layout": {
60 | "text-field": "{name_sv}"
61 | }
62 | },
63 | {
64 | "id": "label_place_town",
65 | "layout": {
66 | "text-field": "{name_sv}"
67 | }
68 | },
69 | {
70 | "id": "label_place_city",
71 | "layout": {
72 | "text-field": "{name_sv}"
73 | }
74 | },
75 | {
76 | "id": "label_country",
77 | "layout": {
78 | "text-field": "{name_sv}"
79 | }
80 | },
81 | {
82 | "id": "icon_subway-station",
83 | "layout": {
84 | "text-field": "{nameSe}"
85 | }
86 | },
87 | {
88 | "id": "icon_bus-station",
89 | "layout": {
90 | "text-field": "{nameSe}"
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "layout": {
96 | "text-field": "{nameSe}"
97 | }
98 | },
99 | {
100 | "id": "icon_aerodrome",
101 | "layout": {
102 | "text-field": "{name_sv}"
103 | }
104 | }
105 | ]
106 | }
--------------------------------------------------------------------------------
/cli/static/print.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "landuse_park",
5 | "paint": {
6 | "fill-color": "#eaf2e0"
7 | }
8 | },
9 | {
10 | "id": "landuse_wood",
11 | "paint": {
12 | "fill-color": "#e3eed4"
13 | }
14 | },
15 | {
16 | "id": "landuse_grass",
17 | "paint": {
18 | "fill-color": "#dfebd0"
19 | }
20 | },
21 | {
22 | "id": "landuse_scrub",
23 | "paint": {
24 | "fill-color": "#d6e5c3"
25 | }
26 | },
27 | {
28 | "id": "landuse_agriculture",
29 | "paint": {
30 | "fill-color": "#eef4dc"
31 | }
32 | },
33 | {
34 | "id": "landuse_cemetery",
35 | "paint": {
36 | "fill-color": "#e0ebd2",
37 | "fill-outline-color": "#d4e3c3"
38 | }
39 | },
40 | {
41 | "id": "landuse_athletics",
42 | "paint": {
43 | "fill-color": "#e1ecd3",
44 | "fill-outline-color": "#cdddb9"
45 | }
46 | },
47 | {
48 | "id": "label_poi_general",
49 | "paint": {
50 | "text-color": "#000"
51 | }
52 | },
53 | {
54 | "id": "label_poi_harbour",
55 | "paint": {
56 | "text-color": "#000"
57 | }
58 | },
59 | {
60 | "id": "label_place_island",
61 | "paint": {
62 | "text-color": "#000"
63 | }
64 | },
65 | {
66 | "id": "label_road_path_cycleway_track_service",
67 | "paint": {
68 | "text-color": "#000"
69 | }
70 | },
71 | {
72 | "id": "label_road_street",
73 | "paint": {
74 | "text-color": "#000"
75 | }
76 | },
77 | {
78 | "id": "label_road_primary",
79 | "paint": {
80 | "text-color": "#000"
81 | }
82 | },
83 | {
84 | "id": "label_place_other",
85 | "paint": {
86 | "text-color": "#000"
87 | }
88 | },
89 | {
90 | "id": "label_place_town",
91 | "paint": {
92 | "text-color": "#000"
93 | }
94 | },
95 | {
96 | "id": "label_place_city",
97 | "paint": {
98 | "text-color": "#000"
99 | }
100 | },
101 | {
102 | "id": "label_country",
103 | "paint": {
104 | "text-color": "#000"
105 | }
106 | }
107 | ]
108 | }
109 |
--------------------------------------------------------------------------------
/cli/static/text-en.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "label_poi_general",
5 | "layout": {
6 | "text-field": "{name_en}"
7 | }
8 | },
9 | {
10 | "id": "label_poi_park",
11 | "layout": {
12 | "text-field": "{name_en}"
13 | }
14 | },
15 | {
16 | "id": "label_poi_harbour",
17 | "layout": {
18 | "text-field": "{name_en}"
19 | }
20 | },
21 | {
22 | "id": "label_water_point",
23 | "layout": {
24 | "text-field": "{name_en}"
25 | }
26 | },
27 | {
28 | "id": "label_water_line",
29 | "layout": {
30 | "text-field": "{name_en}"
31 | }
32 | },
33 | {
34 | "id": "label_place_island",
35 | "layout": {
36 | "text-field": "{name_en}"
37 | }
38 | },
39 | {
40 | "id": "label_road_path_cycleway_track_service",
41 | "layout": {
42 | "text-field": "{name_en}"
43 | }
44 | },
45 | {
46 | "id": "label_road_street",
47 | "layout": {
48 | "text-field": "{name_en}"
49 | }
50 | },
51 | {
52 | "id": "label_road_primary",
53 | "layout": {
54 | "text-field": "{name_en}"
55 | }
56 | },
57 | {
58 | "id": "label_place_other",
59 | "layout": {
60 | "text-field": "{name_en}"
61 | }
62 | },
63 | {
64 | "id": "label_place_town",
65 | "layout": {
66 | "text-field": "{name_en}"
67 | }
68 | },
69 | {
70 | "id": "label_place_city",
71 | "layout": {
72 | "text-field": "{name_en}"
73 | }
74 | },
75 | {
76 | "id": "label_country",
77 | "layout": {
78 | "text-field": "{name_en}"
79 | }
80 | },
81 | {
82 | "id": "icon_subway-station",
83 | "layout": {
84 | "text-field": "{nameFi}"
85 | }
86 | },
87 | {
88 | "id": "icon_bus-station",
89 | "layout": {
90 | "text-field": "{nameFi}"
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "layout": {
96 | "text-field": "{nameFi}"
97 | }
98 | },
99 | {
100 | "id": "icon_aerodrome",
101 | "layout": {
102 | "text-field": "{name_en}"
103 | }
104 | }
105 | ]
106 | }
107 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-text-sv.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "label_poi_general",
5 | "layout": {
6 | "text-field": "{name_sv}"
7 | }
8 | },
9 | {
10 | "id": "label_poi_park",
11 | "layout": {
12 | "text-field": "{name_sv}"
13 | }
14 | },
15 | {
16 | "id": "label_poi_harbour",
17 | "layout": {
18 | "text-field": "{name_sv}"
19 | }
20 | },
21 | {
22 | "id": "label_water_point",
23 | "layout": {
24 | "text-field": "{name_sv}"
25 | }
26 | },
27 | {
28 | "id": "label_water_line",
29 | "layout": {
30 | "text-field": "{name_sv}"
31 | }
32 | },
33 | {
34 | "id": "label_place_island",
35 | "layout": {
36 | "text-field": "{name_sv}"
37 | }
38 | },
39 | {
40 | "id": "label_road_path_cycleway_track_service",
41 | "layout": {
42 | "text-field": "{name_sv}"
43 | }
44 | },
45 | {
46 | "id": "label_road_street",
47 | "layout": {
48 | "text-field": "{name_sv}"
49 | }
50 | },
51 | {
52 | "id": "label_road_primary",
53 | "layout": {
54 | "text-field": "{name_sv}"
55 | }
56 | },
57 | {
58 | "id": "label_place_other",
59 | "layout": {
60 | "text-field": "{name_sv}"
61 | }
62 | },
63 | {
64 | "id": "label_place_town",
65 | "layout": {
66 | "text-field": "{name_sv}"
67 | }
68 | },
69 | {
70 | "id": "label_place_city",
71 | "layout": {
72 | "text-field": "{name_sv}"
73 | }
74 | },
75 | {
76 | "id": "label_country",
77 | "layout": {
78 | "text-field": "{name_sv}"
79 | }
80 | },
81 | {
82 | "id": "icon_subway-station",
83 | "layout": {
84 | "text-field": "{nameSe}"
85 | }
86 | },
87 | {
88 | "id": "icon_bus-station",
89 | "layout": {
90 | "text-field": "{nameSe}"
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "layout": {
96 | "text-field": "{nameSe}"
97 | }
98 | },
99 | {
100 | "id": "icon_aerodrome",
101 | "layout": {
102 | "text-field": "{name_sv}"
103 | }
104 | }
105 | ]
106 | }
--------------------------------------------------------------------------------
/style/hsl-map-theme-print.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "landuse_park",
5 | "paint": {
6 | "fill-color": "#eaf2e0"
7 | }
8 | },
9 | {
10 | "id": "landuse_wood",
11 | "paint": {
12 | "fill-color": "#e3eed4"
13 | }
14 | },
15 | {
16 | "id": "landuse_grass",
17 | "paint": {
18 | "fill-color": "#dfebd0"
19 | }
20 | },
21 | {
22 | "id": "landuse_scrub",
23 | "paint": {
24 | "fill-color": "#d6e5c3"
25 | }
26 | },
27 | {
28 | "id": "landuse_agriculture",
29 | "paint": {
30 | "fill-color": "#eef4dc"
31 | }
32 | },
33 | {
34 | "id": "landuse_cemetery",
35 | "paint": {
36 | "fill-color": "#e0ebd2",
37 | "fill-outline-color": "#d4e3c3"
38 | }
39 | },
40 | {
41 | "id": "landuse_athletics",
42 | "paint": {
43 | "fill-color": "#e1ecd3",
44 | "fill-outline-color": "#cdddb9"
45 | }
46 | },
47 | {
48 | "id": "label_poi_general",
49 | "paint": {
50 | "text-color": "#000"
51 | }
52 | },
53 | {
54 | "id": "label_poi_harbour",
55 | "paint": {
56 | "text-color": "#000"
57 | }
58 | },
59 | {
60 | "id": "label_place_island",
61 | "paint": {
62 | "text-color": "#000"
63 | }
64 | },
65 | {
66 | "id": "label_road_path_cycleway_track_service",
67 | "paint": {
68 | "text-color": "#000"
69 | }
70 | },
71 | {
72 | "id": "label_road_street",
73 | "paint": {
74 | "text-color": "#000"
75 | }
76 | },
77 | {
78 | "id": "label_road_primary",
79 | "paint": {
80 | "text-color": "#000"
81 | }
82 | },
83 | {
84 | "id": "label_place_other",
85 | "paint": {
86 | "text-color": "#000"
87 | }
88 | },
89 | {
90 | "id": "label_place_town",
91 | "paint": {
92 | "text-color": "#000"
93 | }
94 | },
95 | {
96 | "id": "label_place_city",
97 | "paint": {
98 | "text-color": "#000"
99 | }
100 | },
101 | {
102 | "id": "label_country",
103 | "paint": {
104 | "text-color": "#000"
105 | }
106 | }
107 | ]
108 | }
109 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-text-en.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "label_poi_general",
5 | "layout": {
6 | "text-field": "{name_en}"
7 | }
8 | },
9 | {
10 | "id": "label_poi_park",
11 | "layout": {
12 | "text-field": "{name_en}"
13 | }
14 | },
15 | {
16 | "id": "label_poi_harbour",
17 | "layout": {
18 | "text-field": "{name_en}"
19 | }
20 | },
21 | {
22 | "id": "label_water_point",
23 | "layout": {
24 | "text-field": "{name_en}"
25 | }
26 | },
27 | {
28 | "id": "label_water_line",
29 | "layout": {
30 | "text-field": "{name_en}"
31 | }
32 | },
33 | {
34 | "id": "label_place_island",
35 | "layout": {
36 | "text-field": "{name_en}"
37 | }
38 | },
39 | {
40 | "id": "label_road_path_cycleway_track_service",
41 | "layout": {
42 | "text-field": "{name_en}"
43 | }
44 | },
45 | {
46 | "id": "label_road_street",
47 | "layout": {
48 | "text-field": "{name_en}"
49 | }
50 | },
51 | {
52 | "id": "label_road_primary",
53 | "layout": {
54 | "text-field": "{name_en}"
55 | }
56 | },
57 | {
58 | "id": "label_place_other",
59 | "layout": {
60 | "text-field": "{name_en}"
61 | }
62 | },
63 | {
64 | "id": "label_place_town",
65 | "layout": {
66 | "text-field": "{name_en}"
67 | }
68 | },
69 | {
70 | "id": "label_place_city",
71 | "layout": {
72 | "text-field": "{name_en}"
73 | }
74 | },
75 | {
76 | "id": "label_country",
77 | "layout": {
78 | "text-field": "{name_en}"
79 | }
80 | },
81 | {
82 | "id": "icon_subway-station",
83 | "layout": {
84 | "text-field": "{nameFi}"
85 | }
86 | },
87 | {
88 | "id": "icon_bus-station",
89 | "layout": {
90 | "text-field": "{nameFi}"
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "layout": {
96 | "text-field": "{nameFi}"
97 | }
98 | },
99 | {
100 | "id": "icon_aerodrome",
101 | "layout": {
102 | "text-field": "{name_en}"
103 | }
104 | }
105 | ]
106 | }
107 |
--------------------------------------------------------------------------------
/map-icons/icon-terminal-ferry.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/style/hsl-map-style-ticket-sales.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "ticket-sales_icon_sales-point",
5 | "type": "symbol",
6 | "source": "ticket-sales",
7 | "minzoom": 15,
8 | "filter": [
9 | "all",
10 | [
11 | "==",
12 | "$type",
13 | "Point"
14 | ],
15 | [
16 | "in",
17 | "Tyyppi",
18 | "Myyntipiste",
19 | "myyntipiste"
20 | ]
21 | ],
22 | "layout": {
23 | "icon-image": "icon-tickets-sales-point"
24 | }
25 | },
26 | {
27 | "id": "ticket-sales_icon_ticket-machine",
28 | "type": "symbol",
29 | "source": "ticket-sales",
30 | "minzoom": 15,
31 | "filter": [
32 | "all",
33 | [
34 | "==",
35 | "$type",
36 | "Point"
37 | ],
38 | [
39 | "in",
40 | "Tyyppi",
41 | "Kertalippuautomaatti",
42 | "Monilippuautomaatti"
43 | ]
44 | ],
45 | "layout": {
46 | "icon-image": "icon-tickets-machine"
47 | }
48 | },
49 | {
50 | "id": "ticket-sales_icon_ticket-machine-parking",
51 | "type": "symbol",
52 | "source": "ticket-sales",
53 | "minzoom": 15,
54 | "filter": [
55 | "all",
56 | [
57 | "==",
58 | "$type",
59 | "Point"
60 | ],
61 | [
62 | "==",
63 | "Tyyppi",
64 | "Pysäköintiautomaatti"
65 | ]
66 | ],
67 | "layout": {
68 | "icon-image": "icon-tickets-machine-parking",
69 | "visibility": "none"
70 | }
71 | },
72 | {
73 | "id": "ticket-sales_icon_service-point",
74 | "type": "symbol",
75 | "source": "ticket-sales",
76 | "minzoom": 15,
77 | "filter": [
78 | "all",
79 | [
80 | "==",
81 | "$type",
82 | "Point"
83 | ],
84 | [
85 | "==",
86 | "Tyyppi",
87 | "Palvelupiste"
88 | ]
89 | ],
90 | "layout": {
91 | "icon-image": "icon-tickets-service-point"
92 | }
93 | }
94 | ],
95 | "sources": {
96 | "ticket-sales": {
97 | "data": "https://data-hslhrt.opendata.arcgis.com/datasets/f9388fc8a8f848fda3bc584b607afe97_0.geojson",
98 | "type": "geojson"
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/map-icons/icon-park-and-ride.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
32 |
--------------------------------------------------------------------------------
/cli/static/text-fisv.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "label_poi_general",
5 | "layout": {
6 | "text-field": "{name}\n{name_sv_nodefault}"
7 | }
8 | },
9 | {
10 | "id": "label_poi_park",
11 | "layout": {
12 | "text-field": "{name}\n{name_sv_nodefault}"
13 | }
14 | },
15 | {
16 | "id": "label_poi_harbour",
17 | "layout": {
18 | "text-field": "{name}\n{name_sv_nodefault}"
19 | }
20 | },
21 | {
22 | "id": "label_water_point",
23 | "layout": {
24 | "text-field": "{name}\n{name_sv_nodefault}"
25 | }
26 | },
27 | {
28 | "id": "label_water_line",
29 | "layout": {
30 | "text-field": "{name}\n{name_sv_nodefault}"
31 | }
32 | },
33 | {
34 | "id": "label_place_island",
35 | "layout": {
36 | "text-field": "{name}\n{name_sv_nodefault}"
37 | }
38 | },
39 | {
40 | "id": "label_road_path_cycleway_track_service",
41 | "layout": {
42 | "text-field": "{name} {name_sv_nodefault}"
43 | }
44 | },
45 | {
46 | "id": "label_road_street",
47 | "layout": {
48 | "text-field": "{name} {name_sv_nodefault}"
49 | }
50 | },
51 | {
52 | "id": "label_road_primary",
53 | "layout": {
54 | "text-field": "{name} {name_sv_nodefault}"
55 | }
56 | },
57 | {
58 | "id": "label_place_other",
59 | "layout": {
60 | "text-field": "{name}\n{name_sv_nodefault}"
61 | }
62 | },
63 | {
64 | "id": "label_place_city",
65 | "layout": {
66 | "text-field": "{name}\n{name_sv_nodefault}"
67 | }
68 | },
69 | {
70 | "id": "label_place_town",
71 | "layout": {
72 | "text-field": "{name}\n{name_sv_nodefault}"
73 | }
74 | },
75 | {
76 | "id": "label_country",
77 | "layout": {
78 | "text-field": "{name}\n{name_sv_nodefault}"
79 | }
80 | },
81 | {
82 | "id": "icon_subway-station",
83 | "layout": {
84 | "text-field": "{nameFi}\n{nameSe}"
85 | }
86 | },
87 | {
88 | "id": "icon_bus-station",
89 | "layout": {
90 | "text-field": "{nameFi}\n{nameSe}"
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "layout": {
96 | "text-field": "{nameFi}\n{nameSe}"
97 | }
98 | },
99 | {
100 | "id": "icon_aerodrome",
101 | "layout": {
102 | "text-field": "{name}\n{name_sv_nodefault}"
103 | }
104 | }
105 | ]
106 | }
--------------------------------------------------------------------------------
/style/hsl-map-theme-text-fisv.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "label_poi_general",
5 | "layout": {
6 | "text-field": "{name}\n{name_sv_nodefault}"
7 | }
8 | },
9 | {
10 | "id": "label_poi_park",
11 | "layout": {
12 | "text-field": "{name}\n{name_sv_nodefault}"
13 | }
14 | },
15 | {
16 | "id": "label_poi_harbour",
17 | "layout": {
18 | "text-field": "{name}\n{name_sv_nodefault}"
19 | }
20 | },
21 | {
22 | "id": "label_water_point",
23 | "layout": {
24 | "text-field": "{name}\n{name_sv_nodefault}"
25 | }
26 | },
27 | {
28 | "id": "label_water_line",
29 | "layout": {
30 | "text-field": "{name}\n{name_sv_nodefault}"
31 | }
32 | },
33 | {
34 | "id": "label_place_island",
35 | "layout": {
36 | "text-field": "{name}\n{name_sv_nodefault}"
37 | }
38 | },
39 | {
40 | "id": "label_road_path_cycleway_track_service",
41 | "layout": {
42 | "text-field": "{name} {name_sv_nodefault}"
43 | }
44 | },
45 | {
46 | "id": "label_road_street",
47 | "layout": {
48 | "text-field": "{name} {name_sv_nodefault}"
49 | }
50 | },
51 | {
52 | "id": "label_road_primary",
53 | "layout": {
54 | "text-field": "{name} {name_sv_nodefault}"
55 | }
56 | },
57 | {
58 | "id": "label_place_other",
59 | "layout": {
60 | "text-field": "{name}\n{name_sv_nodefault}"
61 | }
62 | },
63 | {
64 | "id": "label_place_city",
65 | "layout": {
66 | "text-field": "{name}\n{name_sv_nodefault}"
67 | }
68 | },
69 | {
70 | "id": "label_place_town",
71 | "layout": {
72 | "text-field": "{name}\n{name_sv_nodefault}"
73 | }
74 | },
75 | {
76 | "id": "label_country",
77 | "layout": {
78 | "text-field": "{name}\n{name_sv_nodefault}"
79 | }
80 | },
81 | {
82 | "id": "icon_subway-station",
83 | "layout": {
84 | "text-field": "{nameFi}\n{nameSe}"
85 | }
86 | },
87 | {
88 | "id": "icon_bus-station",
89 | "layout": {
90 | "text-field": "{nameFi}\n{nameSe}"
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "layout": {
96 | "text-field": "{nameFi}\n{nameSe}"
97 | }
98 | },
99 | {
100 | "id": "icon_aerodrome",
101 | "layout": {
102 | "text-field": "{name}\n{name_sv_nodefault}"
103 | }
104 | }
105 | ]
106 | }
--------------------------------------------------------------------------------
/cli/static/simplified.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "road_service_area",
5 | "minzoom": 14
6 | },
7 | {
8 | "id": "building_shadow",
9 | "minzoom": 17
10 | },
11 | {
12 | "id": "building",
13 | "minzoom": 16
14 | },
15 | {
16 | "id": "tunnel_walk",
17 | "minzoom": 17
18 | },
19 | {
20 | "id": "tunnel_cycleway",
21 | "minzoom": 16
22 | },
23 | {
24 | "id": "tunnel_street",
25 | "minzoom": 13
26 | },
27 | {
28 | "id": "road_path",
29 | "minzoom": 16
30 | },
31 | {
32 | "id": "road_path_steps_case",
33 | "minzoom": 16
34 | },
35 | {
36 | "id": "road_path_steps",
37 | "minzoom": 16
38 | },
39 | {
40 | "id": "road_cycleway_track",
41 | "minzoom": 15
42 | },
43 | {
44 | "id": "road_service",
45 | "minzoom": 14
46 | },
47 | {
48 | "id": "road_street_case",
49 | "minzoom": 13
50 | },
51 | {
52 | "id": "road_street",
53 | "minzoom": 13
54 | },
55 | {
56 | "id": "bridge_path_case",
57 | "minzoom": 16
58 | },
59 | {
60 | "id": "bridge_path_bg",
61 | "minzoom": 16
62 | },
63 | {
64 | "id": "bridge_path",
65 | "minzoom": 16
66 | },
67 | {
68 | "id": "bridge_cycleway_track_case",
69 | "minzoom": 15
70 | },
71 | {
72 | "id": "bridge_cycleway_track_bg",
73 | "minzoom": 15
74 | },
75 | {
76 | "id": "bridge_cycleway_track",
77 | "minzoom": 15
78 | },
79 | {
80 | "id": "bridge_service_case",
81 | "minzoom": 14
82 | },
83 | {
84 | "id": "bridge_service_bg",
85 | "minzoom": 14
86 | },
87 | {
88 | "id": "bridge_service",
89 | "minzoom": 14
90 | },
91 | {
92 | "id": "bridge_street",
93 | "minzoom": 13
94 | },
95 | {
96 | "id": "label_housenum",
97 | "minzoom": 17
98 | },
99 | {
100 | "id": "label_poi_general",
101 | "minzoom": 15
102 | },
103 | {
104 | "id": "label_poi_park",
105 | "minzoom": 14
106 | },
107 | {
108 | "id": "label_road_path_cycleway_track_service",
109 | "minzoom": 16
110 | },
111 | {
112 | "id": "label_road_street",
113 | "minzoom": 13
114 | },
115 | {
116 | "id": "label_place_other",
117 | "layout": {
118 | "text-font": ["Gotham Rounded Medium"]
119 | }
120 | },
121 | {
122 | "id": "label_place_town",
123 | "layout": {
124 | "text-font": ["Gotham Rounded Medium"]
125 | }
126 | },
127 | {
128 | "id": "label_place_city",
129 | "paint": {
130 | "text-color": "#333",
131 | "text-halo-width": 0.5
132 | }
133 | }
134 | ]
135 | }
--------------------------------------------------------------------------------
/style/hsl-map-theme-simplified.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "road_service_area",
5 | "minzoom": 14
6 | },
7 | {
8 | "id": "building_shadow",
9 | "minzoom": 17
10 | },
11 | {
12 | "id": "building",
13 | "minzoom": 16
14 | },
15 | {
16 | "id": "tunnel_walk",
17 | "minzoom": 17
18 | },
19 | {
20 | "id": "tunnel_cycleway",
21 | "minzoom": 16
22 | },
23 | {
24 | "id": "tunnel_street",
25 | "minzoom": 13
26 | },
27 | {
28 | "id": "road_path",
29 | "minzoom": 16
30 | },
31 | {
32 | "id": "road_path_steps_case",
33 | "minzoom": 16
34 | },
35 | {
36 | "id": "road_path_steps",
37 | "minzoom": 16
38 | },
39 | {
40 | "id": "road_cycleway_track",
41 | "minzoom": 15
42 | },
43 | {
44 | "id": "road_service",
45 | "minzoom": 14
46 | },
47 | {
48 | "id": "road_street_case",
49 | "minzoom": 13
50 | },
51 | {
52 | "id": "road_street",
53 | "minzoom": 13
54 | },
55 | {
56 | "id": "bridge_path_case",
57 | "minzoom": 16
58 | },
59 | {
60 | "id": "bridge_path_bg",
61 | "minzoom": 16
62 | },
63 | {
64 | "id": "bridge_path",
65 | "minzoom": 16
66 | },
67 | {
68 | "id": "bridge_cycleway_track_case",
69 | "minzoom": 15
70 | },
71 | {
72 | "id": "bridge_cycleway_track_bg",
73 | "minzoom": 15
74 | },
75 | {
76 | "id": "bridge_cycleway_track",
77 | "minzoom": 15
78 | },
79 | {
80 | "id": "bridge_service_case",
81 | "minzoom": 14
82 | },
83 | {
84 | "id": "bridge_service_bg",
85 | "minzoom": 14
86 | },
87 | {
88 | "id": "bridge_service",
89 | "minzoom": 14
90 | },
91 | {
92 | "id": "bridge_street",
93 | "minzoom": 13
94 | },
95 | {
96 | "id": "label_housenum",
97 | "minzoom": 17
98 | },
99 | {
100 | "id": "label_poi_general",
101 | "minzoom": 15
102 | },
103 | {
104 | "id": "label_poi_park",
105 | "minzoom": 14
106 | },
107 | {
108 | "id": "label_road_path_cycleway_track_service",
109 | "minzoom": 16
110 | },
111 | {
112 | "id": "label_road_street",
113 | "minzoom": 13
114 | },
115 | {
116 | "id": "label_place_other",
117 | "layout": {
118 | "text-font": ["Gotham Rounded Medium"]
119 | }
120 | },
121 | {
122 | "id": "label_place_town",
123 | "layout": {
124 | "text-font": ["Gotham Rounded Medium"]
125 | }
126 | },
127 | {
128 | "id": "label_place_city",
129 | "paint": {
130 | "text-color": "#333",
131 | "text-halo-width": 0.5
132 | }
133 | }
134 | ]
135 | }
--------------------------------------------------------------------------------
/cli/fileMappings.js:
--------------------------------------------------------------------------------
1 | const some = require("lodash/some");
2 | const reduce = require("lodash/reduce");
3 | const get = require("lodash/get");
4 |
5 | const select = (values, value) => some(values, (val) => val === value);
6 | const inGroups = (values, value) => some(values, (val) => value.startsWith(val));
7 |
8 | /**
9 | * Map layers to files. FileMappers is a map of file names and the criteria
10 | * a layer has to fulfill with its id or source-layer property to be included
11 | * in the file. The criteria can be either a function that returns a boolean
12 | * to indicate whether or not the layer should be included, or an array of
13 | * strings that the layer's id or source-layer prop should match.
14 | *
15 | * The order is important. Later file matchers override earlier ones. For a
16 | * layer called "rail_tunnel", and the files "routes" and "base", the layer
17 | * will be included in the "base" file if both criterias match.
18 | */
19 |
20 | const fileMappers = {
21 | base: (value) => {
22 | const names = ["background", "admin_country"];
23 | const groups = [
24 | "landuse",
25 | "water",
26 | "aeroway",
27 | "building",
28 | "road",
29 | "tunnel",
30 | "bridge",
31 | ];
32 | if (inGroups(groups, value)) {
33 | return true;
34 | }
35 | return select(names, value);
36 | },
37 | "municipal-borders": ["municipal_border"],
38 | routes: (value) => inGroups(["route"], value),
39 | stops: (value) => inGroups(["stops"], value),
40 | "ticket-zones": (value) => inGroups(["ticket-zones"], value),
41 | "ticket-zone-labels": (value) => inGroups(["ticket-zone-label"], value),
42 | text: (value) => inGroups(["label"], value),
43 | "subway-entrance": (value) => inGroups(["subway-entrance"], value),
44 | icon: (value) => inGroups(["icon"], value),
45 | "park-and-ride": (value) => inGroups(["park-and-ride"], value),
46 | "ticket-sales": (value) => inGroups(["ticket-sales"], value),
47 | citybikes: (value) => inGroups(["citybike"], value),
48 | };
49 |
50 | function layerToFile(layer) {
51 | const sourceLayer = get(layer, "source-layer", "base");
52 | const layerId = get(layer, "id", "base");
53 |
54 | return reduce(
55 | fileMappers,
56 | (groupName, match, layerGroupName) => {
57 | const matchToGroup = (val) => {
58 | if (typeof match === "function") {
59 | return match(val);
60 | }
61 | if (Array.isArray(match)) {
62 | return select(match, val);
63 | }
64 |
65 | return false;
66 | };
67 |
68 | // The matchers will be called with the sourceLayer first, and then the layerId.
69 | let isInGroup = matchToGroup(sourceLayer);
70 |
71 | if (!isInGroup) {
72 | isInGroup = matchToGroup(layerId);
73 | }
74 |
75 | if (isInGroup) {
76 | return layerGroupName;
77 | }
78 |
79 | return groupName;
80 | },
81 | sourceLayer
82 | );
83 | }
84 |
85 | module.exports = layerToFile;
86 |
--------------------------------------------------------------------------------
/map-icons/icon-citybike-station.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
33 |
--------------------------------------------------------------------------------
/cli/static/driver-info.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "stops_case",
5 | "source": "stops-by-routes",
6 | "minzoom": 0,
7 | "filter": ["==", ["get", "timingStopType"], 0],
8 | "paint": {
9 | "circle-radius": 9
10 | }
11 | },
12 | {
13 | "id": "stops_rail_case",
14 | "source": "stops-by-routes",
15 | "minzoom": 0,
16 | "filter": ["==", ["get", "timingStopType"], 0],
17 | "paint": {
18 | "circle-radius": 9
19 | }
20 | },
21 | {
22 | "id": "stops_rail",
23 | "source": "stops-by-routes",
24 | "minzoom": 0,
25 | "filter": ["==", ["get", "timingStopType"], 0],
26 | "paint": {
27 | "circle-radius": 8
28 | }
29 | },
30 | {
31 | "id": "stops_bus",
32 | "source": "stops-by-routes",
33 | "minzoom": 0,
34 | "filter": ["==", ["get", "timingStopType"], 0],
35 | "paint": {
36 | "circle-radius": 8
37 | }
38 | },
39 | {
40 | "id": "stops_trunk",
41 | "source": "stops-by-routes",
42 | "minzoom": 0,
43 | "filter": ["==", ["get", "timingStopType"], 0],
44 | "paint": {
45 | "circle-radius": 8
46 | }
47 | },
48 | {
49 | "id": "stops_ferry",
50 | "source": "stops-by-routes",
51 | "minzoom": 0,
52 | "filter": ["==", ["get", "timingStopType"], 0],
53 | "paint": {
54 | "circle-radius": 8
55 | }
56 | },
57 | {
58 | "id": "stops_tram",
59 | "source": "stops-by-routes",
60 | "minzoom": 0,
61 | "filter": ["==", ["get", "timingStopType"], 0],
62 | "paint": {
63 | "circle-radius": 8
64 | }
65 | },
66 | {
67 | "id": "stops_lrail",
68 | "source": "stops-by-routes",
69 | "minzoom": 0,
70 | "filter": ["==", ["get", "timingStopType"], 0],
71 | "paint": {
72 | "circle-radius": 8
73 | }
74 | },
75 | {
76 | "id": "stops_subway",
77 | "source": "stops-by-routes",
78 | "minzoom": 0,
79 | "filter": ["==", ["get", "timingStopType"], 0],
80 | "paint": {
81 | "circle-radius": 8
82 | }
83 | },
84 | {
85 | "id": "stops_hub",
86 | "source": "stops-by-routes",
87 | "minzoom": 0,
88 | "filter": ["==", ["get", "timingStopType"], 0],
89 | "paint": {
90 | "circle-radius": 5.5
91 | }
92 | },
93 | {
94 | "id": "stops_rail_hub",
95 | "source": "stops-by-routes",
96 | "minzoom": 0,
97 | "filter": ["==", ["get", "timingStopType"], 0],
98 | "paint": {
99 | "circle-radius": 5.5
100 | }
101 | },
102 | {
103 | "id": "stops_timing_icon",
104 | "minzoom": 0,
105 | "layout": {
106 | "visibility": "visible"
107 | }
108 | },
109 | {
110 | "id": "stops_start_icon",
111 | "minzoom": 0,
112 | "layout": {
113 | "visibility": "visible"
114 | }
115 | }
116 | ]
117 | }
118 |
--------------------------------------------------------------------------------
/style/hsl-map-theme-driver-info.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "stops_case",
5 | "source": "stops-by-routes",
6 | "minzoom": 0,
7 | "filter": ["==", ["get", "timingStopType"], 0],
8 | "paint": {
9 | "circle-radius": 9
10 | }
11 | },
12 | {
13 | "id": "stops_rail_case",
14 | "source": "stops-by-routes",
15 | "minzoom": 0,
16 | "filter": ["==", ["get", "timingStopType"], 0],
17 | "paint": {
18 | "circle-radius": 9
19 | }
20 | },
21 | {
22 | "id": "stops_rail",
23 | "source": "stops-by-routes",
24 | "minzoom": 0,
25 | "filter": ["==", ["get", "timingStopType"], 0],
26 | "paint": {
27 | "circle-radius": 8
28 | }
29 | },
30 | {
31 | "id": "stops_bus",
32 | "source": "stops-by-routes",
33 | "minzoom": 0,
34 | "filter": ["==", ["get", "timingStopType"], 0],
35 | "paint": {
36 | "circle-radius": 8
37 | }
38 | },
39 | {
40 | "id": "stops_trunk",
41 | "source": "stops-by-routes",
42 | "minzoom": 0,
43 | "filter": ["==", ["get", "timingStopType"], 0],
44 | "paint": {
45 | "circle-radius": 8
46 | }
47 | },
48 | {
49 | "id": "stops_ferry",
50 | "source": "stops-by-routes",
51 | "minzoom": 0,
52 | "filter": ["==", ["get", "timingStopType"], 0],
53 | "paint": {
54 | "circle-radius": 8
55 | }
56 | },
57 | {
58 | "id": "stops_tram",
59 | "source": "stops-by-routes",
60 | "minzoom": 0,
61 | "filter": ["==", ["get", "timingStopType"], 0],
62 | "paint": {
63 | "circle-radius": 8
64 | }
65 | },
66 | {
67 | "id": "stops_lrail",
68 | "source": "stops-by-routes",
69 | "minzoom": 0,
70 | "filter": ["==", ["get", "timingStopType"], 0],
71 | "paint": {
72 | "circle-radius": 8
73 | }
74 | },
75 | {
76 | "id": "stops_subway",
77 | "source": "stops-by-routes",
78 | "minzoom": 0,
79 | "filter": ["==", ["get", "timingStopType"], 0],
80 | "paint": {
81 | "circle-radius": 8
82 | }
83 | },
84 | {
85 | "id": "stops_hub",
86 | "source": "stops-by-routes",
87 | "minzoom": 0,
88 | "filter": ["==", ["get", "timingStopType"], 0],
89 | "paint": {
90 | "circle-radius": 5.5
91 | }
92 | },
93 | {
94 | "id": "stops_rail_hub",
95 | "source": "stops-by-routes",
96 | "minzoom": 0,
97 | "filter": ["==", ["get", "timingStopType"], 0],
98 | "paint": {
99 | "circle-radius": 5.5
100 | }
101 | },
102 | {
103 | "id": "stops_timing_icon",
104 | "minzoom": 0,
105 | "layout": {
106 | "visibility": "visible"
107 | }
108 | },
109 | {
110 | "id": "stops_start_icon",
111 | "minzoom": 0,
112 | "layout": {
113 | "visibility": "visible"
114 | }
115 | }
116 | ]
117 | }
118 |
--------------------------------------------------------------------------------
/map-icons/icon-entrance-lift.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
35 |
--------------------------------------------------------------------------------
/map-icons/icon-tickets-sales-point.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/map-icons/icon-tickets-service-point.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
34 |
--------------------------------------------------------------------------------
/data/ticket-zone-labels.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "name": "Ticket zone labels",
4 | "description": "This file contains a set of predefined points to render ticket labels.",
5 | "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
6 | "features": [
7 | {
8 | "type": "Feature",
9 | "properties": {
10 | "Zone": "A"
11 | },
12 | "geometry": {
13 | "type": "Point",
14 | "coordinates": [24.927, 60.19]
15 | }
16 | },
17 | {
18 | "type": "Feature",
19 | "properties": {
20 | "Zone": "B"
21 | },
22 | "geometry": {
23 | "type": "Point",
24 | "coordinates": [24.925, 60.258]
25 | }
26 | },
27 | {
28 | "type": "Feature",
29 | "properties": {
30 | "Zone": "B"
31 | },
32 | "geometry": {
33 | "type": "Point",
34 | "coordinates": [24.78, 60.202]
35 | }
36 | },
37 | {
38 | "type": "Feature",
39 | "properties": {
40 | "Zone": "B"
41 | },
42 | "geometry": {
43 | "type": "Point",
44 | "coordinates": [25.09, 60.213]
45 | }
46 | },
47 | {
48 | "type": "Feature",
49 | "properties": {
50 | "Zone": "C"
51 | },
52 | "geometry": {
53 | "type": "Point",
54 | "coordinates": [25.1794, 60.264]
55 | }
56 | },
57 | {
58 | "type": "Feature",
59 | "properties": {
60 | "Zone": "C"
61 | },
62 | "geometry": {
63 | "type": "Point",
64 | "coordinates": [24.791, 60.323]
65 | }
66 | },
67 | {
68 | "type": "Feature",
69 | "properties": {
70 | "Zone": "C"
71 | },
72 | "geometry": {
73 | "type": "Point",
74 | "coordinates": [25.038, 60.33]
75 | }
76 | },
77 | {
78 | "type": "Feature",
79 | "properties": {
80 | "Zone": "C"
81 | },
82 | "geometry": {
83 | "type": "Point",
84 | "coordinates": [24.63, 60.25]
85 | }
86 | },
87 | {
88 | "type": "Feature",
89 | "properties": {
90 | "Zone": "D"
91 | },
92 | "geometry": {
93 | "type": "Point",
94 | "coordinates": [24.98, 60.415]
95 | }
96 | },
97 | {
98 | "type": "Feature",
99 | "properties": {
100 | "Zone": "D"
101 | },
102 | "geometry": {
103 | "type": "Point",
104 | "coordinates": [25.228, 60.401]
105 | }
106 | },
107 | {
108 | "type": "Feature",
109 | "properties": {
110 | "Zone": "D"
111 | },
112 | "geometry": {
113 | "type": "Point",
114 | "coordinates": [25.331, 60.31]
115 | }
116 | },
117 | {
118 | "type": "Feature",
119 | "properties": {
120 | "Zone": "D"
121 | },
122 | "geometry": {
123 | "type": "Point",
124 | "coordinates": [24.371, 60.18]
125 | }
126 | },
127 | {
128 | "type": "Feature",
129 | "properties": {
130 | "Zone": "D"
131 | },
132 | "geometry": {
133 | "type": "Point",
134 | "coordinates": [24.5, 60.091]
135 | }
136 | }
137 | ]
138 | }
--------------------------------------------------------------------------------
/cli/split.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const fs = require("fs-extra");
3 | const get = require("lodash/get");
4 | const set = require("lodash/set");
5 | const reduce = require("lodash/reduce");
6 | const merge = require("lodash/merge");
7 | const layerToFile = require("./fileMappings");
8 |
9 | const FILENAME_PREFIX = "hsl-map-";
10 |
11 | module.exports = async function(file, dir) {
12 | const filePath = path.resolve(process.cwd(), file);
13 | const outputPath = path.resolve(process.cwd(), dir);
14 | const staticPath = path.resolve(__dirname, "static");
15 |
16 | const writeFile = async (name, content) => {
17 | await fs.writeJson(path.resolve(outputPath, FILENAME_PREFIX + name), content, {
18 | spaces: 2,
19 | });
20 | };
21 |
22 | await fs.mkdirp(outputPath);
23 |
24 | const styleJson = await fs.readJson(filePath);
25 | const mapboxGroups = get(styleJson, "metadata.mapbox:groups", {});
26 | const sources = get(styleJson, "sources", {});
27 | const layers = get(styleJson, "layers", []);
28 |
29 | console.log("Resetting style wrapper...");
30 |
31 | // Reset these to empty things
32 | set(styleJson, "metadata.mapbox-groups", {});
33 | set(styleJson, "sources", {});
34 | set(styleJson, "layers", []);
35 |
36 | console.log("Writing style wrapper...");
37 |
38 | await writeFile("template.json", styleJson);
39 |
40 | console.log("Splitting layers...");
41 |
42 | // Determine which layers go into which files.
43 | const layerGroups = reduce(
44 | layers,
45 | (groups, layer) => {
46 | const fileGroup = layerToFile(layer);
47 |
48 | if (!(fileGroup in groups)) {
49 | set(groups, fileGroup, []);
50 | }
51 |
52 | groups[fileGroup].push(layer);
53 | return groups;
54 | },
55 | {}
56 | );
57 |
58 | // Create the json structure that will be written into the file
59 | const fileGroups = reduce(
60 | layerGroups,
61 | (files, groupLayers, groupName) => {
62 | const container = {
63 | layers: groupLayers,
64 | };
65 |
66 | groupLayers.forEach((layer) => {
67 | const source = get(layer, "source");
68 | const mapboxGroup = get(layer, "metadata.mapbox:group", "");
69 |
70 | if (source) {
71 | merge(container, {
72 | sources: { [source]: sources[source] },
73 | });
74 | }
75 |
76 | if (mapboxGroup) {
77 | merge(container, {
78 | metadata: {
79 | "mapbox:groups": { [mapboxGroup]: mapboxGroups[mapboxGroup] },
80 | },
81 | });
82 | }
83 | });
84 |
85 | files.push({ name: groupName, content: container });
86 | return files;
87 | },
88 | []
89 | );
90 |
91 | const writePromises = fileGroups.map((styleFile) => {
92 | console.log("Writing file %s", styleFile.name);
93 | return writeFile(`style-${styleFile.name}.json`, styleFile.content);
94 | });
95 |
96 | const staticFiles = await fs.readdir(staticPath);
97 |
98 | staticFiles.forEach((staticFile) => {
99 | writePromises.push(
100 | fs.copy(
101 | path.resolve(staticPath, staticFile),
102 | path.resolve(outputPath, `${FILENAME_PREFIX}theme-${staticFile}`)
103 | )
104 | );
105 | });
106 |
107 | await Promise.all(writePromises);
108 |
109 | process.exit(0);
110 | };
111 |
--------------------------------------------------------------------------------
/map-icons/icon-stop-bus.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-wetland.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
39 |
--------------------------------------------------------------------------------
/map-icons/icon-stop-tram.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-terminal-train.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/style/hsl-map-style-subway-entrance.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "subway-entrance_icon",
5 | "type": "symbol",
6 | "source": "vector",
7 | "source-layer": "poi",
8 | "minzoom": 16,
9 | "filter": [
10 | "all",
11 | [
12 | "==",
13 | "$type",
14 | "Point"
15 | ],
16 | [
17 | "in",
18 | "class",
19 | "entrance"
20 | ],
21 | [
22 | "in",
23 | "subclass",
24 | "subway_entrance"
25 | ]
26 | ],
27 | "layout": {
28 | "icon-image": "icon-entrance-subway",
29 | "icon-allow-overlap": true,
30 | "icon-anchor": "bottom",
31 | "icon-size": [
32 | "interpolate",
33 | [
34 | "exponential",
35 | 1.15
36 | ],
37 | [
38 | "zoom"
39 | ],
40 | 15,
41 | 0.533,
42 | 20,
43 | 0.8
44 | ]
45 | },
46 | "paint": {
47 | "icon-translate": [
48 | 0,
49 | -5.25
50 | ]
51 | }
52 | },
53 | {
54 | "id": "subway-entrance_letter",
55 | "type": "symbol",
56 | "source": "vector",
57 | "source-layer": "poi",
58 | "minzoom": 17,
59 | "filter": [
60 | "all",
61 | [
62 | "==",
63 | "$type",
64 | "Point"
65 | ],
66 | [
67 | "in",
68 | "class",
69 | "entrance"
70 | ],
71 | [
72 | "in",
73 | "subclass",
74 | "subway_entrance"
75 | ],
76 | [
77 | "has",
78 | "ref"
79 | ]
80 | ],
81 | "layout": {
82 | "icon-image": [
83 | "concat",
84 | "icon-letter-",
85 | [
86 | "get",
87 | "ref"
88 | ]
89 | ],
90 | "icon-allow-overlap": true,
91 | "icon-anchor": "bottom",
92 | "icon-size": [
93 | "interpolate",
94 | [
95 | "exponential",
96 | 1.15
97 | ],
98 | [
99 | "zoom"
100 | ],
101 | 13,
102 | 0.8,
103 | 20,
104 | 1.2
105 | ]
106 | },
107 | "paint": {
108 | "icon-translate": [
109 | 0,
110 | -5.25
111 | ]
112 | }
113 | },
114 | {
115 | "id": "subway-entrance_accessibility",
116 | "type": "symbol",
117 | "source": "vector",
118 | "source-layer": "poi",
119 | "minzoom": 17,
120 | "filter": [
121 | "all",
122 | [
123 | "==",
124 | "$type",
125 | "Point"
126 | ],
127 | [
128 | "in",
129 | "class",
130 | "entrance"
131 | ],
132 | [
133 | "in",
134 | "subclass",
135 | "subway_entrance"
136 | ],
137 | [
138 | "==",
139 | "wheelchair",
140 | 1
141 | ]
142 | ],
143 | "layout": {
144 | "icon-image": "icon-entrance-wheelchair",
145 | "icon-allow-overlap": true,
146 | "icon-anchor": "top",
147 | "icon-size": [
148 | "interpolate",
149 | [
150 | "exponential",
151 | 1.15
152 | ],
153 | [
154 | "zoom"
155 | ],
156 | 13,
157 | 0.8,
158 | 20,
159 | 1.2
160 | ]
161 | },
162 | "paint": {
163 | "icon-translate": [
164 | 0,
165 | -5.25
166 | ]
167 | }
168 | }
169 | ],
170 | "sources": {
171 | "vector": {
172 | "type": "vector",
173 | "url": "https://api.digitransit.fi/map/v3/hsl-vector-map/index.json"
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/map-icons/icon-stop-train.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-tickets-machine-parking.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/style/hsl-map-style-icon.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers": [
3 | {
4 | "id": "icon_bus-station",
5 | "type": "symbol",
6 | "source": "terminals",
7 | "source-layer": "terminals",
8 | "minzoom": 11,
9 | "filter": [
10 | "all",
11 | [
12 | "==",
13 | "$type",
14 | "Point"
15 | ],
16 | [
17 | "==",
18 | "mode",
19 | "BUS"
20 | ]
21 | ],
22 | "layout": {
23 | "text-optional": true,
24 | "text-size": 10,
25 | "text-field": "{nameFi}",
26 | "text-font": [
27 | "Gotham Rounded Medium"
28 | ],
29 | "text-anchor": "top",
30 | "text-max-width": 8,
31 | "text-offset": [
32 | 0,
33 | 0.5
34 | ],
35 | "icon-image": "icon-terminal-bus",
36 | "icon-size": 0.9
37 | },
38 | "paint": {
39 | "text-color": "#666",
40 | "text-halo-color": "#fff",
41 | "text-halo-width": 1,
42 | "icon-translate": [
43 | 0,
44 | -5.25
45 | ]
46 | }
47 | },
48 | {
49 | "id": "icon_subway-station",
50 | "type": "symbol",
51 | "source": "terminals",
52 | "source-layer": "terminals",
53 | "minzoom": 11,
54 | "filter": [
55 | "all",
56 | [
57 | "==",
58 | "$type",
59 | "Point"
60 | ],
61 | [
62 | "==",
63 | "mode",
64 | "SUBWAY"
65 | ]
66 | ],
67 | "layout": {
68 | "text-optional": true,
69 | "text-size": 10,
70 | "text-field": "{nameFi}",
71 | "text-font": [
72 | "Gotham Rounded Medium"
73 | ],
74 | "text-anchor": "top",
75 | "text-max-width": 8,
76 | "text-offset": [
77 | 0,
78 | 0.5
79 | ],
80 | "icon-image": "icon-terminal-subway",
81 | "icon-size": 0.9
82 | },
83 | "paint": {
84 | "text-color": "#666",
85 | "text-halo-color": "#fff",
86 | "text-halo-width": 1,
87 | "icon-translate": [
88 | 0,
89 | -5.25
90 | ]
91 | }
92 | },
93 | {
94 | "id": "icon_railway-station",
95 | "type": "symbol",
96 | "source": "terminals",
97 | "source-layer": "terminals",
98 | "minzoom": 11,
99 | "filter": [
100 | "all",
101 | [
102 | "==",
103 | "$type",
104 | "Point"
105 | ],
106 | [
107 | "==",
108 | "mode",
109 | "RAIL"
110 | ]
111 | ],
112 | "layout": {
113 | "text-optional": true,
114 | "text-size": 10,
115 | "text-field": "{nameFi}",
116 | "text-font": [
117 | "Gotham Rounded Medium"
118 | ],
119 | "text-anchor": "top",
120 | "text-max-width": 8,
121 | "text-offset": [
122 | 0,
123 | 0.75
124 | ],
125 | "icon-image": "icon-terminal-train",
126 | "icon-size": 0.9
127 | },
128 | "paint": {
129 | "text-color": "#666",
130 | "text-halo-color": "#fff",
131 | "text-halo-width": 1,
132 | "icon-translate": [
133 | 0,
134 | -5.25
135 | ]
136 | }
137 | },
138 | {
139 | "id": "icon_aerodrome",
140 | "type": "symbol",
141 | "source": "vector",
142 | "source-layer": "aerodrome_label",
143 | "minzoom": 5,
144 | "filter": [
145 | "all",
146 | [
147 | "==",
148 | "$type",
149 | "Point"
150 | ],
151 | [
152 | "in",
153 | "class",
154 | "international",
155 | "public",
156 | "regional"
157 | ]
158 | ],
159 | "layout": {
160 | "text-optional": true,
161 | "text-size": 10,
162 | "text-field": "{name}",
163 | "text-font": [
164 | "Gotham Rounded Medium"
165 | ],
166 | "text-anchor": "top",
167 | "text-max-width": 8,
168 | "text-offset": [
169 | 0,
170 | 0.5
171 | ],
172 | "icon-image": "icon-terminal-aerodrome",
173 | "icon-size": 0.9
174 | },
175 | "paint": {
176 | "text-color": "#666",
177 | "text-halo-color": "#fff",
178 | "text-halo-width": 1,
179 | "icon-translate": [
180 | 0,
181 | -5.25
182 | ]
183 | }
184 | }
185 | ],
186 | "sources": {
187 | "terminals": {
188 | "url": "https://kartat.hsl.fi/jore/tiles/terminals/index.json",
189 | "type": "vector"
190 | },
191 | "vector": {
192 | "type": "vector",
193 | "url": "https://api.digitransit.fi/map/v3/hsl-vector-map/index.json"
194 | }
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/map-icons/icon-stop-ferry.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-citybike-station2.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-stop-hybrid.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/map-icons/icon-terminal-ship.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------