From 6ad19a49e9cb3398911d9156e6d924d11c034fb7 Mon Sep 17 00:00:00 2001 From: ncastejon <castejon.nicolas@gmail.com> Date: Tue, 23 Jul 2019 10:11:58 +0200 Subject: [PATCH] Add mvt layer with a WMS style --- package-lock.json | 440 +-- package.json | 4 +- .../http-error-response-interceptor.ts | 1 + .../dataset-map/dataset-map.component.html | 6 +- .../dataset-map/dataset-map.component.ts | 14 + src/app/map/WMSStyleHelper.ts | 3 + src/app/map/components/map.component.html | 2 +- src/app/map/components/map.component.ts | 90 +- src/app/map/components/minimap-control.ts | 2 +- src/app/map/services/map.service.ts | 1154 +++++--- src/assets/mapbox-gl-styles/vector.json | 1 + src/assets/sprite/sprite.json | 2468 +++++++++++++++++ src/assets/sprite/sprite.png | Bin 0 -> 41303 bytes 13 files changed, 3373 insertions(+), 812 deletions(-) create mode 100644 src/app/map/WMSStyleHelper.ts create mode 100644 src/assets/sprite/sprite.json create mode 100644 src/assets/sprite/sprite.png diff --git a/package-lock.json b/package-lock.json index 62ea6983..d916e48e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "webapp", - "version": "2.1.9", + "version": "2.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -761,30 +761,30 @@ "wgs84": "0.0.0" } }, + "@mapbox/geojson-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz", + "integrity": "sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==" + }, "@mapbox/jsonlint-lines-primitives": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", "integrity": "sha1-zlblOfg1UrWNENZy6k1vya3HsjQ=" }, "@mapbox/mapbox-gl-supported": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.0.tgz", - "integrity": "sha512-ZD0Io4XK+/vU/4zpANjOtdWfVszAgnaMPsGR6LKsWh4kLIEv9qoobTVmJPPuwuM+ZI2b3BlZ6DYw1XHVmv6YTA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.1.tgz", + "integrity": "sha512-yyKza9S6z3ELKuf6w5n6VNUB0Osu6Z93RXPfMHLIlNWohu3KqxewLOq4lMXseYJ92GwkRAxd207Pr/Z98cwmvw==" }, "@mapbox/point-geometry": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", "integrity": "sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI=" }, - "@mapbox/shelf-pack": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@mapbox/shelf-pack/-/shelf-pack-3.2.0.tgz", - "integrity": "sha512-dyQxe6ukILV6qaEvxoKCIwhblgRjYp1ZGlClo4xvfbmxzFO5LYu7Tnrg2AZrRgN7VsSragsGcNjzUe9kCdKHYQ==" - }, "@mapbox/tiny-sdf": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-1.1.0.tgz", - "integrity": "sha512-dnhyk8X2BkDRWImgHILYAGgo+kuciNYX30CUKj/Qd5eNjh54OWM/mdOS/PWsPeN+3abtN+QDGYM4G220ynVJKA==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-1.1.1.tgz", + "integrity": "sha512-Ihn1nZcGIswJ5XGbgFAvVumOgWpvIjBX9jiRlIl46uQG9vJOF51ViBYHF95rEZupuyQbEmhLaDPLQlU7fUTsBg==" }, "@mapbox/unitbezier": { "version": "0.0.0", @@ -909,9 +909,9 @@ "dev": true }, "@types/geojson": { - "version": "7946.0.5", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.5.tgz", - "integrity": "sha512-rLlMXpd3rdlrp0+xsrda/hFfOpIxgqFcRpk005UKbHtcdFK+QXAjhBAPnvO58qF4O1LdDXrcaiJxMgstCIlcaw==", + "version": "7946.0.7", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", + "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==", "dev": true }, "@types/jasmine": { @@ -936,9 +936,9 @@ "dev": true }, "@types/mapbox-gl": { - "version": "0.47.2", - "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-0.47.2.tgz", - "integrity": "sha512-2RYTLUCPWkyh2RtzA8g7J5zybA12WbnKQnGLa+4Em2E6Sb0F/aQPl03nVxNX9URXu0+4fk+7ReGB8Pj07SPoEw==", + "version": "0.51.11", + "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-0.51.11.tgz", + "integrity": "sha512-iFDwtUTFHXQjn3vSUxNPxqGtlnikVozRlVMu3/oatMon4QR2DVxAGHW9zwjq/6iv4W92f2z/OaaKsMAGHHBm5Q==", "dev": true, "requires": { "@types/geojson": "*" @@ -1208,11 +1208,6 @@ "negotiator": "0.6.1" } }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" - }, "acorn-dynamic-import": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", @@ -1370,6 +1365,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -1947,17 +1943,6 @@ "to-regex": "^3.0.1" } }, - "brfs": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz", - "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", - "requires": { - "quote-stream": "^1.0.1", - "resolve": "^1.1.5", - "static-module": "^2.2.0", - "through2": "^2.0.0" - } - }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -2082,11 +2067,6 @@ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, - "buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" - }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -2666,6 +2646,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -2926,11 +2907,6 @@ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, "default-gateway": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", @@ -3194,14 +3170,6 @@ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "requires": { - "readable-stream": "^2.0.2" - } - }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -3426,18 +3394,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escodegen": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", - "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", @@ -3448,10 +3404,15 @@ "estraverse": "^4.1.1" } }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" + }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" }, "esrecurse": { "version": "4.2.1", @@ -3465,12 +3426,14 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "etag": { "version": "1.8.1", @@ -3672,11 +3635,6 @@ } } }, - "expect.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.2.0.tgz", - "integrity": "sha1-EChTPSwcNj90pnlv9X7AUg3tK+E=" - }, "express": { "version": "4.16.4", "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", @@ -3733,6 +3691,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -3815,24 +3774,6 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, - "falafel": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", - "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", - "requires": { - "acorn": "^5.0.0", - "foreach": "^2.0.5", - "isarray": "0.0.1", - "object-keys": "^1.0.6" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - } - } - }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -3845,11 +3786,6 @@ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, "fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", @@ -4019,11 +3955,6 @@ "for-in": "^1.0.1" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -4649,11 +4580,6 @@ "rimraf": "2" } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -4878,17 +4804,6 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, - "gray-matter": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-3.1.1.tgz", - "integrity": "sha512-nZ1qjLmayEv0/wt3sHig7I0s3/sJO0dkAaKYQ5YAOApUtYEOonXSFdWvL1khvnZMTvov4UufkqlFsilPnejEXA==", - "requires": { - "extend-shallow": "^2.0.1", - "js-yaml": "^3.10.0", - "kind-of": "^5.0.2", - "strip-bom-string": "^1.0.0" - } - }, "grid-index": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", @@ -4943,14 +4858,6 @@ "har-schema": "^2.0.0" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -5573,7 +5480,8 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true }, "is-extglob": { "version": "2.1.1", @@ -5954,6 +5862,7 @@ "version": "3.12.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -5962,7 +5871,8 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true } } }, @@ -6220,7 +6130,8 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true }, "lcid": { "version": "1.0.0", @@ -6259,15 +6170,6 @@ "pify": "^3.0.0" } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, "license-webpack-plugin": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.0.tgz", @@ -6437,14 +6339,6 @@ "yallist": "^2.1.2" } }, - "magic-string": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", - "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", - "requires": { - "vlq": "^0.2.2" - } - }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -6588,34 +6482,32 @@ } }, "mapbox-gl": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-0.47.0.tgz", - "integrity": "sha512-y1AlNYMAKaqEtaqni0zOMYj9gTc1gZ0lqLkxXK9iFg5+ZBITc5DL9AcrXhpEXNxUzXKFa7dZkSULyNaqXFQ8yQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-0.51.0.tgz", + "integrity": "sha512-ToV6WJIgdLIKSwLO13pRf5EMeVx4gjdO10akFFxGVwYO/G1nCIZOurKFPIEXbAg0zmZXJD+55HbOIg+AbJICpQ==", "requires": { - "@mapbox/jsonlint-lines-primitives": "^2.0.1", + "@mapbox/geojson-types": "^1.0.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^1.4.0", "@mapbox/point-geometry": "^0.1.0", - "@mapbox/shelf-pack": "^3.1.0", "@mapbox/tiny-sdf": "^1.1.0", "@mapbox/unitbezier": "^0.0.0", "@mapbox/vector-tile": "^1.3.1", - "@mapbox/whoots-js": "^3.0.0", - "brfs": "^1.4.4", + "@mapbox/whoots-js": "^3.1.0", "csscolorparser": "~1.0.2", "earcut": "^2.1.3", + "esm": "^3.0.84", "geojson-rewind": "^0.3.0", - "geojson-vt": "^3.1.4", + "geojson-vt": "^3.2.1", "gl-matrix": "^2.6.1", - "gray-matter": "^3.0.8", "grid-index": "^1.0.0", "minimist": "0.0.8", + "murmurhash-js": "^1.0.0", "pbf": "^3.0.5", + "potpack": "^1.0.1", "quickselect": "^1.0.0", "rw": "^1.3.3", - "shuffle-seed": "^1.1.6", - "sort-object": "^0.3.2", - "supercluster": "^4.0.1", - "through2": "^2.0.3", + "supercluster": "^4.1.1", "tinyqueue": "^1.1.0", "vt-pbf": "^3.0.1" } @@ -6698,21 +6590,6 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, - "merge-source-map": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", - "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", - "requires": { - "source-map": "^0.5.6" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } - } - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -6970,6 +6847,11 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=" + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -7395,16 +7277,6 @@ } } }, - "object-inspect": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", - "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==" - }, - "object-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", - "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==" - }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -7535,19 +7407,6 @@ } } }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -7927,7 +7786,8 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -7945,12 +7805,12 @@ } }, "pbf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.1.0.tgz", - "integrity": "sha512-/hYJmIsTmh7fMkHAWWXJ5b8IKLWdjdlAFb3IHkRBn1XUhIYBChVGfVwmHEAV3UfXTxsP/AKfYTXTS/dCPxJd5w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.0.tgz", + "integrity": "sha512-98Eh7rsJNJF/Im6XYMLaOW3cLnNyedlOd6hu3iWMD5I7FZGgpw8yN3vQBrmLbLodu7G784Irb9Qsv2yFrxSAGw==", "requires": { - "ieee754": "^1.1.6", - "resolve-protobuf-schema": "^2.0.0" + "ieee754": "^1.1.12", + "resolve-protobuf-schema": "^2.1.0" } }, "pbkdf2": { @@ -8118,10 +7978,10 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "potpack": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.1.tgz", + "integrity": "sha512-15vItUAbViaYrmaB/Pbw7z6qX2xENbFSTA7Ii4tgbPtasxm5v6ryKhKtL91tpWovDJzTiZqdwzhcFBCwiMVdVw==" }, "preserve": { "version": "0.2.0", @@ -8390,23 +8250,6 @@ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz", "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" }, - "quote-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", - "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", - "requires": { - "buffer-equal": "0.0.1", - "minimist": "^1.1.3", - "through2": "^2.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, "randomatic": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", @@ -8619,13 +8462,6 @@ "integrity": "sha1-N+mQpvKyGyoRwuakj9QTVpjLqX8=", "requires": { "esprima": "~1.0.4" - }, - "dependencies": { - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" - } } }, "reflect-metadata": { @@ -8802,6 +8638,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -9066,11 +8903,6 @@ } } }, - "seedrandom": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz", - "integrity": "sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA==" - }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -9246,22 +9078,14 @@ "mixin-object": "^2.0.1" } }, - "shallow-copy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" - }, "sharkdown": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/sharkdown/-/sharkdown-0.1.0.tgz", - "integrity": "sha1-YdT+Up510CRCEnzJI0NiJlCZIU8=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sharkdown/-/sharkdown-0.1.1.tgz", + "integrity": "sha512-exwooSpmo5s45lrexgz6Q0rFQM574wYIX3iDZ7RLLqOb7IAoQZu9nxlZODU972g19sR69OIpKP2cpHTzU+PHIg==", "requires": { "cardinal": "~0.4.2", - "expect.js": "~0.2.0", "minimist": "0.0.5", - "split": "~0.2.10", - "stream-spigot": "~2.1.2", - "through": "~2.3.4" + "split": "~0.2.10" }, "dependencies": { "minimist": { @@ -9297,14 +9121,6 @@ "rechoir": "^0.6.2" } }, - "shuffle-seed": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/shuffle-seed/-/shuffle-seed-1.1.6.tgz", - "integrity": "sha1-UzwSaDurO0+j6HUfxOViFGdEJgs=", - "requires": { - "seedrandom": "^2.4.2" - } - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -9594,25 +9410,6 @@ "socks": "~2.2.0" } }, - "sort-asc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz", - "integrity": "sha1-q3md9h/HPqCVbHnEtTHtHp53J+k=" - }, - "sort-desc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz", - "integrity": "sha1-GYuMDN6wlcRjNBhh45JdTuNZqe4=" - }, - "sort-object": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz", - "integrity": "sha1-mODRme3kDgfGGoRAPGHWw7KQ+eI=", - "requires": { - "sort-asc": "^0.1.0", - "sort-desc": "^0.1.1" - } - }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -9622,7 +9419,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "source-map-loader": { "version": "0.2.4", @@ -9854,7 +9652,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { "version": "1.16.1", @@ -9882,14 +9681,6 @@ "safe-buffer": "^5.1.1" } }, - "static-eval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.0.tgz", - "integrity": "sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw==", - "requires": { - "escodegen": "^1.8.1" - } - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -9911,27 +9702,6 @@ } } }, - "static-module": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz", - "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", - "requires": { - "concat-stream": "~1.6.0", - "convert-source-map": "^1.5.1", - "duplexer2": "~0.1.4", - "escodegen": "~1.9.0", - "falafel": "^2.1.0", - "has": "^1.0.1", - "magic-string": "^0.22.4", - "merge-source-map": "1.0.4", - "object-inspect": "~1.4.0", - "quote-stream": "~1.0.2", - "readable-stream": "~2.3.3", - "shallow-copy": "~0.0.1", - "static-eval": "^2.0.0", - "through2": "~2.0.3" - } - }, "stats-webpack-plugin": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz", @@ -9996,37 +9766,6 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "stream-spigot": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/stream-spigot/-/stream-spigot-2.1.2.tgz", - "integrity": "sha1-feFF6Bn43Q20UJDRPc9zqO08wDU=", - "requires": { - "readable-stream": "~1.1.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, "streamroller": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", @@ -10105,11 +9844,6 @@ "is-utf8": "^0.2.0" } }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" - }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -10425,6 +10159,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" @@ -10823,14 +10558,6 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "requires": { - "prelude-ls": "~1.1.2" - } - }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", @@ -11095,11 +10822,6 @@ "extsprintf": "^1.2.0" } }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" - }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -11700,11 +11422,6 @@ "string-width": "^1.0.2 || 2" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, "worker-farm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", @@ -11792,7 +11509,8 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true }, "y18n": { "version": "4.0.0", diff --git a/package.json b/package.json index 2bf0bb7b..3b869f20 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "hamburgers": "^1.1.3", "jwt-decode": "^2.2.0", "lodash.clonedeep": "^4.5.0", - "mapbox-gl": "^0.47.0", + "mapbox-gl": "^0.51.0", "ng-inline-svg": "^8.2.1", "ng-lazyload-image": "^5.1.2", "ngx-cookie-service": "^2.1.0", @@ -63,7 +63,7 @@ "@types/jasmine": "^2.8.12", "@types/jasminewd2": "^2.0.6", "@types/jwt-decode": "^2.2.1", - "@types/mapbox-gl": "^0.47.0", + "@types/mapbox-gl": "^0.51.0", "@types/node": "^6.14.2", "codelyzer": "^4.5.0", "jasmine-core": "~2.8.0", diff --git a/src/app/core/interceptors/http-error-response-interceptor.ts b/src/app/core/interceptors/http-error-response-interceptor.ts index 83ae58e1..05ef4075 100644 --- a/src/app/core/interceptors/http-error-response-interceptor.ts +++ b/src/app/core/interceptors/http-error-response-interceptor.ts @@ -44,6 +44,7 @@ export class HttpErrorResponseInterceptor implements HttpInterceptor { console.log('HTTP ERROR: Server Error'); break; default: + console.log(err); console.log(`HTTP ERROR: Status code ${err.status}`); } } diff --git a/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.html b/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.html index b6e169e6..51d58ffe 100644 --- a/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.html +++ b/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.html @@ -1,3 +1,5 @@ <div> - <app-map></app-map> -</div> + <div *ngIf="metadata"> + <app-map [metadata]="metadata"></app-map> + </div> +</div> \ No newline at end of file diff --git a/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts b/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts index f0d0dc1c..35b24a3a 100644 --- a/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts +++ b/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts @@ -1,5 +1,8 @@ import { Component, OnInit, OnDestroy } from '@angular/core'; import { MapService } from '../../../../map/services/map.service'; +import { Subscription } from 'rxjs'; +import { Metadata } from '../../../models'; +import { DatasetDetailService } from '../../../services'; @Component({ selector: 'app-dataset-map', @@ -10,12 +13,23 @@ import { MapService } from '../../../../map/services/map.service'; export class DatasetMapComponent implements OnInit { mapLoaded: boolean; + datasetSub: Subscription; // Subscription to dataset change + metadata: Metadata; constructor( private _mapService: MapService, + private _datasetDetailService: DatasetDetailService, ) { } ngOnInit() { + this.metadata = this._datasetDetailService.datasetMetadata; + + // Subcribe to the dataset changes in the service. When the dataset is loaded + // (with the metadata), we construct the map and display the features + this.datasetSub = this._datasetDetailService.dataset$.subscribe(() => { + this.metadata = this._datasetDetailService.datasetMetadata; + }); + this._mapService.map$.subscribe(() => { this.mapLoaded = true; }); diff --git a/src/app/map/WMSStyleHelper.ts b/src/app/map/WMSStyleHelper.ts new file mode 100644 index 00000000..a2e3174c --- /dev/null +++ b/src/app/map/WMSStyleHelper.ts @@ -0,0 +1,3 @@ +export const wmsHelper = () => { + +}; diff --git a/src/app/map/components/map.component.html b/src/app/map/components/map.component.html index 8eb83b02..08065c03 100644 --- a/src/app/map/components/map.component.html +++ b/src/app/map/components/map.component.html @@ -55,7 +55,7 @@ <div class="columns is-mobile update-map" *ngIf="displayUpdateFeatures"> <div class="column is-narrow"> <div class="column-content"> - <a class="button is-medium" (click)="updateFeatures()"> + <a class="button is-medium"> <span i18n="@@dataset.detail.map.search">Search this area</span> <span class="icon" *ngIf="displaySpinner"> <i class="fas fa-spinner fa-spin"></i> diff --git a/src/app/map/components/map.component.ts b/src/app/map/components/map.component.ts index b52ce504..6c385ccf 100644 --- a/src/app/map/components/map.component.ts +++ b/src/app/map/components/map.component.ts @@ -16,12 +16,14 @@ import { linkFormats } from '../../geosource/models/metadata.model'; export class MapComponent implements OnInit, OnDestroy { + @Input() metadata: Metadata; + + sub: Subscription; + settings = settings; linkFormats = linkFormats; lang: string; // (fr or en) - metadata: Metadata; - sub: Subscription; // Subscription to dataset change featuresToChange: Subscription; map: mapboxgl.Map; @@ -42,6 +44,7 @@ export class MapComponent implements OnInit, OnDestroy { previousDatasetId: string; currentLayerType: string; + availableLayers: string[]; baseLayer3d = 1; displayControls = false; @@ -50,13 +53,12 @@ export class MapComponent implements OnInit, OnDestroy { fullscreen = false; constructor( - private _datasetDetailService: DatasetDetailService, private _mapService: MapService, ) { } ngOnInit() { this.initilizeLanguage(); - + this.initAvailableLayers(); this.constructMap(); // Events received here contain a state (if the data-detail panel has to be displayed or not) @@ -67,52 +69,38 @@ export class MapComponent implements OnInit, OnDestroy { this.selectedData = dataDetails.properties; } }); - - // Subcribe to the dataset changes in the service. When the dataset is loaded - // (with the metadata), we construct the map and display the features - this.sub = this._datasetDetailService.dataset$.subscribe(() => { - this.constructMap(); - }); - - // Display the update button when the service tell us the need - // to update the features (after and zoom interaction) - this._mapService.featuresToUpdate$.subscribe(() => { - if (this._datasetDetailService.datasetDataNumber > this.settings.maxDisplayFeatures) { - this.displayUpdateFeatures = true; - } - this.displayMessageLimitedFeatures = false; - }); - - // When features have been loaded, we hide the update button - this._mapService.mapUpdated$.subscribe((totalData) => { - this.displayUpdateFeatures = false; - this.displaySpinner = false; - if (totalData > this.settings.maxDisplayFeatures && this._datasetDetailService.datasetDataNumber < 100000) { - this.displayMessageLimitedFeatures = true; - this.totalData = totalData; - } - }); } // To avoid call the constructMap when we left the component // (because this is a custom observable, this is not automatically unsubscribed // when the component is destroyed) ngOnDestroy() { - this.sub.unsubscribe(); this._mapService.destroyMap(); } + initAvailableLayers() { + this.availableLayers = []; + this.metadata.link.forEach((link) => { + this.availableLayers.push(link.service); + }); + if (this.availableLayers.includes(linkFormats.wfs)) { + this.currentLayerType = linkFormats.wfs; + } else { + this.currentLayerType = linkFormats.wms; + } + + } + // When we get a metadata, we display the following: // - load Mapbox style file to get the styles and the base layers (vector, plan, satellite) constructMap() { - this.metadata = this._datasetDetailService.datasetMetadata; if (this.metadata) { // Set the basic and default options const options = { container: 'map', - center: [4.85, 45.75], + center: [4.85, 45.75] as mapboxgl.LngLatLike, zoom: 12, maxZoom: 21, }; @@ -156,20 +144,18 @@ export class MapComponent implements OnInit, OnDestroy { // Create the map with the associated style Mapbox file this.displayControls = true; - this.map = this._mapService.createMap(url, this.selectedBaseLayer, this.displayControls, options); - - // We create and add the layers (WMS/WFS) when the base layer is loaded - // (and not on map loaded, because when the style is refreshed, it removes all the sources associated) + this.map = this._mapService.createMap(this.metadata, url, this.selectedBaseLayer, this.displayControls, options); this.map.on('style.load', () => { - this._mapService.addLayers(); - this.currentLayerType = this._mapService.currentLayerType; - // When we come from a copy link, we need to update the features with the new bounding box - if (parameters.length === 6) { - this.updateFeatures(); - } + this._mapService.getWMSStyle() + .subscribe((res) => { + // We create and add the layers (WMS/WFS) when the base layer is loaded + // (and not on map loaded, because when the style is refreshed, it removes all the sources associated) + this._mapService.addLayers(); + this.currentLayerType = this._mapService.currentLayerType; + }); + + this._mapService.previousDatasetId = this.metadata.dataset_id; }); - - this._mapService.previousDatasetId = this.metadata.dataset_id; } } @@ -178,11 +164,6 @@ export class MapComponent implements OnInit, OnDestroy { this._mapService.switchLayer(baseLayer); } - updateFeatures() { - this.displaySpinner = true; - this._mapService.updateFeatures(); - } - // Looks for the language to be used, if not indicated in the url takes the navigator default language initilizeLanguage() { let language = window.location.pathname.split('/')[1]; @@ -196,15 +177,6 @@ export class MapComponent implements OnInit, OnDestroy { } } - switch3DLayer() { - if (this.map.isStyleLoaded()) { - if (this.map.getSource('openmaptiles')) { - this.display3d = !this.display3d; - this._mapService.switch3DLayer(); - } - } - } - changeMapPitchValue(val: number) { this.map.setPitch(val); } @@ -221,7 +193,7 @@ export class MapComponent implements OnInit, OnDestroy { this.shareMessage = geosource.mapMessages.copied; setTimeout(() => { this.shareMessage = geosource.mapMessages.share; - }, 2000); + }, 2000); } mapUrl() { diff --git a/src/app/map/components/minimap-control.ts b/src/app/map/components/minimap-control.ts index 1b41fbfa..cacf6125 100644 --- a/src/app/map/components/minimap-control.ts +++ b/src/app/map/components/minimap-control.ts @@ -26,7 +26,7 @@ export class Minimap { width: '300px', height: '170px', style: '', - center: [0, 0], + center: [0, 0] as mapboxgl.LngLatLike, zoom: 6, bounds: 'parent', classes: '', diff --git a/src/app/map/services/map.service.ts b/src/app/map/services/map.service.ts index cad3e125..7d7a8f06 100644 --- a/src/app/map/services/map.service.ts +++ b/src/app/map/services/map.service.ts @@ -3,16 +3,16 @@ import { Observable, Subject, BehaviorSubject, of, fromEvent, Subscription } fro import { Metadata, IMetadataLink } from '../../geosource/models'; import { Notification } from '../../core/models'; import * as mapboxgl from 'mapbox-gl'; -import { map, catchError, debounceTime } from 'rxjs/operators'; -import { ElasticsearchService } from '../../geosource/services/elasticsearch.service'; +import { map, debounceTime } from 'rxjs/operators'; import { NotificationService } from '../../core/services'; import { notificationMessages } from '../../../i18n/traductions.fr'; import { Minimap } from '../components/minimap-control'; -import { DatasetDetailService } from '../../geosource/services'; import { settings } from '../settings'; import * as cloneDeep from 'lodash.clonedeep'; import { linkFormats } from '../../geosource/models/metadata.model'; +import { HttpClient } from '@angular/common/http'; +import { NullInjector } from '@angular/core/src/di/injector'; @Injectable() export class MapService { @@ -21,7 +21,11 @@ export class MapService { private _map: mapboxgl.Map; private url: string; selectedBaseLayer; + metadata: Metadata; + uriWFS: IMetadataLink; + uriWMS: IMetadataLink; + eventPopupAdded = false; minimap: Minimap; mapIsConstructed: boolean = false; @@ -29,8 +33,11 @@ export class MapService { // Map featureColor: string = '#1d92ff'; - featureColorHalo: string = 'rgba(29, 146, 255, 0.3)'; - featureHighlightedColor: string = '#da322f'; // Tomato color + featureHoverColor: string = '#235b8f'; + featureHighlightedColor: string = '#F72F2F'; // Tomato color + + hoveredFeatureId: string; + highlightedFeatureId: string; // This is used to remeber what is the previous dataset that the map displayed. // The reason is to know if we need to display the same map settings (for example the user went to another @@ -47,6 +54,8 @@ export class MapService { geojson: GeoJSON.FeatureCollection; totalData: number; + wmsStyle: []; + // Properties used to send information to the component // about the features state (need to update or not) private _mapToUpdate = new Subject<any>(); @@ -55,13 +64,17 @@ export class MapService { _errorService: any; constructor( - private _elasticSearchService: ElasticsearchService, private _notificationService: NotificationService, - private _datasetDetailService: DatasetDetailService, + private _httpClient: HttpClient, ) { } - createMap(url: string, baseLayer: any, addControls: boolean, options?: mapboxgl.MapboxOptions): mapboxgl.Map { - this.metadata = this._datasetDetailService.datasetMetadata; + createMap( + metadata: Metadata, + url: string, baseLayer: any, addControls: boolean, options?: mapboxgl.MapboxOptions): mapboxgl.Map { + this.metadata = metadata; + this.uriWFS = this.metadata.link.find((e) => { return e.service === linkFormats.wfs; }); + this.uriWMS = this.metadata.link.find((e) => { return e.service === linkFormats.wms; }); + // Reset to false in ordre to set event listener this.eventPopupAdded = false; // Re-initialize panel state @@ -78,6 +91,7 @@ export class MapService { // Subscribe to the error observable and send a notification this._errorSubscription = errorObservable.subscribe((v) => { + console.log(v); this._notificationService.notify( new Notification({ message: notificationMessages.geosource.mapError, @@ -117,6 +131,7 @@ export class MapService { this.mapIsConstructed = true; return this._map; + } // Three strategies to display the map depending the number of data and the type of service: @@ -125,301 +140,668 @@ export class MapService { // - if WFS exists but data > 100 000, or if WFS no exist: we display the WMS layer addLayers() { // Check if the metadata has WFS data format. - const uriWFS = this.metadata.link.find((e) => { return e.service === linkFormats.wfs; }); - if (uriWFS && this._datasetDetailService.datasetDataNumber < 100000) { - this._currentLayerType = linkFormats.wfs; - this.getWFSFeatures( - this.metadata, - settings.maxDisplayFeatures).subscribe((geojson) => { - this.geojson = geojson; - this.addWFSLayer(); - }); - this._map - .on('zoomend', () => { - this._mapToUpdate.next(); - }) - .on('moveend', () => { - this._mapToUpdate.next(); - }); + // const uriWFS = this.metadata.link.find((e) => { return e.service === linkFormats.wfs; }); + // if (uriWFS && this._datasetDetailService.datasetDataNumber < 100000) { + // this._currentLayerType = linkFormats.wfs; + // this.getWFSFeatures( + // this.metadata, + // settings.maxDisplayFeatures).subscribe((geojson) => { + // this.geojson = geojson; + // this.addWFSLayer(); + // }); + // this._map + // .on('zoomend', () => { + // this._mapToUpdate.next(); + // }) + // .on('moveend', () => { + // this._mapToUpdate.next(); + // }); + // // .on('sourcedata', () => { + // // console.log('source data'); + // // if (this._map.isSourceLoaded('wfs-polygon') && this._map.isSourceLoaded('wfs-clustered-points')) { + // // console.log(this._map.getBounds()); + // // const bounds = new mapboxgl.LngLatBounds( + // // [this.metadata.max_east, this.metadata.max_south], + // // [this.metadata.max_west, this.metadata.max_north], + // // ); + // // console.log(bounds); + + // // this._map.fitBounds(bounds); + // // } + // // }); + + // } else { + // this._currentLayerType = linkFormats.wms; + // const uriWMS = this.metadata.link.find((e) => { return e.service === linkFormats.wms; }); + // this.addWMSLayer(uriWMS); + // } + + this._currentLayerType = linkFormats.wfs; + const url = 'https://download.data.grandlyon.com/mvt/grandlyon?LAYERS' + + `=${this.uriWFS.name}&map.imagetype=mvt&tilemode=gmap&tile={x}+{y}+{z}&mode=tile`; + + this._map.addSource('vector-source', { + type: 'vector', + tiles: [url], + }); - } else { - this._currentLayerType = linkFormats.wms; - const uriWMS = this.metadata.link.find((e) => { return e.service === linkFormats.wms; }); - this.addWMSLayer(uriWMS); - } + this.addMVTLayers(); } - // Get the features inside the bounds of the map, and update the data - // associated to the source of the map - updateFeatures() { - this.closePanel(); - const bounds = this._map.getBounds(); - this.getWFSFeatures(this.metadata, settings.maxDisplayFeatures, bounds).subscribe((geojson) => { - this.geojson = geojson; - const source1 = this._map.getSource('wfs-clustered-points') as mapboxgl.GeoJSONSource; - const source2 = this._map.getSource('wfs-polygon') as mapboxgl.GeoJSONSource; - source1.setData(geojson); - source2.setData(geojson); - // Notify to the component that the map has been ipdated with new features - this._mapUpdated.next(this.totalData); - }); + getWMSStyle() { + return this._httpClient.get<[]>(`http://192.168.62.15:3008?root=${this.uriWMS.url}&id=${this.uriWMS.name}`).pipe( + map((wmsStyle) => { + console.log(wmsStyle); + this.wmsStyle = wmsStyle; + })); } - // - Fetch data from ES - // - Add it to the map source - // - Create the WFS layers from this source - // - if the features are 'Point' type, create clustering layers - addWFSLayer() { - this._map.addSource('wfs-clustered-points', { - type: 'geojson', - data: this.geojson, - cluster: true, - clusterMaxZoom: 13, // Max zoom to cluster points on - clusterRadius: 45, // Radius of each cluster when clustering points (defaults to 50) - }); + addMVTLayers(colorExpression?: any) { + const symbol = { + options: [], + }; + this.wmsStyle.forEach((rule) => { + const options = {}; - this._map.addSource('wfs-polygon', { - type: 'geojson', - data: this.geojson, - }); + if (rule['filter']) { + symbol['filters'] = true; + symbol['property'] = rule['filter'][1]; - // Add the layers for 'Point' features (clustered and unclustered layers) - // Create steps to display different circle size and colors depending the count - this._map.addLayer({ - id: 'point-features', - type: 'circle', - source: 'wfs-clustered-points', - paint: { - // Use step expressions (https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step) - // with three steps to implement three types of circles: - // * 20px circles when point count is less than 20 - // * 30px circles when point count is between 20 and 50 - // * 40px circles when point count is greater than or equal to 50 - 'circle-color': this.featureColor, - 'circle-radius': [ - 'step', - ['get', 'point_count'], - 20, // 20px - 20, // les than 20 features - 30, // 30px - 50, // until - more 50 features - 40, // 40px - ], - 'circle-stroke-width': [ - 'step', - ['get', 'point_count'], - 4, // 4px - 20, // les than 20 features - 6, // 6px - 50, // until - more 50 features - 11, // 11px - ], - 'circle-stroke-color': this.featureColorHalo, - }, - filter: ['has', 'point_count'], - }); + // // Check the type of the property + // this.d - // Add the cluster count layer (the number inside the circle) - this._map.addLayer({ - id: 'cluster-count', - type: 'symbol', - source: 'wfs-clustered-points', - filter: ['has', 'point_count'], - layout: { - 'text-field': '{point_count_abbreviated}', - 'text-size': 14, - 'text-font': ['Noto Sans Bold'], - }, - paint: { - 'text-color': 'white', - }, - }); + options['operator'] = rule['filter'][0]; + options['value'] = rule['filter'][2]; + options['symbol'] = rule['symbolizers'][0]; + + symbol['options'].push(options); + } else { + symbol['symbol'] = rule['symbolizers'][0]; + } + symbol['type'] = rule['symbolizers'][0]['wellKnownName']; + symbol['kind'] = rule['symbolizers'][0]['kind']; - // For 'Polygon' feature highlighted - this._map.addLayer({ - id: 'polygon-features-highlight', - type: 'fill', - layout: { - visibility: 'none', - }, - source: 'wfs-polygon', - paint: { - 'fill-color': this.featureHighlightedColor, - 'fill-opacity': 0.4, - 'fill-outline-color': 'white', - }, - filter: ['==', '$type', 'Polygon'], }); + console.log(symbol); - // For 'Polygon' and 'MultiPolygon' features, one layer is enough (no cluster) - this._map.addLayer( - { - id: 'polygon-features', - type: 'fill', - source: 'wfs-polygon', - paint: { - 'fill-color': this.featureColor, - 'fill-opacity': 0.4, - 'fill-outline-color': 'white', - }, - filter: ['match', ['geometry-type'], ['Polygon', 'MultiPolygon'], true, false], - }, - 'polygon-features-highlight', - ); - - // For 'LineString' feature selected highlight - this._map.addLayer({ - id: 'line-features-highlight', - type: 'line', - source: 'wfs-polygon', - layout: { - 'line-cap': 'round', - 'line-join': 'round', - visibility: 'none', - }, - paint: { - 'line-color': this.featureHighlightedColor, - 'line-width': 3, + let layout = null; + let paint = null; + let type = null; + + if (symbol['type'] === 'Circle') { + type = 'circle'; + + const circleColorOption = []; + circleColorOption.push('case'); + circleColorOption.push(['boolean', ['feature-state', 'hover'], false]); + circleColorOption.push(this.featureHoverColor); + circleColorOption.push(['boolean', ['feature-state', 'highlight'], false]); + circleColorOption.push(this.featureHighlightedColor); + + if (symbol['filters']) { + symbol.options.forEach((option) => { + const condition = []; + condition.push('=='); + // condition.push(option['operator']); + condition.push(['to-string', ['get', symbol['property']]], option['value']); + circleColorOption.push(condition); + + circleColorOption.push(option['symbol']['color']); + // condition.push(this.featureColor); + + }); + circleColorOption.push(this.featureColor); + } else { + circleColorOption.push(symbol['symbol']['color']); + } + + paint = { + 'circle-stroke-width': 1, + 'circle-stroke-opacity': 0.5, + 'circle-stroke-color': '#000', + 'circle-color': + circleColorOption, + }; + } else if (symbol['type'] === 'Triangle' || symbol['type'] === 'Square') { + type = 'symbol'; + const iconShape = symbol['type'] === 'Triangle' ? 'triangle-15' : 'square-15'; + layout = { + 'icon-image': 'triangle-15', + 'icon-size': 1, + 'icon-anchor': 'bottom', + 'icon-allow-overlap': true, + }; + paint = { + 'icon-color': ['case', + ['boolean', ['feature-state', 'hover'], false], + this.featureHoverColor, + ['boolean', ['feature-state', 'highlight'], false], + this.featureHighlightedColor, + symbol['symbol']['color'], + ], + } + } else if (symbol['kind'] === 'Line') { + let lineColorOption = null; + + if (symbol['filters']) { + lineColorOption = []; + lineColorOption.push('=='); + lineColorOption.push(['get', symbol['property']]); + symbol.options.forEach((option) => { + lineColorOption.push(option['value']); + lineColorOption.push(option['symbol']['color']); + }); + lineColorOption.push(this.featureColor); + } else { + lineColorOption = symbol['symbol']['color']; + // lineWidth = symbol['symbol']['width']; + } + + paint = { 'line-opacity': 0.8, - }, - }); + 'line-color': ['case', + ['boolean', ['feature-state', 'hover'], false], + this.featureHoverColor, + ['boolean', ['feature-state', 'highlight'], false], + this.featureHighlightedColor, + lineColorOption, + ], + 'line-width': 2, + }; + } - // For 'LineString' and 'MultiLineString features, one layer is enough (no cluster) - this._map.addLayer( - { - id: 'line-features', - type: 'line', - source: 'wfs-polygon', - layout: { - 'line-cap': 'round', - 'line-join': 'round', - }, - paint: { - 'line-color': this.featureColor, - 'line-width': 3, - 'line-opacity': 0.8, - }, - filter: ['match', ['geometry-type'], ['LineString', 'MultiLineString'], true, false], - }, - 'line-features-highlight', - ); - - this._map.loadImage('./assets/img/marker_blue_active.png', (error, image) => { - if (error) throw error; - this._map.addImage('marker-active', image); - - this._map.loadImage('./assets/img/marker_blue_hover.png', (error, image) => { - if (error) throw error; - this._map.addImage('marker-hover', image); - // Add layer + style for the unclustered points highlighted - this._map.addLayer( - { - id: 'unclustered-point-highlighted', - type: 'symbol', - source: 'wfs-clustered-points', - filter: ['!has', 'point_count'], - layout: { - 'icon-image': 'marker-active', - 'icon-size': 0.5, - 'icon-anchor': 'bottom', - 'icon-allow-overlap': true, - visibility: 'none', - }, + if (symbol['kind'] === 'Polygon') { + // For 'Polygon' and 'MultiPolygon' features + this._map.addLayer( + { + id: 'polygon-features', + type: 'fill', + source: 'vector-source', + 'source-layer': this.uriWFS.name, + paint: { + 'fill-color': ['case', + ['boolean', ['feature-state', 'hover'], false], + this.featureHoverColor, + ['boolean', ['feature-state', 'highlight'], false], + this.featureHighlightedColor, + ['case', + ['match', ['get', 'codegenre'], '2'], + '#99cc00', + '#99cc00', + ], + ], + 'fill-opacity': 0.4, }, - ); + filter: ['match', ['geometry-type'], ['Polygon', 'MultiPolygon'], true, false], + }); + } - this._map.loadImage('./assets/img/marker_blue_normal.png', (error, image) => { - if (error) throw error; - this._map.addImage('marker', image); - // Add layer + style for the unclustered points - this._map.addLayer( - { - id: 'unclustered-point', - type: 'symbol', - source: 'wfs-clustered-points', - filter: ['!has', 'point_count'], - layout: { - 'icon-image': 'marker', - 'icon-size': 0.5, - 'icon-anchor': 'bottom', - 'icon-allow-overlap': true, - }, - }, - 'unclustered-point-highlighted', - ); + if (symbol['kind'] === 'Line') { + // For 'LineString' and 'MultiLineString features + this._map.addLayer( + { + paint, + id: 'line-features', + type: 'line', + source: 'vector-source', + 'source-layer': this.uriWFS.name, + layout: { + 'line-cap': 'round', + 'line-join': 'round', + }, + // 'line-color': ['case', + // ['boolean', ['feature-state', 'hover'], false], + // this.featureHoverColor, + // ['boolean', ['feature-state', 'highlight'], false], + // this.featureHighlightedColor, + // this.featureColor, + // ], + // 'line-width': [ + // 'interpolate', ['linear'], ['zoom'], + // 12, 1, + // 13, 2, + // 16, 10, + // ], + filter: ['match', ['geometry-type'], ['LineString', 'MultiLineString'], true, false], + }, + ); + } - this._map.addLayer( - { - id: 'unclustered-point-hover', - type: 'symbol', - source: 'wfs-clustered-points', - filter: ['==', '_featureId', ''], - layout: { - 'icon-image': 'marker-hover', - 'icon-size': 0.5, - 'icon-anchor': 'bottom', - 'icon-allow-overlap': true, - visibility: 'none', - }, - }, - ); - }); - }); - }); + console.log(layout); + console.log(paint); - if (!this.eventPopupAdded) { - // Change the cursor to a pointer when the mouse is over the unclustered-point layer. - this._map.on('mouseenter', 'unclustered-point', (e) => { - this._map.getCanvas().style.cursor = 'pointer'; - const hoveredFeature = e.features[0].properties._featureId; - this._map.setFilter('unclustered-point-hover', ['==', '_featureId', hoveredFeature]); - this._map.setLayoutProperty('unclustered-point-hover', 'visibility', 'visible'); - }).on('mouseleave', 'unclustered-point', () => { - this._map.getCanvas().style.cursor = ''; - this._map.setFilter('unclustered-point-hover', ['==', '_featureId', '']); - this._map.setLayoutProperty('unclustered-point-hover', 'visibility', 'none'); + const optionsLayer = { + type, + id: 'point-features', + source: 'vector-source', + 'source-layer': this.uriWFS.name, + filter: ['match', ['geometry-type'], ['Point'], true, false], + }; + if (layout) { + optionsLayer['layout'] = layout; + } + if (paint) { + optionsLayer['paint'] = paint; + } + this._map.addLayer(optionsLayer); + // ['match', + // ['get', 'codegenre'], + // 0, '#ffffff', + // 1, '#969696', + // 2, '#99cc00', + // /* other */ this.featureColor, + // ], + + if (!this.eventPopupAdded) { + // Manage the cursor and feature state for point-features layer when mouse events + this._map.on('mousemove', 'point-features', (e) => { + this.manageFeatureOnMouseMove(e.features); + }); + this._map.on('mouseleave', 'point-features', (e) => { + this.manageFeatureOnMouseEnd(); }); - this._map.on('mouseenter', 'polygon-features', () => { - this._map.getCanvas().style.cursor = 'pointer'; - }).on('mouseleave', 'polygon-features', () => { - this._map.getCanvas().style.cursor = ''; + // Manage the cursor and feature state for polygon-features layer when mouse events + this._map.on('mousemove', 'polygon-features', (e) => { + this.manageFeatureOnMouseMove(e.features); + }); + this._map.on('mouseleave', 'polygon-features', (e) => { + this.manageFeatureOnMouseEnd(); }); - this._map.on('mouseenter', 'line-features', () => { - this._map.getCanvas().style.cursor = 'pointer'; - }).on('mouseleave', 'line-features', () => { - this._map.getCanvas().style.cursor = ''; + // Manage the cursor and feature state for line-features layer when mouse events + this._map.on('mousemove', 'line-features', (e) => { + this.manageFeatureOnMouseMove(e.features); + }); + this._map.on('mouseleave', 'line-features', (e) => { + this.manageFeatureOnMouseEnd(); }); - // When a click event occurs on a feature in the states layer + // When a click event occurs on the map, close the information panel this._map.on('click', () => { - // Reset state of panel this.closePanel(); }); - this.addClickEventOnLayer('unclustered-point', 'unclustered-point-highlighted'); - this.addClickEventOnLayer('polygon-features', 'polygon-features-highlight'); - this.addClickEventOnLayer('line-features', 'line-features-highlight'); + if (this._map.getLayer('point-features')) { + this.addClickEventOnLayer('point-features'); + } + if (this._map.getLayer('polygon-features')) { + this.addClickEventOnLayer('polygon-features'); + } + if (this._map.getLayer('line-features')) { + this.addClickEventOnLayer('line-features'); + } this.eventPopupAdded = true; } } - addClickEventOnLayer(layer, highlightedLayer) { + getPointPaintOptions(totalFeatures: number, colorExpression?: any) { + const paintOptions = { + 'circle-stroke-color': 'white', + 'circle-stroke-width': [ + 'interpolate', ['linear'], ['zoom'], + 10, 0.3, + 12, 0.3, + 16, 0.7, + ], + }; + if (colorExpression) { + paintOptions['circle-color'] = colorExpression; + } else { + paintOptions['circle-color'] = ['case', + ['boolean', ['feature-state', 'hover'], false], + this.featureHoverColor, + ['boolean', ['feature-state', 'highlight'], false], + this.featureHighlightedColor, + this.featureColor, + ]; + } + if (totalFeatures < 1000) { + paintOptions['circle-radius'] = [ + 'interpolate', ['linear'], ['zoom'], + 10, 1.75, + 12, 4, + 16, 10, + ]; + } else { + paintOptions['circle-radius'] = [ + 'interpolate', ['linear'], ['zoom'], + 12, 2.5, + 16, 8, + ]; + } + return paintOptions; + } + + // Change the state of one feature. + // State has the following format:{state: value} + // Ex: {hover: true, highlight: false} + changeFeatureState(featureId: string, state) { + if (featureId) { + this._map.setFeatureState( + { + source: 'vector-source', + sourceLayer: this.uriWFS.name, + id: featureId, + }, + state); + } + } + + manageFeatureOnMouseMove(features: any) { + if (features.length > 0) { + this._map.getCanvas().style.cursor = 'pointer'; + if (this.hoveredFeatureId) { + this.changeFeatureState(this.hoveredFeatureId, { hover: false }); + } + + this.hoveredFeatureId = features[0].id; + + // Display hover state only if not already highlighted + const state = this._map.getFeatureState({ + source: 'vector-source', + sourceLayer: this.uriWFS.name, + id: this.hoveredFeatureId, + }); + if (!state.highlight) { + this.changeFeatureState(this.hoveredFeatureId, { hover: true }); + } + } + } + + + manageFeatureOnMouseEnd() { + if (this.hoveredFeatureId) { + this._map.getCanvas().style.cursor = ''; + this.changeFeatureState(this.hoveredFeatureId, { hover: false }); + } + this.hoveredFeatureId = null; + } + + // Get the features inside the bounds of the map, and update the data + // associated to the source of the map + // updateFeatures() { + // this.closePanel(); + // const bounds = this._map.getBounds(); + // this.getWFSFeatures(this.metadata, settings.maxDisplayFeatures, bounds).subscribe((geojson) => { + // this.geojson = geojson; + // const source1 = this._map.getSource('wfs-clustered-points') as mapboxgl.GeoJSONSource; + // const source2 = this._map.getSource('wfs-polygon') as mapboxgl.GeoJSONSource; + // source1.setData(geojson); + // source2.setData(geojson); + // // Notify to the component that the map has been ipdated with new features + // this._mapUpdated.next(this.totalData); + // }); + // } + + // - Fetch data from ES + // - Add it to the map source + // - Create the WFS layers from this source + // - if the features are 'Point' type, create clustering layers + // addWFSLayer() { + // this._map.addSource('wfs-clustered-points', { + // type: 'geojson', + // data: this.geojson, + // cluster: true, + // clusterMaxZoom: 13, // Max zoom to cluster points on + // clusterRadius: 45, // Radius of each cluster when clustering points (defaults to 50) + // }); + + // this._map.addSource('wfs-polygon', { + // type: 'geojson', + // data: this.geojson, + // }); + + // // Add the layers for 'Point' features (clustered and unclustered layers) + // // Create steps to display different circle size and colors depending the count + // this._map.addLayer({ + // id: 'point-features', + // type: 'circle', + // source: 'wfs-clustered-points', + // paint: { + // // Use step expressions (https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step) + // // with three steps to implement three types of circles: + // // * 20px circles when point count is less than 20 + // // * 30px circles when point count is between 20 and 50 + // // * 40px circles when point count is greater than or equal to 50 + // 'circle-color': this.featureColor, + // 'circle-radius': [ + // 'step', + // ['get', 'point_count'], + // 20, // 20px + // 20, // les than 20 features + // 30, // 30px + // 50, // until - more 50 features + // 40, // 40px + // ], + // 'circle-stroke-width': [ + // 'step', + // ['get', 'point_count'], + // 4, // 4px + // 20, // les than 20 features + // 6, // 6px + // 50, // until - more 50 features + // 11, // 11px + // ], + // 'circle-stroke-color': this.featureColorHalo, + // }, + // filter: ['has', 'point_count'], + // }); + + // // Add the cluster count layer (the number inside the circle) + // this._map.addLayer({ + // id: 'cluster-count', + // type: 'symbol', + // source: 'wfs-clustered-points', + // filter: ['has', 'point_count'], + // layout: { + // 'text-field': '{point_count_abbreviated}', + // 'text-size': 14, + // 'text-font': ['Noto Sans Bold'], + // }, + // paint: { + // 'text-color': 'white', + // }, + // }); + + // // For 'Polygon' feature highlighted + // this._map.addLayer({ + // id: 'polygon-features-highlight', + // type: 'fill', + // layout: { + // visibility: 'none', + // }, + // source: 'wfs-polygon', + // paint: { + // 'fill-color': this.featureHighlightedColor, + // 'fill-opacity': 0.4, + // 'fill-outline-color': 'white', + // }, + // filter: ['==', '$type', 'Polygon'], + // }); + + // // For 'Polygon' and 'MultiPolygon' features, one layer is enough (no cluster) + // this._map.addLayer( + // { + // id: 'polygon-features', + // type: 'fill', + // source: 'wfs-polygon', + // paint: { + // 'fill-color': this.featureColor, + // 'fill-opacity': 0.4, + // 'fill-outline-color': 'white', + // }, + // filter: ['match', ['geometry-type'], ['Polygon', 'MultiPolygon'], true, false], + // }, + // 'polygon-features-highlight', + // ); + + // // For 'LineString' feature selected highlight + // this._map.addLayer({ + // id: 'line-features-highlight', + // type: 'line', + // source: 'wfs-polygon', + // layout: { + // 'line-cap': 'round', + // 'line-join': 'round', + // visibility: 'none', + // }, + // paint: { + // 'line-color': this.featureHighlightedColor, + // 'line-width': 3, + // 'line-opacity': 0.8, + // }, + // }); + + // // For 'LineString' and 'MultiLineString features, one layer is enough (no cluster) + // this._map.addLayer( + // { + // id: 'line-features', + // type: 'line', + // source: 'wfs-polygon', + // layout: { + // 'line-cap': 'round', + // 'line-join': 'round', + // }, + // paint: { + // 'line-color': this.featureColor, + // 'line-width': 3, + // 'line-opacity': 0.8, + // }, + // filter: ['match', ['geometry-type'], ['LineString', 'MultiLineString'], true, false], + // }, + // 'line-features-highlight', + // ); + + // this._map.loadImage('./assets/img/marker_blue_active.png', (error, image) => { + // if (error) throw error; + // this._map.addImage('marker-active', image); + + // this._map.loadImage('./assets/img/marker_blue_hover.png', (error, image) => { + // if (error) throw error; + // this._map.addImage('marker-hover', image); + // // Add layer + style for the unclustered points highlighted + // this._map.addLayer( + // { + // id: 'unclustered-point-highlighted', + // type: 'symbol', + // source: 'wfs-clustered-points', + // filter: ['!has', 'point_count'], + // layout: { + // 'icon-image': 'marker-active', + // 'icon-size': 0.5, + // 'icon-anchor': 'bottom', + // 'icon-allow-overlap': true, + // visibility: 'none', + // }, + // }, + // ); + + // this._map.loadImage('./assets/img/marker_blue_normal.png', (error, image) => { + // if (error) throw error; + // this._map.addImage('marker', image); + // // Add layer + style for the unclustered points + // this._map.addLayer( + // { + // id: 'unclustered-point', + // type: 'symbol', + // source: 'wfs-clustered-points', + // filter: ['!has', 'point_count'], + // layout: { + // 'icon-image': 'triangle-15', + // 'icon-size': 2, + // 'icon-anchor': 'bottom', + // 'icon-allow-overlap': true, + // }, + // }, + // 'unclustered-point-highlighted', + // ); + + // this._map.addLayer( + // { + // id: 'unclustered-point-hover', + // type: 'symbol', + // source: 'wfs-clustered-points', + // filter: ['==', '_featureId', ''], + // layout: { + // 'icon-image': 'triangle-15', + // 'icon-size': 2, + // 'icon-anchor': 'bottom', + // 'icon-allow-overlap': true, + // visibility: 'none', + // }, + // paint: { + // 'icon-color': 'red', + // } + // }, + // ); + // }); + // }); + // }); + + // if (!this.eventPopupAdded) { + // // Change the cursor to a pointer when the mouse is over the unclustered-point layer. + // this._map.on('mouseenter', 'unclustered-point', (e) => { + // this._map.getCanvas().style.cursor = 'pointer'; + // const hoveredFeature = e.features[0].properties._featureId; + // this._map.setFilter('unclustered-point-hover', ['==', '_featureId', hoveredFeature]); + // this._map.setLayoutProperty('unclustered-point-hover', 'visibility', 'visible'); + // }).on('mouseleave', 'unclustered-point', () => { + // this._map.getCanvas().style.cursor = ''; + // this._map.setFilter('unclustered-point-hover', ['==', '_featureId', '']); + // this._map.setLayoutProperty('unclustered-point-hover', 'visibility', 'none'); + + // }); + + // this._map.on('mouseenter', 'polygon-features', () => { + // this._map.getCanvas().style.cursor = 'pointer'; + // }).on('mouseleave', 'polygon-features', () => { + // this._map.getCanvas().style.cursor = ''; + // }); + + // this._map.on('mouseenter', 'line-features', () => { + // this._map.getCanvas().style.cursor = 'pointer'; + // }).on('mouseleave', 'line-features', () => { + // this._map.getCanvas().style.cursor = ''; + // }); + + // // When a click event occurs on a feature in the states layer + // this._map.on('click', () => { + // // Reset state of panel + // this.closePanel(); + // }); + + // this.addClickEventOnLayer('unclustered-point', 'unclustered-point-highlighted'); + // this.addClickEventOnLayer('polygon-features', 'polygon-features-highlight'); + // this.addClickEventOnLayer('line-features', 'line-features-highlight'); + + // this.eventPopupAdded = true; + // } + + // } + + addClickEventOnLayer(layer: string) { this._map.on('click', layer, (e) => { - this.selectedFeature = e.features[0].properties._featureId; - this._map.setFilter(highlightedLayer, ['==', ['get', '_featureId'], this.selectedFeature]); - this._map.setLayoutProperty(highlightedLayer, 'visibility', 'visible'); + this.selectedFeature = e.features[0].id; + console.log(this.hoveredFeatureId); + // Reset the hover and highglithed state for the current and previous feature + this.changeFeatureState(this.hoveredFeatureId, { highlight: false }); + this.changeFeatureState(this.highlightedFeatureId, { highlight: false }); + // Set highlited style for the current feature + this.highlightedFeatureId = this.selectedFeature; + this.changeFeatureState(this.highlightedFeatureId, { highlight: true }); + + const feature = e.features[0]; this.handleMapPosition(e.point.x, e.lngLat, () => { - const feature = this.geojson.features.find(f => f.properties._featureId === this.selectedFeature); + const featureCloned = cloneDeep(feature); // Remove the generated id from the properties to be displayed - delete featureCloned.properties._featureId; + delete featureCloned.id; this._panelState.next({ state: true, properties: featureCloned.properties }); }); }); @@ -436,41 +818,41 @@ export class MapService { } // Add the raster (WMS) layer - addWMSLayer(uriWMS: IMetadataLink) { - // ------------------- WMS Source & Layer ------------------- - this._map.addSource(linkFormats.wms, { - type: 'raster', - tiles: [ - `${uriWMS.url}?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&` + - `srs=EPSG:3857&width=256&height=256&transparent=true&layers=${uriWMS.name}`, - ], - tileSize: 256, - }); - - this._map.addLayer({ - id: 'wms-layer', - type: 'raster', - source: 'WMS', - paint: {}, - }); - - this._map.on('click', (e) => { - this.getFeatureInfo(e.lngLat.lng, e.lngLat.lat).subscribe((feature) => { - if (feature) { - this.selectedFeature = feature.properties.gid; - this.handleMapPosition(e.point.x, e.lngLat, () => { - this._panelState.next({ state: true, properties: feature.properties }); - }); - } - }), - catchError( - (err) => { - // If no data, do nothing - return of(null); - }, - ); - }); - } + // addWMSLayer(uriWMS: IMetadataLink) { + // // ------------------- WMS Source & Layer ------------------- + // this._map.addSource(linkFormats.wms, { + // type: 'raster', + // tiles: [ + // `${uriWMS.url}?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&` + + // `srs=EPSG:3857&width=256&height=256&transparent=true&layers=${uriWMS.name}`, + // ], + // tileSize: 256, + // }); + + // this._map.addLayer({ + // id: 'wms-layer', + // type: 'raster', + // source: 'WMS', + // paint: {}, + // }); + + // this._map.on('click', (e) => { + // this.getFeatureInfo(e.lngLat.lng, e.lngLat.lat).subscribe((feature) => { + // if (feature) { + // this.selectedFeature = feature.properties.gid; + // this.handleMapPosition(e.point.x, e.lngLat, () => { + // this._panelState.next({ state: true, properties: feature.properties }); + // }); + // } + // }), + // catchError( + // (err) => { + // // If no data, do nothing + // return of(null); + // }, + // ); + // }); + // } destroyMap() { this._map.remove(); @@ -524,96 +906,96 @@ export class MapService { // Get features from ES. Construct GeoJSON.FeatureCollection Object from it // For 'MultiPoint' type feature, we explode it in multiple 'Point' type features - getWFSFeatures(metadata: Metadata, count: number, bounds?: mapboxgl.LngLatBounds): - Observable<GeoJSON.FeatureCollection> { - - let coordinates = null; - if (bounds) { - coordinates = []; - coordinates.push([bounds.getNorthWest().lng, bounds.getNorthWest().lat]); - coordinates.push([bounds.getSouthEast().lng, bounds.getSouthEast().lat]); - } - - return this._elasticSearchService.getDataByBbox( - metadata.geonet.uuid, - count, - coordinates).pipe( - map((elasticResponse) => { - const uriWFS = metadata.link.find((e) => { return e.service === linkFormats.wfs; }); - // Create the collection feature object - const featureCollection = { - type: 'FeatureCollection', - name: uriWFS.name, - features: [], - }; - - elasticResponse.hits.hits.forEach((e) => { - if (e._source['data-fr'] !== undefined) { - featureCollection.features.push(e._source['data-fr']); - // Order the feature properties by provider order - const orderedProperties = this._datasetDetailService.dataset.fields.list; - featureCollection.features.forEach((feature) => { - const newDataPropertiesOrder = {}; - orderedProperties.forEach((field) => { - newDataPropertiesOrder[field] = feature.properties[field] ? feature.properties[field] : ''; - }); - feature.properties = newDataPropertiesOrder; - }); - } - }); - - this.totalData = elasticResponse.hits.total; - - const newFeatures = []; - // If the features are 'MultiPoint' type, explode it into multiple 'Point' - featureCollection.features.forEach((feature, index) => { - feature.properties['_featureId'] = index; - if (feature.geometry.type === 'MultiPoint') { - feature.geometry.coordinates.forEach((point) => { - const newFeature = Object.assign(feature); - newFeature.geometry.coordinates = point; - newFeature.geometry.type = 'Point'; - newFeatures.push(newFeature); - }); - } else { - newFeatures.push(feature); - } - }); - featureCollection.features = newFeatures; - return featureCollection as GeoJSON.FeatureCollection; - })); - } + // getWFSFeatures(metadata: Metadata, count: number, bounds?: mapboxgl.LngLatBounds): + // Observable<GeoJSON.FeatureCollection> { + + // let coordinates = null; + // if (bounds) { + // coordinates = []; + // coordinates.push([bounds.getNorthWest().lng, bounds.getNorthWest().lat]); + // coordinates.push([bounds.getSouthEast().lng, bounds.getSouthEast().lat]); + // } + + // return this._elasticSearchService.getDataByBbox( + // metadata.geonet.uuid, + // count, + // coordinates).pipe( + // map((elasticResponse) => { + // const uriWFS = metadata.link.find((e) => { return e.service === linkFormats.wfs; }); + // // Create the collection feature object + // const featureCollection = { + // type: 'FeatureCollection', + // name: uriWFS.name, + // features: [], + // }; + + // elasticResponse.hits.hits.forEach((e) => { + // if (e._source['data-fr'] !== undefined) { + // featureCollection.features.push(e._source['data-fr']); + // // Order the feature properties by provider order + // const orderedProperties = this._datasetDetailService.dataset.fields.list; + // featureCollection.features.forEach((feature) => { + // const newDataPropertiesOrder = {}; + // orderedProperties.forEach((field) => { + // newDataPropertiesOrder[field] = feature.properties[field] ? feature.properties[field] : ''; + // }); + // feature.properties = newDataPropertiesOrder; + // }); + // } + // }); + + // this.totalData = elasticResponse.hits.total; + + // const newFeatures = []; + // // If the features are 'MultiPoint' type, explode it into multiple 'Point' + // featureCollection.features.forEach((feature, index) => { + // feature.properties['_featureId'] = index; + // if (feature.geometry.type === 'MultiPoint') { + // feature.geometry.coordinates.forEach((point) => { + // const newFeature = Object.assign(feature); + // newFeature.geometry.coordinates = point; + // newFeature.geometry.type = 'Point'; + // newFeatures.push(newFeature); + // }); + // } else { + // newFeatures.push(feature); + // } + // }); + // featureCollection.features = newFeatures; + // return featureCollection as GeoJSON.FeatureCollection; + // })); + // } // Used for WMS layer. // Get one feature from the coordinates - getFeatureInfo(lng, lat) { - // Create specific filter depending on geometry type - let filter = {}; - if (this._datasetDetailService.datasetData[0].geometry.type === 'Point' - || this._datasetDetailService.datasetData[0].geometry.type === 'LineString' - || this._datasetDetailService.datasetData[0].geometry.type === 'MultiLineString' - || this._datasetDetailService.datasetData[0].geometry.type === 'MultiPoint') { - filter = { - shape: { - coordinates: [lng, lat], - radius: '10m', - type: 'circle', - }, - relation: 'intersects', - }; - } else if (this._datasetDetailService.datasetData[0].geometry.type === 'Polygon' - || this._datasetDetailService.datasetData[0].geometry.type === 'MultiPolygon') { - filter = { - shape: { - coordinates: [lng, lat], - type: 'point', - }, - relation: 'contains', - }; - } - - return this._elasticSearchService.getDataFromCoordinates(filter, this.metadata.geonet.uuid); - } + // getFeatureInfo(lng, lat) { + // // Create specific filter depending on geometry type + // let filter = {}; + // if (this._datasetDetailService.datasetData[0].geometry.type === 'Point' + // || this._datasetDetailService.datasetData[0].geometry.type === 'LineString' + // || this._datasetDetailService.datasetData[0].geometry.type === 'MultiLineString' + // || this._datasetDetailService.datasetData[0].geometry.type === 'MultiPoint') { + // filter = { + // shape: { + // coordinates: [lng, lat], + // radius: '10m', + // type: 'circle', + // }, + // relation: 'intersects', + // }; + // } else if (this._datasetDetailService.datasetData[0].geometry.type === 'Polygon' + // || this._datasetDetailService.datasetData[0].geometry.type === 'MultiPolygon') { + // filter = { + // shape: { + // coordinates: [lng, lat], + // type: 'point', + // }, + // relation: 'contains', + // }; + // } + + // return this._elasticSearchService.getDataFromCoordinates(filter, this.metadata.geonet.uuid); + // } switchLayer(baseLayer) { // Set selected base layer diff --git a/src/assets/mapbox-gl-styles/vector.json b/src/assets/mapbox-gl-styles/vector.json index 544d5b71..eceb716c 100644 --- a/src/assets/mapbox-gl-styles/vector.json +++ b/src/assets/mapbox-gl-styles/vector.json @@ -20,6 +20,7 @@ "attribution": "© <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors" } }, + "sprite": "http://localhost:4200/assets/sprite/sprite", "glyphs": "https://openmaptiles.geo.data.gouv.fr/fonts/{fontstack}/{range}.pbf", "layers": [ { diff --git a/src/assets/sprite/sprite.json b/src/assets/sprite/sprite.json new file mode 100644 index 00000000..373bd965 --- /dev/null +++ b/src/assets/sprite/sprite.json @@ -0,0 +1,2468 @@ +{ + "aerialway-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 0, + "y": 165 + }, + "aerialway-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 0 + }, + "airfield-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 11, + "y": 165 + }, + "airfield-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 0 + }, + "airport-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 22, + "y": 165 + }, + "airport-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 15 + }, + "alcohol-shop-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 33, + "y": 165 + }, + "alcohol-shop-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 15 + }, + "american-football-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 44, + "y": 165 + }, + "american-football-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 0 + }, + "amusement-park-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 55, + "y": 165 + }, + "amusement-park-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 0 + }, + "aquarium-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 66, + "y": 165 + }, + "aquarium-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 15 + }, + "art-gallery-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 77, + "y": 165 + }, + "art-gallery-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 15 + }, + "attraction-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 88, + "y": 165 + }, + "attraction-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 30 + }, + "bakery-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 99, + "y": 165 + }, + "bakery-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 30 + }, + "bank-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 110, + "y": 165 + }, + "bank-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 30 + }, + "bar-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 121, + "y": 165 + }, + "bar-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 30 + }, + "barrier-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 132, + "y": 165 + }, + "barrier-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 45 + }, + "baseball-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 143, + "y": 165 + }, + "baseball-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 45 + }, + "basketball-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 154, + "y": 165 + }, + "basketball-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 45 + }, + "bbq-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 165, + "y": 165 + }, + "bbq-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 45 + }, + "beach-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 176, + "y": 165 + }, + "beach-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 0 + }, + "beer-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 187, + "y": 165 + }, + "beer-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 0 + }, + "bicycle-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 198, + "y": 165 + }, + "bicycle-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 0 + }, + "bicycle-share-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 209, + "y": 165 + }, + "bicycle-share-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 0 + }, + "blood-bank-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 220, + "y": 165 + }, + "blood-bank-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 15 + }, + "bowling-alley-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 0, + "y": 176 + }, + "bowling-alley-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 15 + }, + "bridge-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 11, + "y": 176 + }, + "bridge-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 15 + }, + "building-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 22, + "y": 176 + }, + "building-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 15 + }, + "building-alt1-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 33, + "y": 176 + }, + "building-alt1-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 30 + }, + "bus-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 44, + "y": 176 + }, + "bus-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 30 + }, + "cafe-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 55, + "y": 176 + }, + "cafe-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 30 + }, + "campsite-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 66, + "y": 176 + }, + "campsite-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 30 + }, + "car-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 77, + "y": 176 + }, + "car-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 45 + }, + "car-rental-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 88, + "y": 176 + }, + "car-rental-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 45 + }, + "car-repair-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 99, + "y": 176 + }, + "car-repair-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 45 + }, + "casino-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 110, + "y": 176 + }, + "casino-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 45 + }, + "castle-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 121, + "y": 176 + }, + "castle-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 60 + }, + "cemetery-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 132, + "y": 176 + }, + "cemetery-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 60 + }, + "charging-station-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 143, + "y": 176 + }, + "charging-station-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 60 + }, + "cinema-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 154, + "y": 176 + }, + "cinema-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 60 + }, + "circle-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 165, + "y": 176 + }, + "circle-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 60 + }, + "circle-stroked-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 176, + "y": 176 + }, + "circle-stroked-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 60 + }, + "city-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 187, + "y": 176 + }, + "city-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 60 + }, + "clothing-store-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 198, + "y": 176 + }, + "clothing-store-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 60 + }, + "college-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 209, + "y": 176 + }, + "college-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 75 + }, + "commercial-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 220, + "y": 176 + }, + "commercial-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 75 + }, + "communications-tower-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 0, + "y": 187 + }, + "communications-tower-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 75 + }, + "confectionery-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 11, + "y": 187 + }, + "confectionery-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 75 + }, + "convenience-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 22, + "y": 187 + }, + "convenience-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 75 + }, + "cricket-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 33, + "y": 187 + }, + "cricket-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 75 + }, + "cross-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 44, + "y": 187 + }, + "cross-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 75 + }, + "dam-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 55, + "y": 187 + }, + "dam-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 75 + }, + "danger-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 66, + "y": 187 + }, + "danger-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 90 + }, + "defibrillator-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 77, + "y": 187 + }, + "defibrillator-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 90 + }, + "dentist-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 88, + "y": 187 + }, + "dentist-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 90 + }, + "doctor-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 99, + "y": 187 + }, + "doctor-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 90 + }, + "dog-park-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 110, + "y": 187 + }, + "dog-park-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 90 + }, + "drinking-water-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 121, + "y": 187 + }, + "drinking-water-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 90 + }, + "embassy-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 132, + "y": 187 + }, + "embassy-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 90 + }, + "emergency-phone-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 143, + "y": 187 + }, + "emergency-phone-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 90 + }, + "entrance-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 154, + "y": 187 + }, + "entrance-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 105 + }, + "entrance-alt1-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 165, + "y": 187 + }, + "entrance-alt1-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 105 + }, + "farm-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 176, + "y": 187 + }, + "farm-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 105 + }, + "fast-food-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 187, + "y": 187 + }, + "fast-food-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 105 + }, + "fence-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 198, + "y": 187 + }, + "fence-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 105 + }, + "ferry-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 209, + "y": 187 + }, + "ferry-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 105 + }, + "fire-station-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 220, + "y": 187 + }, + "fire-station-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 105 + }, + "fitness-centre-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 0, + "y": 198 + }, + "fitness-centre-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 105 + }, + "florist-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 11, + "y": 198 + }, + "florist-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 0 + }, + "fuel-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 22, + "y": 198 + }, + "fuel-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 0 + }, + "furniture-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 33, + "y": 198 + }, + "furniture-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 0 + }, + "gaming-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 44, + "y": 198 + }, + "gaming-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 0 + }, + "garden-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 55, + "y": 198 + }, + "garden-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 0 + }, + "garden-centre-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 66, + "y": 198 + }, + "garden-centre-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 0 + }, + "gift-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 77, + "y": 198 + }, + "gift-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 0 + }, + "globe-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 88, + "y": 198 + }, + "globe-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 0 + }, + "golf-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 99, + "y": 198 + }, + "golf-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 15 + }, + "grocery-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 110, + "y": 198 + }, + "grocery-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 15 + }, + "hairdresser-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 121, + "y": 198 + }, + "hairdresser-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 15 + }, + "harbor-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 132, + "y": 198 + }, + "harbor-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 15 + }, + "hardware-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 143, + "y": 198 + }, + "hardware-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 15 + }, + "heart-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 154, + "y": 198 + }, + "heart-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 15 + }, + "heliport-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 165, + "y": 198 + }, + "heliport-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 15 + }, + "home-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 176, + "y": 198 + }, + "home-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 15 + }, + "horse-riding-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 187, + "y": 198 + }, + "horse-riding-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 30 + }, + "hospital-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 198, + "y": 198 + }, + "hospital-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 30 + }, + "ice-cream-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 209, + "y": 198 + }, + "ice-cream-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 30 + }, + "industry-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 220, + "y": 198 + }, + "industry-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 30 + }, + "information-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 0, + "y": 209 + }, + "information-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 30 + }, + "jewelry-store-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 11, + "y": 209 + }, + "jewelry-store-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 30 + }, + "karaoke-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 22, + "y": 209 + }, + "karaoke-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 30 + }, + "landmark-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 33, + "y": 209 + }, + "landmark-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 30 + }, + "landuse-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 44, + "y": 209 + }, + "landuse-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 45 + }, + "laundry-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 55, + "y": 209 + }, + "laundry-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 45 + }, + "library-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 66, + "y": 209 + }, + "library-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 45 + }, + "lighthouse-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 77, + "y": 209 + }, + "lighthouse-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 45 + }, + "lodging-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 88, + "y": 209 + }, + "lodging-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 45 + }, + "logging-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 99, + "y": 209 + }, + "logging-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 45 + }, + "marker-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 110, + "y": 209 + }, + "marker-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 45 + }, + "marker-stroked-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 121, + "y": 209 + }, + "marker-stroked-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 45 + }, + "mobile-phone-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 132, + "y": 209 + }, + "mobile-phone-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 60 + }, + "monument-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 143, + "y": 209 + }, + "monument-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 60 + }, + "mountain-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 154, + "y": 209 + }, + "mountain-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 60 + }, + "museum-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 165, + "y": 209 + }, + "museum-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 60 + }, + "music-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 176, + "y": 209 + }, + "music-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 60 + }, + "natural-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 187, + "y": 209 + }, + "natural-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 60 + }, + "optician-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 198, + "y": 209 + }, + "optician-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 60 + }, + "paint-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 209, + "y": 209 + }, + "paint-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 60 + }, + "park-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 220, + "y": 209 + }, + "park-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 75 + }, + "park-alt1-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 0, + "y": 220 + }, + "park-alt1-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 75 + }, + "parking-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 11, + "y": 220 + }, + "parking-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 75 + }, + "parking-garage-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 22, + "y": 220 + }, + "parking-garage-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 75 + }, + "pharmacy-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 33, + "y": 220 + }, + "pharmacy-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 75 + }, + "picnic-site-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 44, + "y": 220 + }, + "picnic-site-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 75 + }, + "pitch-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 55, + "y": 220 + }, + "pitch-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 75 + }, + "place-of-worship-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 66, + "y": 220 + }, + "place-of-worship-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 75 + }, + "playground-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 77, + "y": 220 + }, + "playground-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 90 + }, + "police-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 88, + "y": 220 + }, + "police-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 90 + }, + "post-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 99, + "y": 220 + }, + "post-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 90 + }, + "prison-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 110, + "y": 220 + }, + "prison-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 90 + }, + "rail-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 121, + "y": 220 + }, + "rail-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 90 + }, + "rail-light-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 132, + "y": 220 + }, + "rail-light-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 90 + }, + "rail-metro-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 143, + "y": 220 + }, + "rail-metro-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 90 + }, + "ranger-station-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 154, + "y": 220 + }, + "ranger-station-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 90 + }, + "recycling-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 165, + "y": 220 + }, + "recycling-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 105 + }, + "religious-buddhist-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 176, + "y": 220 + }, + "religious-buddhist-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 105 + }, + "religious-christian-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 187, + "y": 220 + }, + "religious-christian-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 105 + }, + "religious-jewish-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 198, + "y": 220 + }, + "religious-jewish-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 105 + }, + "religious-muslim-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 209, + "y": 220 + }, + "religious-muslim-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 105 + }, + "residential-community-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 220, + "y": 220 + }, + "residential-community-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 105 + }, + "restaurant-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 231, + "y": 165 + }, + "restaurant-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 105 + }, + "restaurant-noodle-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 242, + "y": 165 + }, + "restaurant-noodle-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 105 + }, + "restaurant-pizza-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 253, + "y": 165 + }, + "restaurant-pizza-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 120 + }, + "restaurant-seafood-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 264, + "y": 165 + }, + "restaurant-seafood-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 120 + }, + "roadblock-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 275, + "y": 165 + }, + "roadblock-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 120 + }, + "rocket-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 286, + "y": 165 + }, + "rocket-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 120 + }, + "school-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 297, + "y": 165 + }, + "school-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 120 + }, + "scooter-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 308, + "y": 165 + }, + "scooter-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 120 + }, + "shelter-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 319, + "y": 165 + }, + "shelter-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 120 + }, + "shoe-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 330, + "y": 165 + }, + "shoe-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 120 + }, + "shop-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 341, + "y": 165 + }, + "shop-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 120 + }, + "skateboard-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 352, + "y": 165 + }, + "skateboard-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 120 + }, + "skiing-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 363, + "y": 165 + }, + "skiing-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 120 + }, + "slaughterhouse-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 374, + "y": 165 + }, + "slaughterhouse-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 120 + }, + "slipway-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 385, + "y": 165 + }, + "slipway-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 120 + }, + "snowmobile-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 396, + "y": 165 + }, + "snowmobile-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 120 + }, + "soccer-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 407, + "y": 165 + }, + "soccer-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 120 + }, + "square-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 418, + "y": 165 + }, + "square-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 120, + "sdf": true + }, + "square-stroked-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 429, + "y": 165 + }, + "square-stroked-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 135 + }, + "stadium-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 440, + "y": 165 + }, + "stadium-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 135 + }, + "star-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 451, + "y": 165 + }, + "star-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 135 + }, + "star-stroked-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 462, + "y": 165 + }, + "star-stroked-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 135 + }, + "suitcase-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 231, + "y": 176 + }, + "suitcase-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 135 + }, + "sushi-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 242, + "y": 176 + }, + "sushi-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 135 + }, + "swimming-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 253, + "y": 176 + }, + "swimming-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 135 + }, + "table-tennis-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 264, + "y": 176 + }, + "table-tennis-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 135 + }, + "teahouse-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 275, + "y": 176 + }, + "teahouse-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 135 + }, + "telephone-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 286, + "y": 176 + }, + "telephone-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 135 + }, + "tennis-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 297, + "y": 176 + }, + "tennis-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 135 + }, + "theatre-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 308, + "y": 176 + }, + "theatre-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 135 + }, + "toilet-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 319, + "y": 176 + }, + "toilet-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 135 + }, + "town-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 330, + "y": 176 + }, + "town-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 135 + }, + "town-hall-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 341, + "y": 176 + }, + "town-hall-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 135 + }, + "triangle-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 352, + "y": 176 + }, + "triangle-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 135, + "sdf": true + }, + "triangle-stroked-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 363, + "y": 176 + }, + "triangle-stroked-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 0, + "y": 150 + }, + "veterinary-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 374, + "y": 176 + }, + "veterinary-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 15, + "y": 150 + }, + "viewpoint-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 385, + "y": 176 + }, + "viewpoint-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 30, + "y": 150 + }, + "village-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 396, + "y": 176 + }, + "village-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 45, + "y": 150 + }, + "volcano-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 407, + "y": 176 + }, + "volcano-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 60, + "y": 150 + }, + "volleyball-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 418, + "y": 176 + }, + "volleyball-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 75, + "y": 150 + }, + "warehouse-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 429, + "y": 176 + }, + "warehouse-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 90, + "y": 150 + }, + "waste-basket-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 440, + "y": 176 + }, + "waste-basket-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 105, + "y": 150 + }, + "watch-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 451, + "y": 176 + }, + "watch-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 120, + "y": 150 + }, + "water-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 462, + "y": 176 + }, + "water-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 135, + "y": 150 + }, + "waterfall-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 231, + "y": 187 + }, + "waterfall-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 150, + "y": 150 + }, + "watermill-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 242, + "y": 187 + }, + "watermill-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 165, + "y": 150 + }, + "wetland-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 253, + "y": 187 + }, + "wetland-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 180, + "y": 150 + }, + "wheelchair-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 264, + "y": 187 + }, + "wheelchair-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 195, + "y": 150 + }, + "windmill-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 275, + "y": 187 + }, + "windmill-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 210, + "y": 150 + }, + "zoo-11": { + "height": 11, + "pixelRatio": 1, + "width": 11, + "x": 286, + "y": 187 + }, + "zoo-15": { + "height": 15, + "pixelRatio": 1, + "width": 15, + "x": 225, + "y": 150 + } +} \ No newline at end of file diff --git a/src/assets/sprite/sprite.png b/src/assets/sprite/sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..9206cf8c0def96d3ea13d31d8784b614e940e937 GIT binary patch literal 41303 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 literal 0 HcmV?d00001 -- GitLab