diff --git a/biome.json b/biome.json
index 4bc75d2b..fae07516 100644
--- a/biome.json
+++ b/biome.json
@@ -3,6 +3,7 @@
"indentStyle": "space"
},
"linter": {
+ "ignore": ["src/default_style/themes.ts"],
"rules": {
"style": {
"useNamingConvention": {}
diff --git a/examples/multi_language.html b/examples/multi_language.html
deleted file mode 100644
index 92888a9d..00000000
--- a/examples/multi_language.html
+++ /dev/null
@@ -1,209 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 7cee9489..cb8a73e5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"@mapbox/unitbezier": "^0.0.0",
"@mapbox/vector-tile": "^1.3.1",
"@types/css-font-loading-module": "^0.0.7",
+ "color2k": "^2.0.3",
"pbf": "^3.2.1",
"pmtiles": "2.7.0",
"potpack": "^1.0.2",
@@ -298,6 +299,11 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
+ "node_modules/color2k": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz",
+ "integrity": "sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog=="
+ },
"node_modules/esbuild": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
@@ -943,6 +949,11 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
+ "color2k": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz",
+ "integrity": "sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog=="
+ },
"esbuild": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
diff --git a/package.json b/package.json
index a22d433b..d762c15b 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"@mapbox/unitbezier": "^0.0.0",
"@mapbox/vector-tile": "^1.3.1",
"@types/css-font-loading-module": "^0.0.7",
+ "color2k": "^2.0.3",
"pbf": "^3.2.1",
"pmtiles": "2.7.0",
"potpack": "^1.0.2",
diff --git a/src/default_style/dark.ts b/src/default_style/dark.ts
deleted file mode 100644
index 2565cd90..00000000
--- a/src/default_style/dark.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { DefaultStyleParams } from "./style";
-
-export const dark: DefaultStyleParams = {
- earth: "#151515",
- glacier: "#1c1c1c",
- residential: "#252B2F",
- hospital: "#3E2C2C",
- cemetery: "#36483D",
- school: "#2C3440",
- industrial: "#33312C",
- wood: "#3A3E38",
- grass: "#4E604D",
- park: "#2C4034",
- water: "#4D5B73",
- sand: "#777777",
- buildings: "#464545",
- highwayCasing: "#000000",
- majorRoadCasing: "#1C1B1B",
- mediumRoadCasing: "#3E3E3E",
- minorRoadCasing: "#000000",
- highway: "#5B5B5B",
- majorRoad: "#595959",
- mediumRoad: "#4F4F4F",
- minorRoad: "#393939",
- boundaries: "#666666",
- mask: "#dddddd",
- countryLabel: "#ffffff",
- cityLabel: "#FFFFFF",
- stateLabel: "#ffffff",
- neighbourhoodLabel: "#FDFDFD",
- landuseLabel: "#DDDDDD",
- waterLabel: "#707E95",
- naturalLabel: "#4c4c4c",
- roadsLabel: "#C4C4C4",
- poisLabel: "#959393",
-};
diff --git a/src/default_style/light.ts b/src/default_style/light.ts
deleted file mode 100644
index b30f1d5b..00000000
--- a/src/default_style/light.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { DefaultStyleParams } from "./style";
-
-export const light: DefaultStyleParams = {
- earth: "#FFFBF6",
- glacier: "#ffffff",
- residential: "#F4F4F8",
- hospital: "#FFF6F6",
- cemetery: "#EFF2EE",
- school: "#F7F6FF",
- industrial: "#FFF9EF",
- wood: "#F4F9EF",
- grass: "#EBF9E3",
- park: "#E5F9D5",
- water: "#B7DFF2",
- sand: "#ebebeb",
- buildings: "#F2EDE8",
- highwayCasing: "#FFC3C3",
- majorRoadCasing: "#FFB9B9",
- mediumRoadCasing: "#FFCE8E",
- minorRoadCasing: "#cccccc",
- highway: "#FFCEBB",
- majorRoad: "#FFE4B3",
- mediumRoad: "#FFF2C8",
- minorRoad: "#ffffff",
- boundaries: "#9e9e9e",
- mask: "#dddddd",
- countryLabel: "#aaaaaa",
- cityLabel: "#6C6C6C",
- stateLabel: "#999999",
- neighbourhoodLabel: "#888888",
- landuseLabel: "#898989",
- waterLabel: "#41ABDC",
- naturalLabel: "#4B8F14",
- roadsLabel: "#888888",
- poisLabel: "#606060",
-};
diff --git a/src/default_style/style.ts b/src/default_style/style.ts
index ab7b2407..7eea8122 100644
--- a/src/default_style/style.ts
+++ b/src/default_style/style.ts
@@ -1,527 +1,559 @@
+import { mix } from "color2k";
import { LabelRule } from "../labeler";
import { PaintRule } from "../painter";
import {
CenteredTextSymbolizer,
CircleSymbolizer,
- FlexSymbolizer,
GroupSymbolizer,
- LabelSymbolizer,
LineLabelSymbolizer,
LineSymbolizer,
OffsetTextSymbolizer,
PolygonSymbolizer,
- ShieldSymbolizer,
exp,
+ linear,
} from "../symbolizer";
-import { Feature } from "../tilecache";
+import { Feature, JsonObject } from "../tilecache";
+import { Theme } from "./themes";
-export interface DefaultStyleParams {
- earth: string;
- glacier: string;
- residential: string;
- hospital: string;
- cemetery: string;
- school: string;
- industrial: string;
- wood: string;
- grass: string;
- park: string;
- water: string;
- sand: string;
- buildings: string;
- highwayCasing: string;
- majorRoadCasing: string;
- mediumRoadCasing: string;
- minorRoadCasing: string;
- highway: string;
- majorRoad: string;
- mediumRoad: string;
- minorRoad: string;
- boundaries: string;
- mask: string;
- countryLabel: string;
- cityLabel: string;
- stateLabel: string;
- neighbourhoodLabel: string;
- landuseLabel: string;
- waterLabel: string;
- naturalLabel: string;
- roadsLabel: string;
- poisLabel: string;
-}
+const getString = (props: JsonObject, key: string): string => {
+ const val = props[key];
+ if (typeof val === "string") return val;
+ return "";
+};
-interface PlacesFeature {
- "pmap:rank": number;
-}
+const getNumber = (props: JsonObject, key: string): number => {
+ const val = props[key];
+ if (typeof val === "number") return val;
+ return 0;
+};
-export const paintRules = (params: DefaultStyleParams): PaintRule[] => {
+export const paintRules = (t: Theme): PaintRule[] => {
return [
{
dataLayer: "earth",
symbolizer: new PolygonSymbolizer({
- fill: params.earth,
+ fill: t.earth,
}),
},
{
- dataLayer: "natural",
+ dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.glacier,
+ fill: (z, f) => {
+ return mix(t.park_a, t.park_b, Math.min(Math.max(z / 12.0, 12), 0));
+ },
}),
filter: (z, f) => {
- return f.props.natural === "glacier";
+ const kind = getString(f.props, "pmap:kind");
+ return ["allotments", "village_green", "playground"].includes(kind);
},
},
{
+ // landuse_urban_green
dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.residential,
+ fill: t.park_b,
+ opacity: 0.7,
}),
filter: (z, f) => {
- return (
- f.props.landuse === "residential" || f.props.place === "neighbourhood"
- );
+ const kind = getString(f.props, "pmap:kind");
+ return [
+ "national_park",
+ "park",
+ "cemetery",
+ "protected_area",
+ "nature_reserve",
+ "forest",
+ "golf_course",
+ ].includes(kind);
},
},
{
dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.hospital,
+ fill: t.hospital,
}),
filter: (z, f) => {
- return f.props.amenity === "hospital";
+ return f.props["pmap:kind"] === "hospital";
},
},
{
dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.cemetery,
+ fill: t.industrial,
}),
filter: (z, f) => {
- return f.props.landuse === "cemetery";
+ return f.props["pmap:kind"] === "industrial";
},
},
{
dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.school,
+ fill: t.school,
}),
filter: (z, f) => {
- return (
- f.props.amenity === "school" ||
- f.props.amenity === "kindergarten" ||
- f.props.amenity === "university" ||
- f.props.amenity === "college"
- );
+ const kind = getString(f.props, "pmap:kind");
+ return ["school", "university", "college"].includes(kind);
},
},
{
dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.industrial,
+ fill: t.beach,
}),
filter: (z, f) => {
- return f.props.landuse === "industrial";
+ return f.props["pmap:kind"] === "beach";
},
},
{
- dataLayer: "natural",
+ dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.wood,
+ fill: t.zoo,
}),
filter: (z, f) => {
- return f.props.natural === "wood";
+ return f.props["pmap:kind"] === "zoo";
},
},
{
dataLayer: "landuse",
symbolizer: new PolygonSymbolizer({
- fill: params.grass,
+ fill: t.zoo,
}),
filter: (z, f) => {
- return f.props.landuse === "grass";
+ const kind = getString(f.props, "pmap:kind");
+ return ["military", "naval_base", "airfield"].includes(kind);
},
},
{
- dataLayer: "landuse",
+ dataLayer: "natural",
symbolizer: new PolygonSymbolizer({
- fill: params.park,
+ fill: (z, f) => {
+ return mix(t.wood_a, t.wood_b, Math.min(Math.max(z / 12.0, 12), 0));
+ },
}),
filter: (z, f) => {
- return f.props.leisure === "park";
+ const kind = getString(f.props, "pmap:kind");
+ return ["wood", "nature_reserve", "forest"].includes(kind);
},
},
{
- dataLayer: "water",
+ dataLayer: "natural",
symbolizer: new PolygonSymbolizer({
- fill: params.water,
+ fill: (z, f) => {
+ return mix(t.scrub_a, t.scrub_b, Math.min(Math.max(z / 12.0, 12), 0));
+ },
}),
+ filter: (z, f) => {
+ const kind = getString(f.props, "pmap:kind");
+ return ["scrub", "grassland", "grass"].includes(kind);
+ },
},
{
dataLayer: "natural",
symbolizer: new PolygonSymbolizer({
- fill: params.sand,
+ fill: t.scrub_b,
}),
filter: (z, f) => {
- return f.props.natural === "sand";
+ const kind = getString(f.props, "pmap:kind");
+ return ["scrub", "grassland", "grass"].includes(kind);
},
},
{
- dataLayer: "buildings",
+ dataLayer: "natural",
symbolizer: new PolygonSymbolizer({
- fill: params.buildings,
+ fill: t.glacier,
}),
+ filter: (z, f) => {
+ return f.props["pmap:kind"] === "glacier";
+ },
},
{
- dataLayer: "roads",
- symbolizer: new LineSymbolizer({
- color: params.highwayCasing,
- width: exp(1.4, [
- [5, 1.5],
- [11, 4],
- [16, 9],
- [20, 40],
- ]),
+ dataLayer: "natural",
+ symbolizer: new PolygonSymbolizer({
+ fill: t.sand,
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "highway";
+ return f.props["pmap:kind"] === "sand";
},
},
{
- dataLayer: "roads",
- symbolizer: new LineSymbolizer({
- color: params.majorRoadCasing,
- width: exp(1.4, [
- [9, 3],
- [12, 4],
- [17, 8],
- [20, 22],
- ]),
+ dataLayer: "landuse",
+ symbolizer: new PolygonSymbolizer({
+ fill: t.aerodrome,
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "major_road";
+ return f.props["pmap:kind"] === "aerodrome";
},
},
{
- dataLayer: "roads",
+ dataLayer: "water",
+ symbolizer: new PolygonSymbolizer({
+ fill: t.water,
+ }),
+ },
+ {
+ // transit_runway
+ dataLayer: "transit",
symbolizer: new LineSymbolizer({
- color: params.mediumRoadCasing,
- width: exp(1.4, [
- [13, 3],
- [17, 6],
- [20, 18],
- ]),
+ color: t.runway,
+ width: (z, f) => {
+ return exp(1.6, [
+ [11, 0],
+ [13, 4],
+ [19, 30],
+ ])(z);
+ },
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "medium_road";
+ return f.props["pmap:kind_detail"] === "runway";
},
},
{
- dataLayer: "roads",
+ // transit_taxiway
+ dataLayer: "transit",
symbolizer: new LineSymbolizer({
- color: params.minorRoadCasing,
- width: exp(1.4, [
- [14, 2],
- [17, 5],
- [20, 15],
- ]),
+ color: t.runway,
+ width: (z, f) => {
+ return exp(1.6, [
+ [14, 0],
+ [14.5, 1],
+ [16, 6],
+ ])(z);
+ },
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "minor_road";
+ return f.props["pmap:kind_detail"] === "taxiway";
},
},
{
- dataLayer: "roads",
+ // transit_pier
+ dataLayer: "transit",
symbolizer: new LineSymbolizer({
- color: params.minorRoad,
- width: exp(1.4, [
- [14, 1],
- [17, 3],
- [20, 13],
- ]),
+ color: t.pier,
+ width: (z, f) => {
+ return exp(1.6, [
+ [13, 0],
+ [13.5, 0, 5],
+ [21, 16],
+ ])(z);
+ },
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "minor_road";
+ return f.props["pmap:kind"] === "pier";
},
},
{
- dataLayer: "roads",
+ // physical_line_river
+ dataLayer: "physical_line",
+ minzoom: 14,
symbolizer: new LineSymbolizer({
- color: params.mediumRoad,
- width: exp(1.4, [
- [13, 2],
- [17, 4],
- [20, 15],
- ]),
+ color: t.water,
+ width: (z, f) => {
+ return exp(1.6, [
+ [9, 0],
+ [9.5, 1.0],
+ [18, 12],
+ ])(z);
+ },
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "medium_road";
+ return f.props["pmap:kind"] === "river";
},
},
{
- dataLayer: "roads",
+ // physical_line_river
+ dataLayer: "physical_line",
+ minzoom: 14,
symbolizer: new LineSymbolizer({
- color: params.majorRoad,
- width: exp(1.4, [
- [9, 2],
- [12, 3],
- [17, 6],
- [20, 20],
- ]),
+ color: t.water,
+ width: 0.5,
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "major_road";
+ return f.props["pmap:kind"] === "stream";
},
},
+ {
+ dataLayer: "landuse",
+ symbolizer: new PolygonSymbolizer({
+ fill: t.pedestrian,
+ }),
+ filter: (z, f) => {
+ return f.props["pmap:kind"] === "pedestrian";
+ },
+ },
+ {
+ dataLayer: "landuse",
+ symbolizer: new PolygonSymbolizer({
+ fill: t.pier,
+ }),
+ filter: (z, f) => {
+ return f.props["pmap:kind"] === "pier";
+ },
+ },
+ {
+ dataLayer: "buildings",
+ symbolizer: new PolygonSymbolizer({
+ fill: t.buildings,
+ opacity: 0.5,
+ }),
+ },
{
dataLayer: "roads",
symbolizer: new LineSymbolizer({
- color: params.highway,
- width: exp(1.4, [
- [5, 0.5],
- [11, 2.5],
- [16, 7],
- [20, 30],
- ]),
+ color: t.major,
+ width: 0.5,
+ }),
+ },
+ {
+ dataLayer: "boundaries",
+ symbolizer: new LineSymbolizer({
+ dash: [3, 2],
+ color: t.boundaries,
+ width: 1,
}),
filter: (z, f) => {
- return f.props["pmap:kind"] === "highway";
+ const minAdminLevel = f.props["pmap:min_admin_level"];
+ return typeof minAdminLevel === "number" && minAdminLevel <= 2;
},
},
{
- dataLayer: "boundaries",
+ dataLayer: "transit",
symbolizer: new LineSymbolizer({
- color: params.boundaries,
- width: 2,
- opacity: 0.4,
+ dash: [0.3, 0.75],
+ color: t.railway,
+ dashWidth: (z, f) => {
+ return exp(1.6, [
+ [4, 0],
+ [7, 0.15],
+ [19, 9],
+ ])(z);
+ },
+ opacity: 0.5,
}),
+ filter: (z, f) => {
+ return f.props["pmap:kind"] === "rail";
+ },
},
{
- dataLayer: "mask",
- symbolizer: new PolygonSymbolizer({
- fill: params.mask,
+ dataLayer: "boundaries",
+ symbolizer: new LineSymbolizer({
+ dash: [3, 2],
+ color: t.boundaries,
+ width: 0.5,
}),
+ filter: (z, f) => {
+ const minAdminLevel = f.props["pmap:min_admin_level"];
+ return typeof minAdminLevel === "number" && minAdminLevel > 2;
+ },
},
];
};
-export const labelRules = (
- params: DefaultStyleParams,
- language1?: string[],
- language2?: string[],
-): LabelRule[] => {
- let nametags = ["name"];
- if (language1) nametags = language1;
-
- const languageStack = (symbolizer: LabelSymbolizer, fill: string) => {
- if (!language2) return symbolizer;
- if (symbolizer instanceof OffsetTextSymbolizer) {
- return new FlexSymbolizer([
- symbolizer,
- new OffsetTextSymbolizer({
- fill: fill,
- labelProps: language2,
- }),
- ]);
- }
- return new FlexSymbolizer([
- symbolizer,
- new CenteredTextSymbolizer({
- fill: fill,
- labelProps: language2,
- }),
- ]);
- };
+export const labelRules = (t: Theme): LabelRule[] => {
+ const nametags = ["name"];
return [
+ // {
+ // id: "neighbourhood",
+ // dataLayer: "places",
+ // symbolizer: languageStack(
+ // new CenteredTextSymbolizer({
+ // labelProps: nametags,
+ // fill: params.neighbourhoodLabel,
+ // font: "500 10px sans-serif",
+ // textTransform: "uppercase",
+ // }),
+ // params.neighbourhoodLabel,
+ // ),
+ // filter: (z, f) => {
+ // return f.props["pmap:kind"] === "neighbourhood";
+ // },
+ // },
{
- dataLayer: "places",
- symbolizer: languageStack(
- new CenteredTextSymbolizer({
- labelProps: nametags,
- fill: params.countryLabel,
- lineHeight: 1.5,
- font: (z: number, f?: Feature) => {
- if (z < 6) return "200 14px sans-serif";
- return "200 20px sans-serif";
- },
- textTransform: "uppercase",
- }),
- params.countryLabel,
- ),
+ dataLayer: "roads",
+ symbolizer: new LineLabelSymbolizer({
+ labelProps: nametags,
+ fill: t.roads_label_minor,
+ font: "400 12px sans-serif",
+ width: 2,
+ stroke: t.roads_label_minor_halo,
+ }),
+ // TODO: sort by minzoom
+ minzoom: 16,
filter: (z, f) => {
- return f.props["pmap:kind"] === "country";
+ const kind = getString(f.props, "pmap:kind");
+ return ["minor_road", "other", "path"].includes(kind);
},
},
{
- dataLayer: "places",
- symbolizer: languageStack(
- new CenteredTextSymbolizer({
- labelProps: nametags,
- fill: params.stateLabel,
- font: "300 16px sans-serif",
- }),
- params.stateLabel,
- ),
+ dataLayer: "roads",
+ symbolizer: new LineLabelSymbolizer({
+ labelProps: nametags,
+ fill: t.roads_label_major,
+ font: "400 12px sans-serif",
+ width: 2,
+ stroke: t.roads_label_major_halo,
+ }),
+ // TODO: sort by minzoom
+ minzoom: 12,
filter: (z, f) => {
- return f.props["pmap:kind"] === "state";
+ const kind = getString(f.props, "pmap:kind");
+ return ["highway", "major_road", "medium_road"].includes(kind);
},
},
{
- id: "cities_high",
- dataLayer: "places",
+ dataLayer: "roads",
+ symbolizer: new LineLabelSymbolizer({
+ labelProps: nametags,
+ fill: t.roads_label_major,
+ font: "400 12px sans-serif",
+ width: 2,
+ stroke: t.roads_label_major_halo,
+ }),
+ // TODO: sort by minzoom
+ minzoom: 12,
filter: (z, f) => {
- return f.props["pmap:kind"] === "city";
- },
- minzoom: 7,
- symbolizer: languageStack(
- new CenteredTextSymbolizer({
- labelProps: nametags,
- fill: params.cityLabel,
- font: (z: number, f?: Feature) => {
- if (f?.props["pmap:rank"] === 1) {
- if (z > 8) return "600 20px sans-serif";
- return "600 12px sans-serif";
- }
- if (z > 8) return "600 16px sans-serif";
- return "600 10px sans-serif";
- },
- }),
- params.cityLabel,
- ),
- sort: (a, b) => {
- return (
- (a as PlacesFeature)["pmap:rank"] - (b as PlacesFeature)["pmap:rank"]
- );
+ const kind = getString(f.props, "pmap:kind");
+ return ["highway", "major_road", "medium_road"].includes(kind);
},
},
{
- id: "cities_low",
- dataLayer: "places",
+ dataLayer: "physical_point",
+ symbolizer: new CenteredTextSymbolizer({
+ labelProps: nametags,
+ fill: t.ocean_label,
+ lineHeight: 1.5,
+ letterSpacing: 1,
+ font: (z, f) => {
+ const size = linear([
+ [3, 10],
+ [10, 12],
+ ])(z);
+ return `400 ${size}px sans-serif`;
+ },
+ textTransform: "uppercase",
+ }),
filter: (z, f) => {
- return f.props["pmap:kind"] === "city";
+ const kind = getString(f.props, "pmap:kind");
+ return ["ocean", "bay", "strait", "fjord"].includes(kind);
},
- maxzoom: 6,
- symbolizer: new GroupSymbolizer([
- new CircleSymbolizer({
- radius: 2,
- fill: params.cityLabel,
- }),
- languageStack(
- new OffsetTextSymbolizer({
- labelProps: nametags,
- fill: params.cityLabel,
- offsetX: 2,
- offsetY: 2,
- font: (z: number, f?: Feature) => {
- if (f?.props["pmap:rank"] === 1) {
- if (z > 8) return "600 20px sans-serif";
- return "600 12px sans-serif";
- }
- if (z > 8) return "600 16px sans-serif";
- return "600 10px sans-serif";
- },
- }),
- params.cityLabel,
- ),
- ]),
- sort: (a, b) => {
- return (
- (a as PlacesFeature)["pmap:rank"] - (b as PlacesFeature)["pmap:rank"]
- );
+ },
+ {
+ dataLayer: "physical_point",
+ symbolizer: new CenteredTextSymbolizer({
+ labelProps: nametags,
+ fill: t.ocean_label,
+ lineHeight: 1.5,
+ letterSpacing: 1,
+ font: (z, f) => {
+ const size = linear([
+ [3, 0],
+ [6, 12],
+ [10, 12],
+ ])(z);
+ return `400 ${size}px sans-serif`;
+ },
+ }),
+ filter: (z, f) => {
+ const kind = getString(f.props, "pmap:kind");
+ return ["sea", "lake", "water"].includes(kind);
},
},
{
- id: "neighbourhood",
dataLayer: "places",
- symbolizer: languageStack(
- new CenteredTextSymbolizer({
- labelProps: nametags,
- fill: params.neighbourhoodLabel,
- font: "500 10px sans-serif",
- textTransform: "uppercase",
- }),
- params.neighbourhoodLabel,
- ),
+ symbolizer: new CenteredTextSymbolizer({
+ labelProps: (z, f) => {
+ if (z < 6) {
+ return ["name:short"];
+ }
+ return nametags;
+ },
+ fill: t.state_label,
+ stroke: t.state_label_halo,
+ width: 1,
+ lineHeight: 1.5,
+ font: (z: number, f?: Feature) => {
+ if (z < 6) return "400 16px sans-serif";
+ return "400 12px sans-serif";
+ },
+ textTransform: "uppercase",
+ }),
filter: (z, f) => {
- return f.props["pmap:kind"] === "neighbourhood";
+ return f.props["pmap:kind"] === "region";
},
},
- // {
- // dataLayer: "landuse",
- // symbolizer: languageStack(
- // new PolygonLabelSymbolizer({
- // label_props: nametags,
- // fill: params.landuseLabel,
- // font: "300 12px sans-serif",
- // }),
- // params.landuseLabel,
- // ),
- // },
- // {
- // dataLayer: "water",
- // symbolizer: languageStack(
- // new PolygonLabelSymbolizer({
- // label_props: nametags,
- // fill: params.waterLabel,
- // font: "italic 600 12px sans-serif",
- // }),
- // params.waterLabel,
- // ),
- // },
- // {
- // dataLayer: "natural",
- // symbolizer: languageStack(
- // new PolygonLabelSymbolizer({
- // label_props: nametags,
- // fill: params.naturalLabel,
- // font: "italic 300 12px sans-serif",
- // }),
- // params.naturalLabel,
- // ),
- // },
{
- dataLayer: "roads",
- symbolizer: languageStack(
- new LineLabelSymbolizer({
- labelProps: nametags,
- fill: params.roadsLabel,
- font: "500 12px sans-serif",
- }),
- params.roadsLabel,
- ),
- minzoom: 12,
+ dataLayer: "places",
+ symbolizer: new CenteredTextSymbolizer({
+ labelProps: nametags,
+ fill: t.country_label,
+ lineHeight: 1.5,
+ font: (z: number, f?: Feature) => {
+ if (z < 6) return "600 12px sans-serif";
+ return "600 12px sans-serif";
+ },
+ textTransform: "uppercase",
+ }),
+ filter: (z, f) => {
+ return f.props["pmap:kind"] === "country";
+ },
},
{
- dataLayer: "roads",
- symbolizer: new ShieldSymbolizer({
- labelProps: ["ref"],
- font: "600 9px sans-serif",
- background: params.highway,
- padding: 2,
- fill: params.neighbourhoodLabel,
+ // places_locality
+ dataLayer: "places",
+ minzoom: 9,
+ symbolizer: new CenteredTextSymbolizer({
+ labelProps: nametags,
+ fill: t.city_label,
+ lineHeight: 1.5,
+ font: (z: number, f?: Feature) => {
+ if (!f) return "400 12px sans-serif";
+ const minZoom = f.props["pmap:min_zoom"];
+ let weight = 400;
+ if (minZoom && minZoom <= 5) {
+ weight = 600;
+ }
+ let size = 12;
+ const popRank = f.props["pmap:population_rank"];
+ if (popRank && popRank > 9) {
+ size = 16;
+ }
+ return `${weight} ${size}px sans-serif`;
+ },
}),
+ sort: (a, b) => {
+ const aRank = getNumber(a, "pmap:population_rank");
+ const bRank = getNumber(b, "pmap:population_rank");
+ return aRank - bRank;
+ },
filter: (z, f) => {
- return f.props["pmap:kind"] === "highway";
+ return f.props["pmap:kind"] === "locality";
},
},
{
- dataLayer: "pois",
+ dataLayer: "places",
+ maxzoom: 8,
symbolizer: new GroupSymbolizer([
new CircleSymbolizer({
radius: 2,
- fill: params.poisLabel,
+ fill: t.city_circle,
+ stroke: t.city_circle_stroke,
+ width: 1.5,
+ }),
+ new OffsetTextSymbolizer({
+ labelProps: nametags,
+ fill: t.city_label,
+ stroke: t.city_label_halo,
+ width: 1,
+ offsetX: 6,
+ offsetY: 4.5,
+ font: (z, f) => {
+ return "400 12px sans-serif";
+ },
}),
- languageStack(
- new OffsetTextSymbolizer({
- labelProps: nametags,
- fill: params.poisLabel,
- offsetX: 2,
- offsetY: 2,
- font: "300 10px sans-serif",
- }),
- params.poisLabel,
- ),
]),
+ filter: (z, f) => {
+ return f.props["pmap:kind"] === "locality";
+ },
},
];
};
diff --git a/src/default_style/themes.ts b/src/default_style/themes.ts
new file mode 100644
index 00000000..5dc80f89
--- /dev/null
+++ b/src/default_style/themes.ts
@@ -0,0 +1,549 @@
+export interface Theme {
+ background: string;
+ earth: string;
+ park_a: string;
+ park_b: string;
+ hospital: string;
+ industrial: string;
+ school: string;
+ wood_a: string;
+ wood_b: string;
+ pedestrian: string;
+ scrub_a: string;
+ scrub_b: string;
+ glacier: string;
+ sand: string;
+ beach: string;
+ aerodrome: string;
+ runway: string;
+ water: string;
+ pier: string;
+ zoo: string;
+ military: string;
+
+ tunnel_other_casing: string;
+ tunnel_minor_casing: string;
+ tunnel_link_casing: string;
+ tunnel_medium_casing: string;
+ tunnel_major_casing: string;
+ tunnel_highway_casing: string;
+ tunnel_other: string;
+ tunnel_minor: string;
+ tunnel_link: string;
+ tunnel_medium: string;
+ tunnel_major: string;
+ tunnel_highway: string;
+
+ transit_pier: string;
+ buildings: string;
+
+ minor_service_casing: string;
+ minor_casing: string;
+ link_casing: string;
+ medium_casing: string;
+ major_casing_late: string;
+ highway_casing_late: string;
+ other: string;
+ minor_service: string;
+ minor_a: string;
+ minor_b: string;
+ link: string;
+ medium: string;
+ major_casing_early: string;
+ major: string;
+ highway_casing_early: string;
+ highway: string;
+
+ railway: string;
+ boundaries: string;
+ waterway_label: string;
+
+ bridges_other_casing: string;
+ bridges_minor_casing: string;
+ bridges_link_casing: string;
+ bridges_medium_casing: string;
+ bridges_major_casing: string;
+ bridges_highway_casing: string;
+ bridges_other: string;
+ bridges_minor: string;
+ bridges_link: string;
+ bridges_medium: string;
+ bridges_major: string;
+ bridges_highway: string;
+
+ roads_label_minor: string;
+ roads_label_minor_halo: string;
+ roads_label_major: string;
+ roads_label_major_halo: string;
+ ocean_label: string;
+ peak_label: string;
+ subplace_label: string;
+ subplace_label_halo: string;
+ city_circle: string;
+ city_circle_stroke: string;
+ city_label: string;
+ city_label_halo: string;
+ state_label: string;
+ state_label_halo: string;
+ country_label: string;
+}
+
+export const LIGHT: Theme = {
+ background: "#cccccc",
+ earth: "#e0e0e0",
+ park_a: "#cfddd5",
+ park_b: "#9cd3b4",
+ hospital: "#e4dad9",
+ industrial: "#d1dde1",
+ school: "#e4ded7",
+ wood_a: "#d0ded0",
+ wood_b: "#a0d9a0",
+ pedestrian: "#e3e0d4",
+ scrub_a: "#cedcd7",
+ scrub_b: "#99d2bb",
+ glacier: "#e7e7e7",
+ sand: "#e2e0d7",
+ beach: "#e8e4d0",
+ aerodrome: "#dadbdf",
+ runway: "#e9e9ed",
+ water: "#80deea",
+ pier: "#e0e0e0",
+ zoo: "#c6dcdc",
+ military: "#dcdcdc",
+
+ tunnel_other_casing: "#e0e0e0",
+ tunnel_minor_casing: "#e0e0e0",
+ tunnel_link_casing: "#e0e0e0",
+ tunnel_medium_casing: "#e0e0e0",
+ tunnel_major_casing: "#e0e0e0",
+ tunnel_highway_casing: "#e0e0e0",
+ tunnel_other: "#d5d5d5",
+ tunnel_minor: "#d5d5d5",
+ tunnel_link: "#d5d5d5",
+ tunnel_medium: "#d5d5d5",
+ tunnel_major: "#d5d5d5",
+ tunnel_highway: "#d5d5d5",
+
+ transit_pier: "#e0e0e0",
+ buildings: "#cccccc",
+
+ minor_service_casing: "#e0e0e0",
+ minor_casing: "#e0e0e0",
+ link_casing: "#e0e0e0",
+ medium_casing: "#e0e0e0",
+ major_casing_late: "#e0e0e0",
+ highway_casing_late: "#e0e0e0",
+ other: "#ebebeb",
+ minor_service: "#ebebeb",
+ minor_a: "#ebebeb",
+ minor_b: "#ffffff",
+ link: "#ffffff",
+ medium: "#f5f5f5",
+ major_casing_early: "#e0e0e0",
+ major: "#ffffff",
+ highway_casing_early: "#e0e0e0",
+ highway: "#ffffff",
+
+ railway: "#a7b1b3",
+ boundaries: "#adadad",
+ waterway_label: "#ffffff",
+
+ bridges_other_casing: "#e0e0e0",
+ bridges_minor_casing: "#e0e0e0",
+ bridges_link_casing: "#e0e0e0",
+ bridges_medium_casing: "#e0e0e0",
+ bridges_major_casing: "#e0e0e0",
+ bridges_highway_casing: "#e0e0e0",
+ bridges_other: "#ebebeb",
+ bridges_minor: "#ffffff",
+ bridges_link: "#ffffff",
+ bridges_medium: "#f0eded",
+ bridges_major: "#f5f5f5",
+ bridges_highway: "#ffffff",
+
+ roads_label_minor: "#91888b",
+ roads_label_minor_halo: "#ffffff",
+ roads_label_major: "#938a8d",
+ roads_label_major_halo: "#ffffff",
+ ocean_label: "#ffffff",
+ peak_label: "#7e9aa0",
+ subplace_label: "#8f8f8f",
+ subplace_label_halo: "#e0e0e0",
+ city_circle: "#ffffff",
+ city_circle_stroke: "#a3a3a3",
+ city_label: "#5c5c5c",
+ city_label_halo: "#e0e0e0",
+ state_label: "#b3b3b3",
+ state_label_halo: "#e0e0e0",
+ country_label: "#a3a3a3",
+};
+
+export const DARK: Theme = {
+ background: "#34373d",
+ earth: "#1f1f1f",
+ park_a: "#232325",
+ park_b: "#232325",
+ hospital: "#252424",
+ industrial: "#222222",
+ school: "#262323",
+ wood_a: "#202121",
+ wood_b: "#202121",
+ pedestrian: "#1e1e1e",
+ scrub_a: "#222323",
+ scrub_b: "#222323",
+ glacier: "#1c1c1c",
+ sand: "#212123",
+ beach: "#28282a",
+ aerodrome: "#1e1e1e",
+ runway: "#333333",
+ water: "#34373d",
+ pier: "#222222",
+ zoo: "#222323",
+ military: "#242323",
+
+ tunnel_other_casing: "#141414",
+ tunnel_minor_casing: "#141414",
+ tunnel_link_casing: "#141414",
+ tunnel_medium_casing: "#141414",
+ tunnel_major_casing: "#141414",
+ tunnel_highway_casing: "#141414",
+ tunnel_other: "#292929",
+ tunnel_minor: "#292929",
+ tunnel_link: "#292929",
+ tunnel_medium: "#292929",
+ tunnel_major: "#292929",
+ tunnel_highway: "#292929",
+
+ transit_pier: "#333333",
+ buildings: "#111111",
+
+ minor_service_casing: "#1f1f1f",
+ minor_casing: "#1f1f1f",
+ link_casing: "#1f1f1f",
+ medium_casing: "#1f1f1f",
+ major_casing_late: "#1f1f1f",
+ highway_casing_late: "#1f1f1f",
+ other: "#333333",
+ minor_service: "#333333",
+ minor_a: "#3d3d3d",
+ minor_b: "#333333",
+ link: "#3d3d3d",
+ medium: "#3d3d3d",
+ major_casing_early: "#1f1f1f",
+ major: "#3d3d3d",
+ highway_casing_early: "#1f1f1f",
+ highway: "#474747",
+
+ railway: "#000000",
+ boundaries: "#5b6374",
+ waterway_label: "#717784",
+
+ bridges_other_casing: "#2b2b2b",
+ bridges_minor_casing: "#1f1f1f",
+ bridges_link_casing: "#1f1f1f",
+ bridges_medium_casing: "#1f1f1f",
+ bridges_major_casing: "#1f1f1f",
+ bridges_highway_casing: "#1f1f1f",
+ bridges_other: "#333333",
+ bridges_minor: "#333333",
+ bridges_link: "#3d3d3d",
+ bridges_medium: "#3d3d3d",
+ bridges_major: "#3d3d3d",
+ bridges_highway: "#474747",
+
+ roads_label_minor: "#525252",
+ roads_label_minor_halo: "#1f1f1f",
+ roads_label_major: "#666666",
+ roads_label_major_halo: "#1f1f1f",
+ ocean_label: "#717784",
+ peak_label: "#898080",
+ subplace_label: "#525252",
+ subplace_label_halo: "#1f1f1f",
+ city_circle: "#000000",
+ city_circle_stroke: "#7a7a7a",
+ city_label: "#7a7a7a",
+ city_label_halo: "#212121",
+ state_label: "#3d3d3d",
+ state_label_halo: "#1f1f1f",
+ country_label: "#5c5c5c",
+};
+
+export const WHITE: Theme = {
+ background: "#ffffff",
+ earth: "#ffffff",
+ park_a: "#fcfcfc",
+ park_b: "#fcfcfc",
+ hospital: "#f8f8f8",
+ industrial: "#fcfcfc",
+ school: "#f8f8f8",
+ wood_a: "#fafafa",
+ wood_b: "#fafafa",
+ pedestrian: "#fdfdfd",
+ scrub_a: "#fafafa",
+ scrub_b: "#fafafa",
+ glacier: "#fcfcfc",
+ sand: "#fafafa",
+ beach: "#f6f6f6",
+ aerodrome: "#fdfdfd",
+ runway: "#efefef",
+ water: "#dcdcdc",
+ pier: "#f5f5f5",
+ zoo: "#f7f7f7",
+ military: "#fcfcfc",
+
+ tunnel_other_casing: "#d6d6d6",
+ tunnel_minor_casing: "#fcfcfc",
+ tunnel_link_casing: "#fcfcfc",
+ tunnel_medium_casing: "#fcfcfc",
+ tunnel_major_casing: "#fcfcfc",
+ tunnel_highway_casing: "#fcfcfc",
+ tunnel_other: "#d6d6d6",
+ tunnel_minor: "#d6d6d6",
+ tunnel_link: "#d6d6d6",
+ tunnel_medium: "#d6d6d6",
+ tunnel_major: "#d6d6d6",
+ tunnel_highway: "#d6d6d6",
+
+ transit_pier: "#efefef",
+ buildings: "#efefef",
+
+ minor_service_casing: "#ffffff",
+ minor_casing: "#ffffff",
+ link_casing: "#ffffff",
+ medium_casing: "#ffffff",
+ major_casing_late: "#ffffff",
+ highway_casing_late: "#ffffff",
+ other: "#f5f5f5",
+ minor_service: "#f5f5f5",
+ minor_a: "#ebebeb",
+ minor_b: "#f5f5f5",
+ link: "#ebebeb",
+ medium: "#ebebeb",
+ major_casing_early: "#ffffff",
+ major: "#ebebeb",
+ highway_casing_early: "#ffffff",
+ highway: "#ebebeb",
+
+ railway: "#d6d6d6",
+ boundaries: "#adadad",
+ waterway_label: "#adadad",
+
+ bridges_other_casing: "#ffffff",
+ bridges_minor_casing: "#ffffff",
+ bridges_link_casing: "#ffffff",
+ bridges_medium_casing: "#ffffff",
+ bridges_major_casing: "#ffffff",
+ bridges_highway_casing: "#ffffff",
+ bridges_other: "#f5f5f5",
+ bridges_minor: "#f5f5f5",
+ bridges_link: "#ebebeb",
+ bridges_medium: "#ebebeb",
+ bridges_major: "#ebebeb",
+ bridges_highway: "#ebebeb",
+
+ roads_label_minor: "#adadad",
+ roads_label_minor_halo: "#ffffff",
+ roads_label_major: "#999999",
+ roads_label_major_halo: "#ffffff",
+ ocean_label: "#adadad",
+ peak_label: "#adadad",
+ subplace_label: "#8f8f8f",
+ subplace_label_halo: "#ffffff",
+ city_circle: "#ffffff",
+ city_circle_stroke: "#adadad",
+ city_label: "#5c5c5c",
+ city_label_halo: "#ffffff",
+ state_label: "#b3b3b3",
+ state_label_halo: "#ffffff",
+ country_label: "#b8b8b8",
+};
+
+export const GRAYSCALE: Theme = {
+ background: "#a3a3a3",
+ earth: "#cccccc",
+ park_a: "#c2c2c2",
+ park_b: "#c2c2c2",
+ hospital: "#d0d0d0",
+ industrial: "#c6c6c6",
+ school: "#d0d0d0",
+ wood_a: "#c2c2c2",
+ wood_b: "#c2c2c2",
+ pedestrian: "#c4c4c4",
+ scrub_a: "#c2c2c2",
+ scrub_b: "#c2c2c2",
+ glacier: "#d2d2d2",
+ sand: "#d2d2d2",
+ beach: "#d2d2d2",
+ aerodrome: "#c9c9c9",
+ runway: "#f5f5f5",
+ water: "#a3a3a3",
+ pier: "#b8b8b8",
+ zoo: "#c7c7c7",
+ military: "#bfbfbf",
+
+ tunnel_other_casing: "#b8b8b8",
+ tunnel_minor_casing: "#b8b8b8",
+ tunnel_link_casing: "#b8b8b8",
+ tunnel_medium_casing: "#b8b8b8",
+ tunnel_major_casing: "#b8b8b8",
+ tunnel_highway_casing: "#b8b8b8",
+ tunnel_other: "#d6d6d6",
+ tunnel_minor: "#d6d6d6",
+ tunnel_link: "#d6d6d6",
+ tunnel_medium: "#d6d6d6",
+ tunnel_major: "#d6d6d6",
+ tunnel_highway: "#d6d6d6",
+
+ transit_pier: "#b8b8b8",
+ buildings: "#e0e0e0",
+
+ minor_service_casing: "#cccccc",
+ minor_casing: "#cccccc",
+ link_casing: "#cccccc",
+ medium_casing: "#cccccc",
+ major_casing_late: "#cccccc",
+ highway_casing_late: "#cccccc",
+ other: "#e0e0e0",
+ minor_service: "#e0e0e0",
+ minor_a: "#ebebeb",
+ minor_b: "#e0e0e0",
+ link: "#ebebeb",
+ medium: "#ebebeb",
+ major_casing_early: "#cccccc",
+ major: "#ebebeb",
+ highway_casing_early: "#cccccc",
+ highway: "#ebebeb",
+
+ railway: "#f5f5f5",
+ boundaries: "#5c5c5c",
+ waterway_label: "#7a7a7a",
+
+ bridges_other_casing: "#cccccc",
+ bridges_minor_casing: "#cccccc",
+ bridges_link_casing: "#cccccc",
+ bridges_medium_casing: "#cccccc",
+ bridges_major_casing: "#cccccc",
+ bridges_highway_casing: "#cccccc",
+ bridges_other: "#e0e0e0",
+ bridges_minor: "#e0e0e0",
+ bridges_link: "#ebebeb",
+ bridges_medium: "#ebebeb",
+ bridges_major: "#ebebeb",
+ bridges_highway: "#ebebeb",
+
+ roads_label_minor: "#999999",
+ roads_label_minor_halo: "#e0e0e0",
+ roads_label_major: "#8f8f8f",
+ roads_label_major_halo: "#ebebeb",
+ ocean_label: "#7a7a7a",
+ peak_label: "#5c5c5c",
+ subplace_label: "#7a7a7a",
+ subplace_label_halo: "#cccccc",
+ city_circle: "#c2c2c2",
+ city_circle_stroke: "#7a7a7a",
+ city_label: "#474747",
+ city_label_halo: "#cccccc",
+ state_label: "#999999",
+ state_label_halo: "#cccccc",
+ country_label: "#858585",
+};
+
+export const BLACK: Theme = {
+ background: "#2b2b2b",
+ earth: "#141414",
+ park_a: "#181818",
+ park_b: "#181818",
+ hospital: "#1d1d1d",
+ industrial: "#101010",
+ school: "#111111",
+ wood_a: "#1a1a1a",
+ wood_b: "#1a1a1a",
+ pedestrian: "#191919",
+ scrub_a: "#1c1c1c",
+ scrub_b: "#1c1c1c",
+ glacier: "#191919",
+ sand: "#161616",
+ beach: "#1f1f1f",
+ aerodrome: "#191919",
+ runway: "#323232",
+ water: "#333333",
+ pier: "#0a0a0a",
+ zoo: "#191919",
+ military: "#121212",
+
+ tunnel_other_casing: "#101010",
+ tunnel_minor_casing: "#101010",
+ tunnel_link_casing: "#101010",
+ tunnel_medium_casing: "#101010",
+ tunnel_major_casing: "#101010",
+ tunnel_highway_casing: "#101010",
+ tunnel_other: "#292929",
+ tunnel_minor: "#292929",
+ tunnel_link: "#292929",
+ tunnel_medium: "#292929",
+ tunnel_major: "#292929",
+ tunnel_highway: "#292929",
+
+ transit_pier: "#0a0a0a",
+ buildings: "#0a0a0a",
+
+ minor_service_casing: "#141414",
+ minor_casing: "#141414",
+ link_casing: "#141414",
+ medium_casing: "#141414",
+ major_casing_late: "#141414",
+ highway_casing_late: "#141414",
+ other: "#1f1f1f",
+ minor_service: "#1f1f1f",
+ minor_a: "#292929",
+ minor_b: "#1f1f1f",
+ link: "#1f1f1f",
+ medium: "#292929",
+ major_casing_early: "#141414",
+ major: "#292929",
+ highway_casing_early: "#141414",
+ highway: "#292929",
+
+ railway: "#292929",
+ boundaries: "#707070",
+ waterway_label: "#707070",
+
+ bridges_other_casing: "#141414",
+ bridges_minor_casing: "#141414",
+ bridges_link_casing: "#141414",
+ bridges_medium_casing: "#141414",
+ bridges_major_casing: "#141414",
+ bridges_highway_casing: "#141414",
+ bridges_other: "#1f1f1f",
+ bridges_minor: "#1f1f1f",
+ bridges_link: "#292929",
+ bridges_medium: "#292929",
+ bridges_major: "#292929",
+ bridges_highway: "#292929",
+
+ roads_label_minor: "#525252",
+ roads_label_minor_halo: "#141414",
+ roads_label_major: "#5c5c5c",
+ roads_label_major_halo: "#141414",
+ ocean_label: "#707070",
+ peak_label: "#707070",
+ subplace_label: "#5c5c5c",
+ subplace_label_halo: "#141414",
+ city_circle: "#000000",
+ city_circle_stroke: "#666666",
+ city_label: "#999999",
+ city_label_halo: "#141414",
+ state_label: "#3d3d3d",
+ state_label_halo: "#141414",
+ country_label: "#707070",
+};
+
+const themes: Record