diff --git a/package-lock.json b/package-lock.json index 62ea69832b1da17751932afbb810fba6f52b4a18..d916e48e1c113c59a0e14200a9c687231ad1d061 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 2bf0bb7b558083212a34b85c1f51e159ceb08c78..3b869f20cb817e1585dcdf12d6cde2302678270d 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 83ae58e153ea05980aab8991b906ce6909cbff12..05ef4075133683dcf7ed594a18d4b3869c475bb9 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 b6e169e628b942e0c8810e48cd98651bdef9079b..51d58ffebeb98ef461235b262f08b0a6621acad3 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 f0d0dc1cc655e76e6372eb70ddcdcdb08aa2a034..35b24a3ada97a7068f14d9f5aa04b54159007ff7 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 0000000000000000000000000000000000000000..a2e3174cff40b26863a8452dd76283a5a310b953 --- /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 8eb83b02827ec548fc95d34441a69a61abba3877..08065c0319c8b9d0e2eb05fea6b33340cf80ff91 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 b52ce50430b827a46274b93e85d08b91968c3093..6c385ccf84b506fa4268e67188caab4dc91b8e11 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 1b41fbfaaa7d72ee995abd0cf722cae4eda610bf..cacf612587c7f7d09b442eedbc75a16f97540d8f 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 cad3e12581adfef0b6aa733f1329dad1aae7b52e..7d7a8f06feec641b2083818ed7c3f3ef4d04d252 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 544d5b717720dbd7fea2745b667114b46105386c..eceb716cb3659a6a0234962338f4bc3cdbc80c78 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 0000000000000000000000000000000000000000..373bd9659af1f8d3da13ef4e980ffb803bbd320e --- /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 Binary files /dev/null and b/src/assets/sprite/sprite.png differ