├── .gitignore ├── src ├── images │ ├── dark.png │ ├── light.png │ ├── lineDark.png │ ├── miamiDay.png │ ├── quadkeys.png │ ├── terrain.png │ ├── countries.png │ ├── lineWhite.png │ ├── satellite.png │ ├── springSoft.png │ ├── geojson-tools.png │ ├── springBright.png │ ├── countriesBright.png │ ├── geojson-tools-loaddata.png │ ├── remove.svg │ ├── dark │ │ ├── add.svg │ │ ├── moon.svg │ │ ├── code.svg │ │ ├── copy.svg │ │ ├── tool.svg │ │ ├── trash-2.svg │ │ ├── gift.svg │ │ └── sun.svg │ ├── light │ │ ├── add.svg │ │ ├── moon.svg │ │ ├── code.svg │ │ ├── copy.svg │ │ ├── tool.svg │ │ ├── trash-2.svg │ │ ├── gift.svg │ │ └── sun.svg │ ├── drag-dots.svg │ ├── pin.svg │ ├── logo.svg │ ├── file-upload.svg │ ├── file-uploadWhite.svg │ ├── full-screen.svg │ ├── xyz-logo-v1.svg │ ├── upload.svg │ ├── dark-mode.svg │ ├── xyz-logo.svg │ ├── cp.svg │ ├── cpWhite.svg │ ├── document-editWhite.svg │ ├── document-edit.svg │ ├── add-file.svg │ ├── cleaning.svg │ ├── cleaningWhite.svg │ ├── light-mode.svg │ ├── worldwide.svg │ └── worldwideWhite.svg ├── components │ ├── editor.js │ ├── alertBar.js │ ├── themes │ │ ├── index.js │ │ └── WithLabel │ │ │ └── here │ │ │ ├── countriesBright.js │ │ │ ├── countries.js │ │ │ └── lines_white.js │ ├── hereMap │ │ ├── hereMap.js │ │ └── getCustomStyle.js │ ├── common.js │ ├── eventHandling.js │ └── loadData.js ├── lib │ ├── json-lint.js │ ├── resizer.js │ └── jsonlint.js ├── index.html ├── style │ └── style.css └── index.js ├── .ort.yml ├── config └── postcss.config.js ├── .github └── workflows │ └── webpack.yml ├── LICENSE ├── CONTRIBUTING.md ├── package.json ├── webpack.config.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | .env 4 | .idea/ 5 | -------------------------------------------------------------------------------- /src/images/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/dark.png -------------------------------------------------------------------------------- /src/images/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/light.png -------------------------------------------------------------------------------- /src/images/lineDark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/lineDark.png -------------------------------------------------------------------------------- /src/images/miamiDay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/miamiDay.png -------------------------------------------------------------------------------- /src/images/quadkeys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/quadkeys.png -------------------------------------------------------------------------------- /src/images/terrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/terrain.png -------------------------------------------------------------------------------- /src/images/countries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/countries.png -------------------------------------------------------------------------------- /src/images/lineWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/lineWhite.png -------------------------------------------------------------------------------- /src/images/satellite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/satellite.png -------------------------------------------------------------------------------- /src/images/springSoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/springSoft.png -------------------------------------------------------------------------------- /src/images/geojson-tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/geojson-tools.png -------------------------------------------------------------------------------- /src/images/springBright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/springBright.png -------------------------------------------------------------------------------- /src/images/countriesBright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/countriesBright.png -------------------------------------------------------------------------------- /src/images/geojson-tools-loaddata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzmaps/geojson-tool/HEAD/src/images/geojson-tools-loaddata.png -------------------------------------------------------------------------------- /src/images/remove.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/dark/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ort.yml: -------------------------------------------------------------------------------- 1 | excludes: 2 | scopes: 3 | - name: 'devDependencies' 4 | reason: 'BUILD_TOOL_OF' 5 | comment: 'These are dependencies only used for development. They are not distributed in the context of this project.' -------------------------------------------------------------------------------- /src/images/dark/moon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/moon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/dark/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/dark/copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/drag-dots.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/postcss.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | module.exports = ({file, options, env}) => ({ 8 | plugins: [ 9 | require('autoprefixer')(), 10 | require('cssnano')({preset: 'default', discardUnused: false}) 11 | ] 12 | }) 13 | -------------------------------------------------------------------------------- /src/images/dark/tool.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/tool.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/pin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/dark/trash-2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/trash-2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | logo 3 | Created with Sketch. 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/images/dark/gift.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/gift.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/dark/sun.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/light/sun.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/editor.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | import * as monaco from 'monaco-editor'; 8 | 9 | export let startValue = [ 10 | '{', 11 | '"type": "FeatureCollection",', 12 | '"features": []', 13 | '}' 14 | ].join('\n'); 15 | 16 | export let editor = monaco.editor.create(document.getElementById('editor'), { 17 | value: startValue, 18 | language: 'json', 19 | dragAndDrop: false, 20 | validate: true, 21 | "bracketPairColorization.enabled": true, 22 | formatOnPaste: true, 23 | maxTokenizationLineLength: 100000, 24 | //default is 20000 25 | }); 26 | -------------------------------------------------------------------------------- /src/images/file-upload.svg: -------------------------------------------------------------------------------- 1 | file-upload -------------------------------------------------------------------------------- /src/images/file-uploadWhite.svg: -------------------------------------------------------------------------------- 1 | file-upload 2 | -------------------------------------------------------------------------------- /src/lib/json-lint.js: -------------------------------------------------------------------------------- 1 | let CodeMirror = require('codemirror'); 2 | // the 'fork-and-fixed' jsonlint file 3 | window['jsonlint'] = require('./jsonlint'); 4 | 5 | CodeMirror.registerHelper("lint", "json", function(text) { 6 | let found = []; 7 | if (!window.jsonlint) { 8 | if (window.console) { 9 | window.console.error("Error: window.jsonlint not defined, CodeMirror JSON linting cannot run."); 10 | } 11 | return found; 12 | } 13 | let jsonlint = window.jsonlint.parser; 14 | jsonlint.parseError = function(str, hash) { 15 | let loc = hash.loc; 16 | found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column), 17 | to: CodeMirror.Pos(loc.last_line - 1, loc.last_column), 18 | message: str}); 19 | }; 20 | try { jsonlint.parse(text); } 21 | catch(e) {} 22 | return found; 23 | }); 24 | -------------------------------------------------------------------------------- /.github/workflows/webpack.yml: -------------------------------------------------------------------------------- 1 | name: NodeJS with Webpack 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | environment: 12 | name: github-pages 13 | url: ${{ steps.deployment.outputs.page_url }} 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | id-token: write 18 | pages: write 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | 23 | - name: Use Node.js 18.x 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: 18.x 27 | 28 | - name: Build 29 | run: | 30 | npm install 31 | npx webpack 32 | 33 | - name: Setup Pages 34 | uses: actions/configure-pages@v3 35 | 36 | - name: Upload artifact 37 | uses: actions/upload-pages-artifact@v1 38 | with: 39 | path: 'dist/' 40 | 41 | - name: Deploy to GitHub Pages 42 | id: deployment 43 | uses: actions/deploy-pages@v1 44 | -------------------------------------------------------------------------------- /src/images/full-screen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/xyz-logo-v1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Group 3 4 | Created with Sketch. 5 | 6 | 7 | 8 | XYZ 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (C) 2023- XYZ maps contributors 4 | Copyright (C) 2019 HERE Europe B.V. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | 'Software'), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The team behind the [GeoJSON-tool](https://github.com/xyzmaps/geojson-tool) gratefully accepts contributions via 4 | [pull requests](https://help.github.com/articles/about-pull-requests/) filed against the 5 | [GitHub project](https://github.com/xyzmaps/geojson-tool/pulls). 6 | 7 | # Signing each Commit 8 | 9 | As part of filing a pull request we ask you to sign off the 10 | [Developer Certificate of Origin](https://developercertificate.org/) (DCO) in each commit. 11 | Any Pull Request with commits that are not signed off will be reject by the 12 | [DCO check](https://probot.github.io/apps/dco/). 13 | 14 | A DCO is lightweight way for a contributor to confirm that they wrote or otherwise have the right 15 | to submit code or documentation to a project. Simply add `Signed-off-by` as shown in the example below 16 | to indicate that you agree with the DCO. 17 | 18 | An example signed commit message: 19 | 20 | ``` 21 | README.md: Fix minor spelling mistake 22 | 23 | Signed-off-by: John Doe 24 | ``` 25 | 26 | Git has the `-s` flag that can sign a commit for you, see example below: 27 | 28 | `$ git commit -s -m 'README.md: Fix minor spelling mistake'` -------------------------------------------------------------------------------- /src/components/alertBar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | let alertBar = function (visibility, type, mesg) { 8 | document.getElementById('barMessage').innerHTML = mesg; 9 | let alertBarWrapper = document.getElementById('alertBar'); 10 | 11 | if(visibility === 1) { 12 | alertBarWrapper.style.display = 'block'; 13 | } else { 14 | alertBarWrapper.style.display = 'none'; 15 | } 16 | 17 | if(type === 'warning'){ 18 | alertBarWrapper.style.backgroundColor = '#FAB800'; 19 | alertBarWrapper.style.color = '#000'; 20 | } else if(type === 'error') { 21 | alertBarWrapper.style.backgroundColor = '#C41C33'; 22 | alertBarWrapper.style.color = '#fff'; 23 | } else if(type === 'success') { 24 | alertBarWrapper.style.backgroundColor = '#06B87C'; 25 | alertBarWrapper.style.color = '#fff'; 26 | } else if(type === 'info') { 27 | alertBarWrapper.style.backgroundColor = '#48DAD0'; 28 | alertBarWrapper.style.color = '#000'; 29 | } 30 | 31 | document.getElementById('remove-bar').addEventListener("click", function (ev) { 32 | ev.stopPropagation(); 33 | alertBarWrapper.style.display = 'none'; 34 | }, false); 35 | } 36 | 37 | export { alertBar } 38 | -------------------------------------------------------------------------------- /src/images/upload.svg: -------------------------------------------------------------------------------- 1 | 69 - Upload (Solid)Created with Sketch. -------------------------------------------------------------------------------- /src/images/dark-mode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/xyz-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/lib/resizer.js: -------------------------------------------------------------------------------- 1 | function resizer(resizerID, mousemove, cursor) { 2 | let resizer = document.getElementById(resizerID); 3 | resizer.style.cursor = cursor; 4 | resizer.mousemove = mousemove; 5 | 6 | resizer.onmousedown = function (e) { 7 | try{ 8 | 9 | document.documentElement.addEventListener('mousemove', resizer.doDrag, false); 10 | document.documentElement.addEventListener('mouseup', resizer.stopDrag, false); 11 | } catch (e) { 12 | ErrorMessage("resizer.onmousedown(...) failed! Your browser does not support this feature. " + e.message); 13 | } 14 | } 15 | 16 | resizer.doDrag = function (e) { 17 | if (e.which !== 1){ 18 | resizer.stopDrag(e); 19 | return; 20 | } 21 | resizer.mousemove(e); 22 | } 23 | 24 | resizer.stopDrag = function (e) { 25 | document.documentElement.removeEventListener('mousemove', resizer.doDrag, false); 26 | document.documentElement.removeEventListener('mouseup', resizer.stopDrag, false); 27 | } 28 | } 29 | 30 | function resizerX(resizerID, mousemove) { 31 | resizer(resizerID, mousemove, "e-resize"); 32 | } 33 | 34 | function resizerY(resizerID, mousemove) { 35 | resizer(resizerID, mousemove, "n-resize"); 36 | } 37 | 38 | function resizerXY(resizerID, mousemove) { 39 | resizer(resizerID, mousemove, "ne-resize"); 40 | } 41 | 42 | export { resizer, resizerX, resizerY, resizerXY } 43 | -------------------------------------------------------------------------------- /src/images/cp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/cpWhite.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/images/document-editWhite.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/images/document-edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xyzmaps-geojson-tool", 3 | "version": "1.2.0", 4 | "private": true, 5 | "author": { 6 | "name": "XYZ Maps and contributors", 7 | "url": "https://github.com/xyzmaps" 8 | }, 9 | "license": "MIT", 10 | "description": "A web based visualization tool for GeoJSON data.", 11 | "main": "index.js", 12 | "scripts": { 13 | "build": "webpack", 14 | "start": "webpack serve" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/xyzmaps/geojson-tool" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/xyzmaps/geojson-tool/issues" 22 | }, 23 | "keywords": [ 24 | "GeoJSON", 25 | "XYZ Maps Visualization", 26 | "Map Visualization" 27 | ], 28 | "devDependencies": { 29 | "@babel/core": "^7.16.0", 30 | "autoprefixer": "^10.4.2", 31 | "babel-loader": "^8.2.3", 32 | "css-loader": "^6.5.1", 33 | "file-loader": "^6.2.0", 34 | "html-loader": "^3.1.0", 35 | "html-webpack-plugin": "^5.5.0", 36 | "json-formatter-js": "^2.3.4", 37 | "style-loader": "^3.3.1", 38 | "svg-inline-loader": "^0.8.2", 39 | "webpack": "^5.66.0", 40 | "webpack-cli": "^4.9.1", 41 | "webpack-dev-server": "^4.6.0" 42 | }, 43 | "dependencies": { 44 | "@here/xyz-maps-common": "0.26.0", 45 | "@here/xyz-maps-core": "0.26.0", 46 | "@here/xyz-maps-display": "0.26.0", 47 | "copy-webpack-plugin": "^6.4.1", 48 | "geojson-validation": "^1.0.2", 49 | "glob": "^7.2.0", 50 | "lodash.isequal": "^4.5.0", 51 | "monaco-editor": "^0.31.0", 52 | "monaco-editor-webpack-plugin": "^7.0.0" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/components/themes/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2017-2019 HERE Europe B.V. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | * License-Filename: LICENSE 19 | * 20 | * 21 | */ 22 | 23 | import hereWithLabelDark from './WithLabel/here/dark'; 24 | import hereWithLabelLight from './WithLabel/here/light'; 25 | import hereWithLabelMiamiDay from './WithLabel/here/miamiDay'; 26 | import hereWithLabelSpringSoft from './WithLabel/here/spring-soft'; 27 | import hereWithLabelCountries from './WithLabel/here/countries'; 28 | import hereWithLabelCountriesBright from './WithLabel/here/countriesBright'; 29 | import hereWithLabelSpringBright from './WithLabel/here/springBright'; 30 | import hereWithLabelLineDark from './WithLabel/here/lines_dark'; 31 | import hereWithLabelLineWhite from './WithLabel/here/lines_white'; 32 | 33 | export const themes = { 34 | withLabel: { 35 | here: { 36 | dark: hereWithLabelDark, 37 | light: hereWithLabelLight, 38 | miamiDay: hereWithLabelMiamiDay, 39 | springSoft: hereWithLabelSpringSoft, 40 | countries: hereWithLabelCountries, 41 | countriesBright: hereWithLabelCountriesBright, 42 | springBright: hereWithLabelSpringBright, 43 | LineDark: hereWithLabelLineDark, 44 | LineWhite: hereWithLabelLineWhite, 45 | } 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/images/add-file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/cleaning.svg: -------------------------------------------------------------------------------- 1 | cleaning -------------------------------------------------------------------------------- /src/images/cleaningWhite.svg: -------------------------------------------------------------------------------- 1 | cleaning 2 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | const webpack = require("webpack"), 8 | path = require("path"), 9 | HtmlWebpackPlugin = require("html-webpack-plugin"), 10 | MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'), 11 | CopyWebpackPlugin = require('copy-webpack-plugin'); 12 | 13 | 14 | module.exports = { 15 | stats: 'errors-only', 16 | mode: 'development', 17 | entry: [ 18 | "./src/index.js" 19 | ], 20 | output: { 21 | filename: "bundle.js", 22 | path: path.join(__dirname, 'dist') 23 | }, 24 | devServer: { 25 | // inline: true, 26 | static: { 27 | directory: path.resolve(__dirname, 'dist') 28 | }, 29 | port:3000 30 | }, 31 | module: { 32 | rules: [ 33 | { 34 | test: /\.js$/, 35 | exclude: /(node_modules)/, 36 | loader: "babel-loader" 37 | }, 38 | { 39 | test: /\.css$/, 40 | use: [ 41 | { loader: "style-loader"}, 42 | { loader: "css-loader"} 43 | ] 44 | }, 45 | { 46 | test: /\.html$/, 47 | loader: require.resolve('html-loader'), 48 | } 49 | // { 50 | // test: /\.svg(\?.*)?$/, 51 | // issuer: /\.js$/, 52 | // loader: 'svg-inline-loader' 53 | // }, 54 | // { 55 | // test: /\.(jpe?g|png|gif)$/i, 56 | // loader: 'file-loader', 57 | // // options: { 58 | // // name: 'images/[name].[ext]', 59 | // // publicPath: '/' 60 | // // } 61 | // } 62 | ] 63 | }, 64 | plugins: [ 65 | new HtmlWebpackPlugin({ 66 | inject: 'body', 67 | template: './src/index.html', 68 | favicon: './src/images/logo.svg' 69 | }), 70 | new MonacoWebpackPlugin(), 71 | new CopyWebpackPlugin({ 72 | patterns: [ 73 | { from: "./src/images", to: "./images" }, 74 | ], 75 | }) 76 | ], 77 | /* node: { 78 | dgram: 'empty', 79 | fs: 'empty', 80 | net: 'empty', 81 | tls: 'empty', 82 | child_process: 'empty' 83 | },*/ 84 | resolve: { 85 | fallback: { 86 | dgram: false, 87 | fs: false, 88 | net: false, 89 | tls: false, 90 | child_process: false 91 | }, 92 | modules: ['node_modules'], 93 | extensions: ['.js', '.scss', '.html', '.css'] 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XYZ GeoJSON Tool 2 | 3 | A web based visualization tool for GeoJSON data. 4 | 5 | [XYZ GeoJSON on github pages](https://xyzmaps.github.io/geojson-tool/) 6 | 7 | ## Overview 8 | 9 | The GeoJSON Tool is a web based visualization tool for GeoJSON data that can quickly display data from a various sources, highlight and inspect specific features and supports even complex operations like finding data based on content. 10 | 11 |  12 | 13 | 14 |  15 | 16 | ## Getting Started 17 | 18 | ### Getting Started Guide 19 | 20 | Also below is the list of feature available with this tool: 21 | 22 | - Drag and drop multiple GeoJSON file on map to render and load editor with data. 23 | - Directly jump to particular location on first load: https://geojson.tools/?map=-74.0146844,40.7053532,15 24 | - Upload multiple GeoJSON file to render and load editor with data. 25 | - Use multiple GeoJSON file URL to render and load editor with data. 26 | - Use GeoJSON editor to render feature on map. 27 | - Share tool's URL with GeoJSON url in params. 28 | - On selecting lat-long in editor map with that point get centered. 29 | - On selecting feature object in editor, map with that feature will be highlighted. 30 | - On click of any feature its property will be visible and corresponding lat-long will be focused in editor. 31 | - Highlight features with matching properties by clicking on property label in feature explorer pop-up card. 32 | - Map only view option from UI as well as URL parameters. 33 | - Displaying feature colors if available in property object of feature. 34 | - Visualize your XYZ space data directly from URL using for example `url=http://localhost:8080/hub/spaces/QL5wrOzP/search?limit=5000` 35 | - If GeoJSON properties object contains `heading_drg` or `vehicBearing` then it renders point as arrow image with provided bearing. 36 | - If GeoJSON properties object contains `marker-url` then it renders image from given url instead of point on map. 37 | - If GeoJSON properties object contains `marker-text` then it display given text instead of point on map. 38 | 39 | ## Development 40 | 41 | Install node and project dependencies: 42 | 43 | ``` 44 | npm install 45 | ``` 46 | 47 | Run a local server with: 48 | 49 | ``` 50 | npm start 51 | ``` 52 | 53 | An App will be served at http://localhost:3000 54 | 55 | 56 | ## License 57 | 58 | Copyright (C) 2023- XYZ Maps and contributors 59 | 60 | Copyright (C) 2019 HERE Europe B.V. 61 | 62 | See the [LICENSE](./LICENSE) file in the root of this project for license details. 63 | -------------------------------------------------------------------------------- /src/components/hereMap/hereMap.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | import '@here/xyz-maps-common'; 8 | import '@here/xyz-maps-core'; 9 | import {Map} from '@here/xyz-maps-display'; 10 | import '@here/xyz-maps-display'; 11 | import {MVTLayer, TileLayer, LocalProvider} from "@here/xyz-maps-core"; 12 | import { getCustomStyle } from './getCustomStyle'; 13 | import springSoft from "../themes/WithLabel/here/spring-soft"; 14 | import miamiDay from "../themes/WithLabel/here/miamiDay"; 15 | import springBright from "../themes/WithLabel/here/springBright"; 16 | import lineDark from "../themes/WithLabel/here/lines_dark"; 17 | import lineWhite from "../themes/WithLabel/here/lines_white"; 18 | let lat, long, zoom; 19 | 20 | let urlParam = window.location.href.split('map=')[1]; 21 | if(urlParam) { 22 | lat = parseFloat(urlParam.split(",")[1]); 23 | long = parseFloat(urlParam.split(",")[0]); 24 | zoom = parseFloat(urlParam.split(",")[2]); 25 | } 26 | function getMVTLayerWithStyle(style) { 27 | return new MVTLayer({ 28 | name : 'mvt-world-layer', 29 | remote : { 30 | url : 'https://tile.nextzen.org/tilezen/vector/v1/256/all/{z}/{x}/{y}.mvt?api_key=DpCrhQqsR2igQPEINRTfcw' 31 | }, 32 | min : 1, 33 | max : 20, 34 | style: style 35 | }); 36 | } 37 | 38 | //Styled MVT layers 39 | let miamiDayLayer = getMVTLayerWithStyle(miamiDay), 40 | springSoftLayer = getMVTLayerWithStyle(springSoft), 41 | springBrightLayer = getMVTLayerWithStyle(springBright), 42 | lineDarkLayer = getMVTLayerWithStyle(lineDark), 43 | lineWhiteLayer = getMVTLayerWithStyle(lineWhite); 44 | 45 | let featureProvider = new LocalProvider({ 46 | name: 'featureProvider' 47 | }); 48 | 49 | let featureLayer = new TileLayer({ 50 | name: 'featureLayer', 51 | min: 0, 52 | max: 20, 53 | provider: featureProvider, 54 | style: getCustomStyle("blue") 55 | }); 56 | 57 | let config = { 58 | zoomLevel: urlParam ? zoom : 2, 59 | center: { 60 | "longitude": urlParam ? long : 25.91699, 61 | "latitude": urlParam ? lat : 11.38269 62 | }, 63 | ui: { 64 | ZoomControl: false, 65 | Copyright: { 66 | defaultOwner: "OpenStreetMap contributors" 67 | } 68 | }, 69 | layers: [springSoftLayer, featureLayer], 70 | behavior: { 71 | pitch: true, 72 | rotate: true 73 | } 74 | }; 75 | 76 | window.display = new Map(document.getElementById("map"), config); 77 | 78 | export { 79 | featureProvider, 80 | springSoftLayer, 81 | springBrightLayer, 82 | miamiDayLayer, 83 | lineDarkLayer, 84 | lineWhiteLayer 85 | } 86 | -------------------------------------------------------------------------------- /src/images/light-mode.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/images/worldwide.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/images/worldwideWhite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/components/common.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | import { featureProvider } from './hereMap/hereMap' 8 | import {editor} from "./editor"; 9 | 10 | export function validateGeojson(isValid, error) { 11 | if(!isValid){ 12 | window.setTimeout(function(){ 13 | for(let i = 0; i < error.length; i++ ) { 14 | editor.setGutterMarker(i, 'CodeMirror-lint-markers', createMarker(error[`${i}`])); 15 | console.log('Invalid GeoJSON: ' ,error[`${i}`]); 16 | } 17 | }, 500); 18 | } 19 | } 20 | 21 | export function createMarker(errorMessage) { 22 | let div = document.createElement('div'), 23 | message = document.createAttribute("message"); 24 | message.value = errorMessage; 25 | div.setAttributeNode(message); 26 | div.className = "CodeMirror-lint-marker-error error-tooltip"; 27 | return div; 28 | } 29 | 30 | export function IsJsonString(str) { 31 | try { 32 | JSON.parse(str); 33 | } catch (e) { 34 | return false; 35 | } 36 | return true; 37 | } 38 | 39 | export function isPosition(selectedTxt) { 40 | 41 | let long = parseFloat(selectedTxt.split(',')[0]), 42 | lat = parseFloat(selectedTxt.split(',')[1]); 43 | if (typeof lat === 'number' && lat <= 90 && lat >= -90 && 44 | typeof long === 'number' && long <= 180 && long >= -180){ 45 | return [long, lat]; 46 | } 47 | return false; 48 | } 49 | 50 | export function clearURLParam() { 51 | let url = window.location.href.split('url='); 52 | if(url[1]) { 53 | window.history.pushState({}, "", url[0]); 54 | } 55 | } 56 | 57 | /* slider JS */ 58 | 59 | export function resizeX(x) { 60 | let leftPanel = document.getElementById("panelWrapper"), 61 | mapContainer = document.getElementById("mapWrapper"), 62 | leftPanelWidth = leftPanel.parentElement.clientWidth + document.getElementById('mainContainer').offsetLeft - x, 63 | mapContainerWidth = window.innerWidth - leftPanelWidth - 5; 64 | document.getElementById('mainContainer').style.gridTemplateColumns = mapContainerWidth + 'px 7px ' + leftPanelWidth + 'px'; 65 | } 66 | 67 | export function getLatLong(latInfo, longInfo) { 68 | let pointFeature = { 69 | "type": "Feature", 70 | "properties": {}, 71 | "geometry": { 72 | "type": "Point", 73 | "coordinates": [ 74 | latInfo, 75 | longInfo 76 | ] 77 | } 78 | }; 79 | display.setCenter(latInfo, longInfo); 80 | display.setZoomlevel(20); 81 | featureProvider.addFeature( pointFeature ); 82 | window.setTimeout(function(){ 83 | featureProvider.removeFeature( pointFeature ); 84 | }, 1000); 85 | } 86 | 87 | export function onlyMapView() { 88 | document.querySelector('.desktopNavigationBar').style.display = 'none'; 89 | document.querySelector('.map-panel-wrapper').style.display = 'none'; 90 | document.querySelector('.sliderPan').style.display = 'none'; 91 | document.querySelector('.panel-wrapper').style.display = 'none'; 92 | document.querySelector('.map-container').style.height = '100%'; 93 | document.querySelector('.main-container').style.height = '100%'; 94 | document.querySelector('.main-container').style.gridTemplateColumns = '100%'; 95 | display.resize(); 96 | } 97 | 98 | function originalToolView() { 99 | document.querySelector('.desktopNavigationBar').style.display = 'flex'; 100 | document.querySelector('.map-panel-wrapper').style.display = 'block'; 101 | document.querySelector('.sliderPan').style.display = 'block'; 102 | document.querySelector('.panel-wrapper').style.display = 'block'; 103 | document.querySelector('.map-container').style.height = 'calc(100% - 50px)'; 104 | document.querySelector('.main-container').style.height = 'calc(100% - 50px)'; 105 | document.querySelector('.main-container').style.gridTemplateColumns = '65% 7px 34.61%'; 106 | display.resize(document.querySelector('.map-container').offsetWidth, window.innerHeight - 50); 107 | document.getElementById('fullScreenToggle').style.display = 'block'; 108 | } 109 | 110 | export function toggleMapView() { 111 | let sliderPan = document.querySelector(".sliderPan"); 112 | if (sliderPan.style.display === "block") { 113 | onlyMapView(); 114 | } else { 115 | originalToolView(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | XYZ Maps GeoJSON Visualizer 11 | 12 | 13 | 14 | 15 | Scanning the planet... 16 | 17 | X 18 | 19 | 20 | 21 | 22 | 23 | 24 | Go 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | + 42 | 2 43 | - 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | A random collection of GeoJSON Open Data samples to get you started with the various FeatureTypes: 59 | Points of NYC MTA stations 60 | MultiPoints in the ocean somewhere 61 | LineStrings of streetcars in Rostock 62 | MultiLineString in New York 63 | Polygons for Philadelpha Police Service Areas 64 | MultiPolygons of parks in Rostock 65 | 66 | 67 | 68 | 69 | 70 | Authorization Header: 71 | 72 | 73 | Authorize 74 | 75 | 76 | 77 | From GeoJSON Url: 78 | 79 | 80 | Go 81 | 82 | 83 | 84 | 85 | From GeoJSON file: 86 | 87 | Upload 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/components/eventHandling.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | import { 8 | miamiDayLayer, 9 | springSoftLayer, 10 | springBrightLayer, 11 | lineDarkLayer, 12 | lineWhiteLayer, 13 | featureProvider 14 | } from './hereMap/hereMap' 15 | import {getCustomStyle} from './hereMap/getCustomStyle' 16 | import { toggleMapView, clearURLParam } from './common' 17 | import { spaceLayer, clearSpaceData } from './loadData' 18 | import { editor, startValue } from './editor' 19 | import {alertBar} from "./alertBar"; 20 | let isDebug = false, 21 | currentMap = springSoftLayer, 22 | currentStyle = "blue"; 23 | 24 | function addLayer(l) { 25 | display.addLayer(l,0); 26 | currentMap = l; 27 | } 28 | 29 | function removeLayer() { 30 | display.removeLayer(currentMap); 31 | currentMap = null; 32 | } 33 | 34 | function DebugOnOff() { 35 | if (isDebug) { 36 | display.debug(false); 37 | display.debug(true); 38 | } 39 | } 40 | 41 | document.getElementById('zoomIn').addEventListener('click', function(ev){ 42 | display.setZoomlevel(display.getZoomlevel() + 1); 43 | document.querySelector('.zoom-info').innerHTML = display.getZoomlevel().toPrecision(2).toString(); 44 | DebugOnOff(); 45 | }); 46 | 47 | document.getElementById('zoomOut').addEventListener('click', function(ev){ 48 | if(display.getZoomlevel() > 2) { 49 | display.setZoomlevel(display.getZoomlevel() - 1); 50 | document.querySelector('.zoom-info').innerHTML = display.getZoomlevel().toPrecision(2).toString(); 51 | } 52 | DebugOnOff(); 53 | }); 54 | 55 | document.getElementById('changeFeatureColor').addEventListener('click', function(ev) { 56 | window.display.getLayers().forEach(it => { 57 | if (it.name === "featureLayer") { 58 | if (currentStyle === "blue") { 59 | it.setStyle(getCustomStyle("black")); 60 | currentStyle = "black"; 61 | document.getElementById('changeFeatureColor').style.background = '#032c2b'; 62 | document.getElementById('changeFeatureColor').style["border-color"] = '#fff'; 63 | } else if (currentStyle === "black"){ 64 | it.setStyle(getCustomStyle("yellow")); 65 | currentStyle = "yellow"; 66 | document.getElementById('changeFeatureColor').style.background = '#ffe800'; 67 | document.getElementById('changeFeatureColor').style["border-color"] = 'rgba(255,145,0,0.8)'; 68 | } else if (currentStyle === "yellow"){ 69 | it.setStyle(getCustomStyle("blue")); 70 | currentStyle = "blue"; 71 | document.getElementById('changeFeatureColor').style.background = '#00afaa'; 72 | document.getElementById('changeFeatureColor').style["border-color"] = 'rgba(29,87,84,0)'; 73 | } 74 | } 75 | }) 76 | window.display.refresh(); 77 | }); 78 | 79 | document.getElementById('mapSwitcher').addEventListener('click', function(e){ 80 | if (e.target.title !== "Map Styles") { 81 | removeLayer(); 82 | let layer; 83 | switch (e.target.title) { 84 | case "Miami": 85 | layer = miamiDayLayer; 86 | break; 87 | case "SpringSoft": 88 | layer = springSoftLayer; 89 | break; 90 | case "SpringBright": 91 | layer = springBrightLayer; 92 | break; 93 | case "LineDark": 94 | layer = lineDarkLayer; 95 | break; 96 | case "LineWhite": 97 | layer = lineWhiteLayer; 98 | break; 99 | case "Satellite": 100 | layer = satelliteLayer; 101 | break; 102 | case "Terrain": 103 | layer = terrainLayer; 104 | break; 105 | } 106 | document.getElementsByClassName("activeStyle")[0].className = ""; 107 | document.getElementById(e.target.id).className += "activeStyle"; 108 | addLayer(layer); 109 | DebugOnOff(); 110 | } 111 | }); 112 | 113 | document.getElementById('fullScreenToggle').addEventListener('click', function(){ 114 | toggleMapView(); 115 | }); 116 | 117 | document.querySelector('.geojsonFileInput').addEventListener('click', function(){ 118 | document.getElementById('geojsonFileInput').click(); 119 | }); 120 | 121 | document.addEventListener("keyup", function(event) { 122 | event.preventDefault(); 123 | if (event.key === 'Escape') { 124 | toggleMapView(); 125 | } 126 | }); 127 | 128 | document.getElementById('tab').addEventListener('click', function(e) { 129 | let i, tabContent, tabLinks; 130 | tabContent = document.getElementsByClassName("tab-content"); 131 | 132 | for (i = 0; i < tabContent.length; i++) { 133 | tabContent[`${i}`].style.display = "none"; 134 | } 135 | 136 | tabLinks = document.getElementsByClassName("tabLinks"); 137 | for (i = 0; i < tabLinks.length; i++) { 138 | tabLinks[`${i}`].className = tabLinks[`${i}`].className.replace(" selected", ""); 139 | } 140 | 141 | if(e.target.title === 'Editor') { 142 | document.getElementById('editor').style.display = "block"; 143 | e.target.className = "tabLinks selected"; 144 | } else if(e.target.title === 'Load Data') { 145 | document.getElementById('load-data-wrapper').style.display = "block"; 146 | document.getElementById('editor').style.display = "none"; 147 | e.target.className = "tabLinks selected"; 148 | } else if(e.target.title === 'Load Sample') { 149 | document.getElementById('load-sample-wrapper').style.display = "block"; 150 | document.getElementById('editor').style.display = "none"; 151 | e.target.className = "tabLinks selected"; 152 | } else if(e.target.title === 'Clear Content') { 153 | featureProvider.clear(); 154 | document.querySelector('#info').innerHTML = ""; 155 | document.querySelector('#editor-tab').click(); 156 | editor.getModel().setValue(startValue); 157 | clearURLParam(); 158 | display.removeLayer(spaceLayer); 159 | clearSpaceData(); 160 | document.querySelector('#editor-tab').click(); 161 | document.getElementById('changeFeatureColor').style.display = 'none'; 162 | } else if(e.target.title === 'Copy Content') { 163 | document.querySelector('#editor-tab').click(); 164 | navigator.clipboard.writeText(editor.getValue()).then(r => alertBar(1, 'success','Successfully copied to clipboard!')) 165 | } 166 | }); 167 | -------------------------------------------------------------------------------- /src/components/hereMap/getCustomStyle.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | export function getCustomStyle(favor) { 8 | let outLineColor, color; 9 | switch (favor) { 10 | case "black": 11 | outLineColor = 'rgb(255,255,255)'; 12 | color = '#032c2b'; 13 | break; 14 | case "blue": 15 | outLineColor = 'rgb(0,0,0,0)'; 16 | color = '#00afaa'; 17 | break; 18 | case "yellow": 19 | outLineColor = 'rgba(255,145,0,0.8)'; 20 | color = '#ffe800'; 21 | break; 22 | } 23 | return { 24 | styleGroups:{ 25 | "Point": [{ 26 | zIndex: function(feature){ 27 | return feature.properties.zIndex || 999; 28 | }, 29 | type:"Circle", 30 | stroke: function(feature){ 31 | return handleColorType(feature.properties.stroke) || handleColorType(feature.properties.color) || outLineColor; 32 | }, 33 | "strokeWidth": function(feature){ 34 | return feature.properties['stroke-width'] || 8; 35 | }, 36 | fill: function(feature){ 37 | return feature.properties.fill || handleColorType(feature.properties.color) || color; 38 | }, 39 | radius: function(feature){ 40 | return feature.properties.r || 5; 41 | }, 42 | opacity: function(feature){ 43 | return feature.properties.opacity || 1; 44 | }, 45 | }], 46 | "Point_marker": [{ 47 | zIndex: function(feature){ 48 | return feature.properties.zIndex || 999; 49 | }, 50 | type:"Image", 51 | src: function(feature){ 52 | return feature.properties['marker-url'] || ''; 53 | }, 54 | width:32, 55 | height:32 56 | 57 | }], 58 | "LineString": [{ 59 | zIndex: function(feature){ 60 | return feature.properties.zIndex || 2; 61 | }, 62 | type:"Line", 63 | stroke: function(feature){ 64 | return handleColorType(feature.properties.stroke) || handleColorType(feature.properties.color) || color; 65 | }, 66 | "strokeWidth": function(feature){ 67 | return feature.properties['stroke-width'] || 8; 68 | } 69 | }], 70 | "Polygon": [{ 71 | zIndex: function(feature){ 72 | return feature.properties.zIndex || 2; 73 | }, 74 | type:"Polygon", 75 | stroke: function(feature){ 76 | return handleColorType(feature.properties.stroke) || handleColorType(feature.properties.color) || outLineColor; 77 | }, 78 | "strokeWidth": function(feature){ 79 | return feature.properties['stroke-width'] || 8; 80 | }, 81 | opacity: function(feature){ 82 | return feature.properties.opacity || 0.6; 83 | }, 84 | fill: function(feature){ 85 | return feature.properties.fill || handleColorType(feature.properties.color) || color; 86 | }, 87 | }], 88 | "MultiPoint": [{ 89 | zIndex: function(feature){ 90 | return feature.properties.zIndex || 3; 91 | }, 92 | type:"Circle", 93 | stroke: function(feature){ 94 | return handleColorType(feature.properties.stroke) || handleColorType(feature.properties.color) || outLineColor; 95 | }, 96 | "strokeWidth": function(feature){ 97 | return feature.properties['stroke-width'] || 8; 98 | }, 99 | fill: function(feature){ 100 | return feature.properties.fill || handleColorType(feature.properties.color) || color; 101 | }, 102 | radius: function(feature){ 103 | return feature.properties.r || 5; 104 | } 105 | }], 106 | "MultiLineString": [{ 107 | zIndex: function(feature){ 108 | return feature.properties.zIndex || 2; 109 | }, 110 | type:"Line", 111 | stroke: function(feature){ 112 | return handleColorType(feature.properties.stroke) || handleColorType(feature.properties.color) || color; 113 | }, 114 | "strokeWidth": function(feature){ 115 | return feature.properties['stroke-width'] || 8; 116 | } 117 | }], 118 | "MultiPolygon": [{ 119 | zIndex: function(feature){ 120 | return feature.properties.zIndex || 999; 121 | }, 122 | type:"Polygon", 123 | stroke: function(feature){ 124 | return handleColorType(feature.properties.stroke) || handleColorType(feature.properties.color) || outLineColor; 125 | }, 126 | "strokeWidth": function(feature){ 127 | return feature.properties['stroke-width'] || 8; 128 | }, 129 | opacity: function(feature){ 130 | return feature.properties.opacity || 0.6 131 | }, 132 | fill: function(feature){ 133 | return feature.properties.fill || handleColorType(feature.properties.color) || color; 134 | } 135 | }], 136 | "Image": [{ 137 | zIndex: function(feature){ 138 | return feature.properties.zIndex || 2; 139 | }, 140 | type:"Image", 141 | src: function(feature){ 142 | let arrowColor = feature.properties.fill || handleColorType(feature.properties.color); 143 | if(arrowColor) { 144 | return getDirectionImage(arrowColor); 145 | } else { 146 | return getDirectionImage(color); 147 | } 148 | }, 149 | rotation: function(feature){ 150 | return feature.properties.vehicleBearing || feature.properties.heading_deg || 0 151 | }, 152 | width:32, 153 | height:32 154 | }], 155 | "Text": [{ 156 | zIndex: function(feature){ 157 | return feature.properties.zIndex || 4; 158 | }, 159 | type:"Text", 160 | text: function(feature){ 161 | return feature.properties['marker-text'] || ''; 162 | }, 163 | font:"normal 15px Arial", 164 | fill: function(feature){ 165 | return feature.properties['text-color'] || feature.properties['text-fill'] || '#000' 166 | } 167 | }] 168 | }, 169 | strokeWidthZoomScale: function(level){ 170 | return level > 14 ? .5 : .25; 171 | }, 172 | assign: function( feature, zoomlevel ){ 173 | 174 | if(feature.properties && (feature.properties["heading_deg"] || feature.properties["vehicleBearing"])) { 175 | return this.styleGroups["Image"]; 176 | } else if(feature.properties && feature.properties["marker-url"]) { 177 | return this.styleGroups["Point_marker"]; 178 | } else if(feature.properties && feature.properties["marker-text"]) { 179 | return this.styleGroups["Text"]; 180 | } else { 181 | return feature.geometry.type; 182 | } 183 | } 184 | }; 185 | } 186 | 187 | function handleColorType(color) { 188 | if (color) { 189 | let isValidHexColor = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color); 190 | let isValidHexColorWithoutHash = /([0-9A-F]{6}$)|([0-9A-F]{3}$)/i.test(color); 191 | 192 | if (!isValidHexColor && !color.indexOf('rgb') > -1 && !color.indexOf('hsl') > -1) { 193 | if (!(color.indexOf('#') === 1) && isValidHexColorWithoutHash) { 194 | color = '#' + color; 195 | } 196 | } 197 | return color; 198 | } else { 199 | return null; 200 | } 201 | } 202 | 203 | export function getDirectionImage(color) { 204 | let canvas = document.createElement('canvas'), 205 | ctx = canvas.getContext('2d'); 206 | canvas.width = 32; 207 | canvas.height = 32; 208 | ctx.beginPath(); 209 | ctx.moveTo(16,0); 210 | ctx.lineTo(0,32); 211 | ctx.lineTo(16,26); 212 | ctx.lineTo(32,32); 213 | ctx.fillStyle = color; 214 | ctx.fill(); 215 | return canvas.toDataURL(); 216 | } 217 | -------------------------------------------------------------------------------- /src/components/themes/WithLabel/here/countriesBright.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2017-2019 HERE Europe B.V. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | * License-Filename: LICENSE 19 | * 20 | * 21 | */ 22 | 23 | /* eslint-disable */ 24 | const countriesBright = { 25 | mainColors: ['#67D2C8', '#F7F7F7'], 26 | 27 | backgroundColor: '#67D2C8', 28 | 29 | strokeWidthZoomScale: function(level) { 30 | return level > 17 ? 1 : level > 14 ? 0.5 : 0.25; 31 | }, 32 | 33 | styleGroups: { 34 | waterArea: [ 35 | { 36 | zIndex: 4, 37 | type: 'Polygon', 38 | fill: '#F7F7F7', 39 | }, 40 | ], 41 | 42 | riverLines: [ 43 | { 44 | zIndex: 4, 45 | type: 'Line', 46 | strokeWidth: 1, 47 | stroke: '#F7F7F7', 48 | }, 49 | ], 50 | 51 | oceanLabels: [ 52 | { 53 | zLevel: 2, 54 | type: 'Text', 55 | font: '10px "OpenSans", sans-serif', 56 | text: f => f.properties.name, 57 | text: f => f.properties['name:en'], 58 | text: feature => feature.properties.name.toUpperCase(), 59 | strokeWidth: 3, 60 | stroke: '#F7F7F7', 61 | fill: '#67D2C8', 62 | collide: false, 63 | }, 64 | ], 65 | 66 | earth: [ 67 | { 68 | zIndex: 1, 69 | type: 'Polygon', 70 | fill: '#67D2C8', 71 | }, 72 | ], 73 | 74 | countryBoundary: [ 75 | { 76 | zIndex: 5, 77 | type: 'Line', 78 | strokeWidth: 6, 79 | stroke: '#F7F7F7', 80 | }, 81 | ], 82 | 83 | countryBoundaryZ9: [ 84 | { 85 | zIndex: 5, 86 | type: 'Line', 87 | strokeWidth: 14, 88 | stroke: '#F7F7F7', 89 | }, 90 | ], 91 | 92 | dashed_boundary: [ 93 | { 94 | zIndex: 5, 95 | type: 'Line', 96 | strokeWidth: 5, 97 | stroke: '#F7F7F7', 98 | strokeDasharray: [3, 4], 99 | }, 100 | ], 101 | 102 | buildings: [ 103 | { 104 | zIndex: 4, 105 | type: 'Polygon', 106 | fill: '#F7F7F7', 107 | }, 108 | ], 109 | 110 | countryL: [ 111 | { 112 | zLevel: 2, 113 | type: 'Text', 114 | text: f => f.properties['name:en'], 115 | text: feature => feature.properties.name.toUpperCase(), 116 | stroke: '#67D2C8', 117 | fill: '#F7F7F7', 118 | font: 'bold 13px "OpenSans", sans-serif', 119 | strokeWidth: 4, 120 | collide: false, 121 | }, 122 | ], 123 | 124 | countryS: [ 125 | { 126 | zLevel: 2, 127 | type: 'Text', 128 | text: f => f.properties['name:en'], 129 | text: feature => feature.properties.name.toUpperCase(), 130 | stroke: '#67D2C8', 131 | fill: '#F7F7F7', 132 | font: 'bold 9px "OpenSans", sans-serif', 133 | strokeWidth: 4, 134 | collide: false, 135 | }, 136 | ], 137 | 138 | capitalXL: [ 139 | { 140 | zLevel: 2, 141 | type: 'Text', 142 | text: f => f.properties['name:en'], 143 | stroke: '#67D2C8', 144 | fill: '#F7F7F7', 145 | // fill: '#0000ff', 146 | font: 'bold 16px "OpenSans", sans-serif', 147 | strokeWidth: 3, 148 | collide: false, 149 | }, 150 | ], 151 | 152 | capitalL: [ 153 | { 154 | zLevel: 2, 155 | type: 'Text', 156 | text: f => f.properties['name:en'], 157 | stroke: '#67D2C8', 158 | fill: '#F7F7F7', 159 | // fill: '#0000ff', 160 | font: 'bold 14px "OpenSans", sans-serif', 161 | strokeWidth: 3, 162 | collide: false, 163 | }, 164 | ], 165 | 166 | population10m: [ 167 | { 168 | zLevel: 2, 169 | type: 'Text', 170 | text: f => f.properties['name:en'], 171 | stroke: '#67D2C8', 172 | fill: '#F7F7F7', 173 | // fill: '#ffff00', 174 | font: '16px "OpenSans", sans-serif', 175 | strokeWidth: 4, 176 | collide: false, 177 | }, 178 | ], 179 | 180 | population10mLarge: [ 181 | { 182 | zLevel: 2, 183 | type: 'Text', 184 | text: f => f.properties['name:en'], 185 | stroke: '#67D2C8', 186 | fill: '#F7F7F7', 187 | // fill: '#ffff00', 188 | font: '18px "OpenSans", sans-serif', 189 | strokeWidth: 4, 190 | collide: false, 191 | }, 192 | ], 193 | 194 | population5m10m: [ 195 | { 196 | zLevel: 2, 197 | type: 'Text', 198 | text: f => f.properties['name:en'], 199 | stroke: '#67D2C8', 200 | fill: '#F7F7F7', 201 | // fill: '#ffff00', 202 | font: '14px "OpenSans", sans-serif', 203 | strokeWidth: 4, 204 | collide: false, 205 | }, 206 | ], 207 | 208 | population5m10mLarge: [ 209 | { 210 | zLevel: 2, 211 | type: 'Text', 212 | text: f => f.properties['name:en'], 213 | stroke: '#67D2C8', 214 | fill: '#F7F7F7', 215 | // fill: '#ffff00', 216 | font: '17px "OpenSans", sans-serif', 217 | strokeWidth: 4, 218 | collide: false, 219 | }, 220 | ], 221 | 222 | population1m5m: [ 223 | { 224 | zLevel: 2, 225 | type: 'Text', 226 | text: f => f.properties['name:en'], 227 | stroke: '#67D2C8', 228 | fill: '#F7F7F7', 229 | // fill: '#ffff00', 230 | font: '13px "OpenSans", sans-serif', 231 | strokeWidth: 4, 232 | collide: false, 233 | }, 234 | ], 235 | 236 | population1m5mLarge: [ 237 | { 238 | zLevel: 2, 239 | type: 'Text', 240 | text: f => f.properties['name:en'], 241 | stroke: '#67D2C8', 242 | fill: '#F7F7F7', 243 | // fill: '#ffff00', 244 | font: '16px "OpenSans", sans-serif', 245 | strokeWidth: 4, 246 | collide: false, 247 | }, 248 | ], 249 | }, 250 | 251 | assign: function(feature, level) { 252 | var props = feature.properties; 253 | var kind = props.kind; 254 | var layer = props.layer; 255 | var geom = feature.geometry.type; 256 | 257 | if (layer === 'earth') { 258 | return 'earth'; 259 | } 260 | 261 | if (layer === 'water') { 262 | if (kind === 'river') { 263 | return 'riverLines'; 264 | } 265 | 266 | if (geom === 'LineString' || geom === 'MultiLineString') { 267 | return; 268 | } 269 | 270 | if (kind === 'oceans') { 271 | if (feature.properties.min_zoom <= 6) { 272 | return 'oceanLabels'; 273 | } 274 | if (feature.properties.min_zoom === 7) { 275 | if (level <= 6) { 276 | return 'waterArea'; 277 | } 278 | return 'oceanLabels'; 279 | } 280 | if (feature.properties.min_zoom === 8) { 281 | if (level <= 7) { 282 | return 'waterArea'; 283 | } 284 | return 'oceanLabels'; 285 | } 286 | if (feature.properties.min_zoom === 9) { 287 | if (level <= 7) { 288 | return 'waterArea'; 289 | } 290 | return 'oceanLabels'; 291 | } 292 | if (feature.properties.min_zoom === 10) { 293 | if (level <= 9) { 294 | return 'waterArea'; 295 | } 296 | return 'oceanLabels'; 297 | } 298 | } 299 | 300 | return 'waterArea'; 301 | } 302 | 303 | if (layer === 'boundaries') { 304 | if (kind === 'country') { 305 | if (level >= 9) { 306 | return 'countryBoundaryZ9'; 307 | } 308 | if (level >= 1) { 309 | return 'countryBoundary'; 310 | } 311 | } 312 | if (kind === 'disputed') { 313 | return 'dashed_boundary'; 314 | } 315 | } 316 | 317 | if (layer === 'buildings') { 318 | return layer; 319 | } 320 | 321 | if (layer === 'places') { 322 | if (kind === 'country') { 323 | if (level >= 4) { 324 | return 'countryL'; 325 | } 326 | if (level >= 2) { 327 | return 'countryS'; 328 | } 329 | } 330 | 331 | if (kind === 'locality') { 332 | if (props.population >= 10000000) { 333 | if (level >= 9) { 334 | return 'population10mLarge'; 335 | } 336 | if (level >= 4) { 337 | if (props.country_capital === true) { 338 | return 'capitalXL'; 339 | } 340 | return 'population10m'; 341 | } 342 | } 343 | 344 | if (props.population >= 5000000 && props.population < 10000000) { 345 | if (level >= 9) { 346 | return 'population5m10mLarge'; 347 | } 348 | if (level >= 4) { 349 | if (props.country_capital === true) { 350 | return 'capitalL'; 351 | } 352 | return 'population5m10m'; 353 | } 354 | } 355 | 356 | if (props.population >= 1000000 && props.population < 5000000) { 357 | if (level >= 10) { 358 | return 'population1m5mLarge'; 359 | } 360 | if (level >= 4) { 361 | if (props.country_capital === true) { 362 | return 'capitalL'; 363 | } 364 | return 'population1m5m'; 365 | } 366 | } 367 | } 368 | } 369 | }, 370 | }; 371 | 372 | export default countriesBright; 373 | -------------------------------------------------------------------------------- /src/components/themes/WithLabel/here/countries.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2017-2019 HERE Europe B.V. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | * License-Filename: LICENSE 19 | * 20 | * 21 | */ 22 | 23 | /* eslint-disable */ 24 | const countries = { 25 | mainColors: ['#333333', '#AEAEAE'], 26 | 27 | backgroundColor: '#AEAEAE', 28 | 29 | strokeWidthZoomScale: function(level) { 30 | return level > 17 ? 1 : level > 14 ? 0.5 : 0.25; 31 | }, 32 | 33 | styleGroups: { 34 | waterArea: [ 35 | { 36 | zIndex: 4, 37 | type: 'Polygon', 38 | fill: '#333333', 39 | }, 40 | ], 41 | 42 | riverLines: [ 43 | { 44 | zIndex: 4, 45 | type: 'Line', 46 | strokeWidth: 1, 47 | stroke: '#333333', 48 | }, 49 | ], 50 | 51 | oceanLabels: [ 52 | { 53 | zLevel: 2, 54 | type: 'Text', 55 | font: '10px "OpenSans", sans-serif', 56 | text: f => f.properties.name, 57 | text: f => f.properties['name:en'], 58 | text: feature => feature.properties.name.toUpperCase(), 59 | strokeWidth: 3, 60 | stroke: '#333333', 61 | fill: '#AEAEAE', 62 | collide: false, 63 | }, 64 | ], 65 | 66 | earth: [ 67 | { 68 | zIndex: 1, 69 | type: 'Polygon', 70 | fill: '#AEAEAE', 71 | }, 72 | ], 73 | 74 | countryBoundary: [ 75 | { 76 | zIndex: 3, 77 | type: 'Line', 78 | strokeWidth: 6, 79 | stroke: '#333333', 80 | }, 81 | ], 82 | 83 | countryBoundaryZ9: [ 84 | { 85 | zIndex: 3, 86 | type: 'Line', 87 | strokeWidth: 14, 88 | stroke: '#333333', 89 | }, 90 | ], 91 | 92 | dashed_boundary: [ 93 | { 94 | zIndex: 3, 95 | type: 'Line', 96 | strokeWidth: 5, 97 | stroke: '#333333', 98 | strokeDasharray: [3, 4], 99 | }, 100 | ], 101 | 102 | buildings: [ 103 | { 104 | zIndex: 4, 105 | type: 'Polygon', 106 | fill: '#FFFFFF', 107 | }, 108 | ], 109 | 110 | countryL: [ 111 | { 112 | zLevel: 2, 113 | type: 'Text', 114 | text: f => f.properties['name:en'], 115 | text: feature => feature.properties.name.toUpperCase(), 116 | stroke: '#AEAEAE', 117 | fill: '#FFFFFF', 118 | font: 'bold 13px "OpenSans", sans-serif', 119 | strokeWidth: 0, 120 | collide: false, 121 | }, 122 | ], 123 | 124 | countryS: [ 125 | { 126 | zLevel: 2, 127 | type: 'Text', 128 | text: f => f.properties['name:en'], 129 | text: feature => feature.properties.name.toUpperCase(), 130 | stroke: '#AEAEAE', 131 | fill: '#FFFFFF', 132 | font: 'bold 9px "OpenSans", sans-serif', 133 | strokeWidth: 0, 134 | collide: false, 135 | }, 136 | ], 137 | 138 | capitalXL: [ 139 | { 140 | zLevel: 2, 141 | type: 'Text', 142 | text: f => f.properties['name:en'], 143 | stroke: '#AEAEAE', 144 | fill: '#FFFFFF', 145 | // fill: '#0000ff', 146 | font: 'bold 16px "OpenSans", sans-serif', 147 | strokeWidth: 0, 148 | collide: false, 149 | }, 150 | ], 151 | 152 | capitalL: [ 153 | { 154 | zLevel: 2, 155 | type: 'Text', 156 | text: f => f.properties['name:en'], 157 | stroke: '#AEAEAE', 158 | fill: '#FFFFFF', 159 | // fill: '#0000ff', 160 | font: 'bold 14px "OpenSans", sans-serif', 161 | strokeWidth: 0, 162 | collide: false, 163 | }, 164 | ], 165 | 166 | population10m: [ 167 | { 168 | zLevel: 2, 169 | type: 'Text', 170 | text: f => f.properties['name:en'], 171 | stroke: '#AEAEAE', 172 | fill: '#FFFFFF', 173 | // fill: '#ffff00', 174 | font: '16px "OpenSans", sans-serif', 175 | strokeWidth: 0, 176 | collide: false, 177 | }, 178 | ], 179 | 180 | population10mLarge: [ 181 | { 182 | zLevel: 2, 183 | type: 'Text', 184 | text: f => f.properties['name:en'], 185 | stroke: '#AEAEAE', 186 | fill: '#FFFFFF', 187 | // fill: '#ffff00', 188 | font: '18px "OpenSans", sans-serif', 189 | strokeWidth: 0, 190 | collide: false, 191 | }, 192 | ], 193 | 194 | population5m10m: [ 195 | { 196 | zLevel: 2, 197 | type: 'Text', 198 | text: f => f.properties['name:en'], 199 | stroke: '#AEAEAE', 200 | fill: '#FFFFFF', 201 | // fill: '#ffff00', 202 | font: '14px "OpenSans", sans-serif', 203 | strokeWidth: 0, 204 | collide: false, 205 | }, 206 | ], 207 | 208 | population5m10mLarge: [ 209 | { 210 | zLevel: 2, 211 | type: 'Text', 212 | text: f => f.properties['name:en'], 213 | stroke: '#AEAEAE', 214 | fill: '#FFFFFF', 215 | // fill: '#ffff00', 216 | font: '17px "OpenSans", sans-serif', 217 | strokeWidth: 0, 218 | collide: false, 219 | }, 220 | ], 221 | 222 | population1m5m: [ 223 | { 224 | zLevel: 2, 225 | type: 'Text', 226 | text: f => f.properties['name:en'], 227 | stroke: '#AEAEAE', 228 | fill: '#FFFFFF', 229 | // fill: '#ffff00', 230 | font: '13px "OpenSans", sans-serif', 231 | strokeWidth: 0, 232 | collide: false, 233 | }, 234 | ], 235 | 236 | population1m5mLarge: [ 237 | { 238 | zLevel: 2, 239 | type: 'Text', 240 | text: f => f.properties['name:en'], 241 | stroke: '#AEAEAE', 242 | fill: '#FFFFFF', 243 | // fill: '#ffff00', 244 | font: '16px "OpenSans", sans-serif', 245 | strokeWidth: 0, 246 | collide: false, 247 | }, 248 | ], 249 | 250 | neighbourhoodS: [ 251 | { 252 | zLevel: 2, 253 | type: 'Text', 254 | text: f => f.properties['name:en'], 255 | text: feature => feature.properties.name.toUpperCase(), 256 | stroke: '#AEAEAE', 257 | // fill: '#D4D4D4', 258 | fill: '#333333', 259 | font: '9px "OpenSans", sans-serif', 260 | strokeWidth: 2, 261 | collide: false, 262 | }, 263 | ], 264 | 265 | neighbourhoodL: [ 266 | { 267 | zLevel: 2, 268 | type: 'Text', 269 | text: f => f.properties['name:en'], 270 | text: feature => feature.properties.name.toUpperCase(), 271 | stroke: '#AEAEAE', 272 | // fill: '#D4D4D4', 273 | fill: '#333333', 274 | font: '12px "OpenSans", sans-serif', 275 | strokeWidth: 3, 276 | collide: false, 277 | }, 278 | ], 279 | }, 280 | 281 | assign: function(feature, level) { 282 | var props = feature.properties; 283 | var kind = props.kind; 284 | var layer = props.layer; 285 | var geom = feature.geometry.type; 286 | 287 | if (layer === 'earth') { 288 | return 'earth'; 289 | } 290 | 291 | if (layer === 'water') { 292 | if (kind === 'river') { 293 | return 'riverLines'; 294 | } 295 | 296 | if (geom === 'LineString' || geom === 'MultiLineString') { 297 | return; 298 | } 299 | 300 | if (kind === 'oceans') { 301 | if (feature.properties.min_zoom <= 6) { 302 | return 'oceanLabels'; 303 | } 304 | if (feature.properties.min_zoom === 7) { 305 | if (level <= 6) { 306 | return 'waterArea'; 307 | } 308 | return 'oceanLabels'; 309 | } 310 | if (feature.properties.min_zoom === 8) { 311 | if (level <= 7) { 312 | return 'waterArea'; 313 | } 314 | return 'oceanLabels'; 315 | } 316 | if (feature.properties.min_zoom === 9) { 317 | if (level <= 7) { 318 | return 'waterArea'; 319 | } 320 | return 'oceanLabels'; 321 | } 322 | if (feature.properties.min_zoom === 10) { 323 | if (level <= 9) { 324 | return 'waterArea'; 325 | } 326 | return 'oceanLabels'; 327 | } 328 | } 329 | 330 | return 'waterArea'; 331 | } 332 | 333 | if (layer === 'boundaries') { 334 | if (kind === 'country') { 335 | if (level >= 9) { 336 | return 'countryBoundaryZ9'; 337 | } 338 | if (level >= 1) { 339 | return 'countryBoundary'; 340 | } 341 | } 342 | if (kind === 'disputed') { 343 | return 'dashed_boundary'; 344 | } 345 | } 346 | 347 | if (layer === 'buildings') { 348 | return layer; 349 | } 350 | 351 | if (layer === 'places') { 352 | if (kind === 'country') { 353 | if (level >= 4) { 354 | return 'countryL'; 355 | } 356 | if (level >= 2) { 357 | return 'countryS'; 358 | } 359 | } 360 | 361 | if (kind === 'locality') { 362 | if (props.population >= 10000000) { 363 | if (level >= 9) { 364 | return 'population10mLarge'; 365 | } 366 | if (level >= 4) { 367 | if (props.country_capital === true) { 368 | return 'capitalXL'; 369 | } 370 | return 'population10m'; 371 | } 372 | } 373 | 374 | if (props.population >= 5000000 && props.population < 10000000) { 375 | if (level >= 9) { 376 | return 'population5m10mLarge'; 377 | } 378 | if (level >= 4) { 379 | if (props.country_capital === true) { 380 | return 'capitalL'; 381 | } 382 | return 'population5m10m'; 383 | } 384 | } 385 | 386 | if (props.population >= 1000000 && props.population < 5000000) { 387 | if (level >= 10) { 388 | return 'population1m5mLarge'; 389 | } 390 | if (level >= 4) { 391 | if (props.country_capital === true) { 392 | return 'capitalL'; 393 | } 394 | return 'population1m5m'; 395 | } 396 | } 397 | } 398 | 399 | if (kind === 'neighbourhood') { 400 | if (level >= 15) { 401 | return 'neighbourhoodL'; 402 | } 403 | if (level >= 13) { 404 | return 'neighbourhoodS'; 405 | } 406 | } 407 | } 408 | }, 409 | }; 410 | 411 | export default countries; 412 | -------------------------------------------------------------------------------- /src/components/loadData.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | import { editor } from './editor' 8 | import { getCustomStyle } from './hereMap/getCustomStyle' 9 | import { alertBar } from './alertBar.js' 10 | import { featureProvider } from './hereMap/hereMap' 11 | import {GeoRect, SpaceProvider, TileLayer} from "@here/xyz-maps-core"; 12 | import {onlyMapView} from "./common"; 13 | let spaceLayer, 14 | spaceProvider, 15 | token = null; 16 | 17 | 18 | function loader(type) { 19 | if(type === 'block') { 20 | document.querySelector('.loader').style.display = 'block'; 21 | } else { 22 | document.querySelector('.loader').style.display = 'none'; 23 | } 24 | } 25 | 26 | export function clearSpaceData() { 27 | spaceLayer = undefined; 28 | spaceProvider = undefined; 29 | } 30 | 31 | document.getElementById('authButton').addEventListener('click', function(e) { 32 | if (token != null) { 33 | token = null; 34 | document.getElementById('authHeader').value = ''; 35 | document.getElementById('authButton').innerHTML = 'Authorize'; 36 | } else { 37 | token = document.getElementById('authHeader').value; 38 | console.log(document.getElementById('authButton')); 39 | document.getElementById('authButton').innerHTML = 'Clear'; 40 | } 41 | }) 42 | 43 | export function handleMultipleLocalFiles(fileList) { 44 | 45 | let featuresCollectionArr = [], 46 | filesProcessed = 0; 47 | loader('block'); 48 | for(let s = 0; s -1) { 108 | let urlList = urlParam.split('&maponly')[0]; 109 | multipleHttpGetAsync(urlList.split(';')); 110 | } else { 111 | multipleHttpGetAsync(urlParam.split(';')); 112 | } 113 | } else { 114 | let params = new URLSearchParams(window.location.search); 115 | if(params.has("space") && params.has("access_token")){ 116 | loadSpace(params.get("space"), params.get("access_token")); 117 | } 118 | } 119 | 120 | if( window.location.href.indexOf('maponly=true') > -1) { 121 | onlyMapView(); 122 | document.querySelector('.fullScreenToggle').style.display = 'none'; 123 | } 124 | } 125 | 126 | function loadSpace(spaceId, spaceAccessToken) { 127 | 128 | spaceProvider = new SpaceProvider ({ 129 | name: 'spaceProvider', 130 | level: 2, 131 | space: spaceId, 132 | credentials: { 133 | access_token: spaceAccessToken, 134 | limit: 100000 135 | } 136 | }); 137 | 138 | spaceLayer = new TileLayer ({ 139 | name: 'spaceLayer', 140 | min: 2, 141 | max: 20, 142 | providers: [{ 143 | min: 2, 144 | max: 20, 145 | provider: spaceProvider 146 | }], 147 | style: getCustomStyle("light") 148 | }); 149 | 150 | display.addLayer(spaceLayer); 151 | } 152 | 153 | function handleMultipleXhr(data) { 154 | let featureList = []; 155 | for(let i = 0; i< data.length; i++) { 156 | let respText = data[`${i}`].responseText; 157 | 158 | if(data[`${i}`].getResponseHeader('Content-Type').indexOf('json') > -1) { 159 | featureList = handleMultipleFeature(respText, featureList); 160 | } else if(data[`${i}`].getResponseHeader('Content-Type').indexOf('text') > -1) { 161 | try { 162 | featureList = handleMultipleFeature(respText, featureList); 163 | } catch(e) { 164 | alertBar(1, 'error','Error: Unexpected Content-Type.'); 165 | } 166 | } 167 | } 168 | return featureList; 169 | } 170 | 171 | function getPromise(url, wHeader=true) { 172 | return new Promise(function(resolve, reject) { 173 | let xhr = new XMLHttpRequest(); 174 | xhr.open( 'GET', url, true ); 175 | if (wHeader && token != null) { 176 | xhr.setRequestHeader("Authorization", token); 177 | } 178 | xhr.onload = function(e) { 179 | if(xhr.readyState === 4){ 180 | if (xhr.status === 200) { 181 | resolve(xhr); 182 | } else { 183 | loader('unblock'); 184 | console.log('Error code ' + xhr.status + ' for ' + xhr.responseURL); 185 | alertBar(1, 'error','Error: Failed to load resource.'); 186 | } 187 | } else { 188 | loader('unblock'); 189 | alertBar(1, 'error','Error: Failed to load resource.'); 190 | } 191 | } 192 | xhr.onerror = function(e) { 193 | loader('unblock'); 194 | alertBar(1, 'error','Error: Failed to load resource.'); 195 | } 196 | xhr.send(null); 197 | }); 198 | } 199 | 200 | function handleMultipleFeature(respText, featureList) { 201 | let parsed = JSON.parse(respText), 202 | currentFeatureCollection; 203 | 204 | if(parsed.type === 'FeatureCollection') { 205 | currentFeatureCollection = parsed.features; 206 | } else if(parsed.type === "MultiPoint" || 207 | parsed.type === "LineString" || 208 | parsed.type === "MultiLineString" || 209 | parsed.type === "Polygon" || 210 | parsed.type === "Point" || 211 | parsed.type === "MultiPolygon") { 212 | currentFeatureCollection = [{ 213 | "type": "Feature", 214 | "properties": {}, 215 | "geometry": parsed 216 | }] 217 | } else { 218 | currentFeatureCollection = [parsed]; 219 | } 220 | 221 | for(let j=0; j=0; i--) { 232 | let code = str.charCodeAt(i); 233 | if (code > 0x7f && code <= 0x7ff) s++; 234 | else if (code > 0x7ff && code <= 0xffff) s+=2; 235 | if (code >= 0xDC00 && code <= 0xDFFF) i--; //trail surrogate 236 | } 237 | return s; 238 | } 239 | 240 | function handleGeojsonResponse(txt) { 241 | let geojsonTxt = JSON.parse(txt); 242 | if(byteLength(txt) < 200000000){ 243 | document.querySelector('#editor-tab').click(); 244 | editor.setValue(JSON.stringify(geojsonTxt, null, 2)); 245 | } else { 246 | displayGeoJSON(geojsonTxt); 247 | window.setTimeout(function(){ 248 | alertBar(1, 'warning','Editor is not loaded with JSON as data size is more than 20mb.'); 249 | }, 3000); 250 | } 251 | } 252 | 253 | function handleMultipleGeojsonResponse(obj) { 254 | let geojsonTxt = JSON.stringify(obj); 255 | if(byteLength(geojsonTxt) < 200000000){ 256 | document.querySelector('#editor-tab').click(); 257 | editor.setValue(JSON.stringify(obj, null, 2)); 258 | } else { 259 | displayGeoJSON(obj); 260 | window.setTimeout(function(){ 261 | alertBar(1, 'warning','Editor is not loaded with JSON as data size is more than 20mb.'); 262 | }, 3000); 263 | } 264 | } 265 | 266 | export function displayGeoJSON(collection) { 267 | let failedFeature = 0; 268 | document.querySelector('#info').innerHTML = ""; 269 | alertBar(0); 270 | if( !(collection instanceof Array) ) { 271 | if(collection.type === "FeatureCollection") { 272 | collection = collection.features; 273 | } else if(collection.type === "MultiPoint" || 274 | collection.type === "LineString" || 275 | collection.type === "MultiLineString" || 276 | collection.type === "Polygon" || 277 | collection.type === "Point" || 278 | collection.type === "MultiPolygon") { 279 | collection = [{ 280 | "type": "Feature", 281 | "properties": {}, 282 | "geometry": collection 283 | }] 284 | } else { 285 | collection = [collection]; 286 | } 287 | } 288 | 289 | let length = collection.length; 290 | 291 | if( length ) 292 | { 293 | featureProvider.clear(); 294 | 295 | let minLon=Infinity, minLat=Infinity, maxLon=-Infinity, maxLat=-Infinity; 296 | 297 | while( length-- ) 298 | { 299 | // feature.bbox is only optional by geojson spec so we cant rely on... 300 | // ...but the maphub provider is making sure every feature includes a boundingbox =) 301 | try{ 302 | let feature = featureProvider.addFeature( collection[`${length}`] ); 303 | 304 | // GeometryCollections are not supported for now. 305 | if( feature ) 306 | { 307 | let bbox = feature.bbox; 308 | if (bbox[0] < minLon) minLon = bbox[0]; 309 | if (bbox[1] < minLat) minLat = bbox[1]; 310 | if (bbox[2] > maxLon) maxLon = bbox[2]; 311 | if (bbox[3] > maxLat) maxLat = bbox[3]; 312 | } 313 | }catch(e){ 314 | console.log("Failed to add current feature : "+JSON.stringify(collection[`${length}`])); 315 | failedFeature++; 316 | } 317 | } 318 | 319 | if( minLon < Infinity ) { 320 | display.setViewBounds( 321 | new GeoRect( minLon, minLat, maxLon, maxLat ) 322 | ); 323 | } 324 | 325 | if(failedFeature) { 326 | alertBar(1, 'info', featureProvider.cnt + ' feature(s) added successfully and ' + failedFeature +' feature(s) failed to load.'); 327 | console.error("Failed to add "+ failedFeature +" feature(s)"); 328 | } else if(featureProvider.cnt && window.location.href.indexOf('maponly') === -1) { 329 | alertBar(1, 'success', featureProvider.cnt + ' feature(s) added successfully.'); 330 | } 331 | } 332 | } 333 | 334 | export { spaceLayer, spaceProvider } 335 | -------------------------------------------------------------------------------- /src/style/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | * { 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | } 12 | 13 | html, body{ 14 | width: 100%; 15 | height: 100%; 16 | } 17 | 18 | body{ 19 | overflow: hidden; 20 | font-size: 16px; 21 | line-height: 20px; 22 | font-family: sans-serif; 23 | } 24 | 25 | button { 26 | font-family: sans-serif; 27 | } 28 | 29 | #map { 30 | background-color: #e1e1e1; 31 | position: relative; 32 | width: 100%; 33 | height: 100%; 34 | } 35 | 36 | #map > div:first-child { 37 | width: 100% !important; 38 | height: 100% !important; 39 | } 40 | 41 | #map > div:first-child > canvas { 42 | width: 100% !important; 43 | height: 100% !important; 44 | } 45 | 46 | #info{ 47 | z-index: 1; 48 | position: absolute; 49 | left: 0; 50 | top: 0; 51 | background-color: rgba(30, 30, 30, 0.8); 52 | border-radius: 5px; 53 | max-height: 100%; 54 | max-width: 40%; 55 | min-width: 300px; 56 | overflow: auto; 57 | } 58 | 59 | #info >div:first-child{ 60 | padding: 0.5em; 61 | 62 | } 63 | 64 | .mainWrapper { 65 | height: 100%; 66 | } 67 | 68 | .main-container { 69 | display: grid; 70 | grid-template-columns: 65% 7px 34.61%; 71 | height: 100%; 72 | } 73 | 74 | .panel-wrapper { 75 | background-color: #fff; 76 | } 77 | 78 | .editor-wrapper { 79 | width: 100%; 80 | height: calc(100vh - 50px); 81 | border-left: 1px solid #e1e1e1; 82 | } 83 | 84 | .editor-wrapper .edit { 85 | display: none; 86 | } 87 | 88 | .sliderPan { 89 | background: #fff url("../images/drag-dots.svg") center no-repeat; 90 | background-size: 29px; 91 | display: block; 92 | } 93 | .sliderPanDark { 94 | background: #000 url("../images/drag-dots.svg") center no-repeat; 95 | background-size: 29px; 96 | display: block; 97 | } 98 | 99 | .load-sample-wrapper, 100 | .load-data-wrapper, 101 | .lat-long-wrapper, 102 | .geojson-url-wrapper { 103 | background-color: #f5f4f4; 104 | padding: 15px; 105 | height: calc(100% - 40px); 106 | width: 100%; 107 | } 108 | 109 | .load-data-wrapper { 110 | border-left: 1px solid #e1e1e1; 111 | } 112 | 113 | .load-sample-wrapper > a { 114 | font-family: sans-serif; 115 | text-decoration: underline; 116 | margin-top: 30px; 117 | display: grid; 118 | grid-template-columns: 80% 15%; 119 | grid-column-gap: 10px; 120 | } 121 | 122 | a.button { 123 | -webkit-appearance: button; 124 | -moz-appearance: button; 125 | /* text-decoration: none; */ 126 | color: #000; 127 | } 128 | 129 | .lat-long-wrapper > div { 130 | margin-top: 30px; 131 | display: grid; 132 | grid-template-columns: 25% 25% 25% auto; 133 | grid-column-gap: 20px; 134 | } 135 | 136 | .geojson-url-wrapper > div { 137 | margin-top: 30px; 138 | display: grid; 139 | grid-template-columns: 80% 15%; 140 | grid-column-gap: 20px; 141 | } 142 | 143 | .tab-content { 144 | display: none; 145 | } 146 | 147 | .editor-wrapper { 148 | display: block; 149 | } 150 | 151 | .load-data-wrapper h1 { 152 | font-size: 16px; 153 | } 154 | 155 | .load-data-wrapper ul li:nth-child(odd) { 156 | background-color: #fff; 157 | } 158 | 159 | .load-data-wrapper ul li { 160 | width: 100%; 161 | height: 45px; 162 | padding-left: 12px; 163 | line-height: 45px; 164 | cursor: pointer; 165 | display: block; 166 | overflow: hidden; 167 | text-overflow: ellipsis; 168 | white-space: nowrap; 169 | text-decoration: underline; 170 | } 171 | 172 | .loadDiv, 173 | .loadDataFromUploadedFile, 174 | .loadDataFromUrl { 175 | margin-top: 20px; 176 | margin-bottom: 30px; 177 | padding-bottom: 30px; 178 | border-bottom: 1px solid #dedede; 179 | } 180 | .loadDiv > div, 181 | .loadDataFromUrl > div{ 182 | margin-top: 15px; 183 | display: flex; 184 | flex-direction: row; 185 | justify-content: space-between; 186 | align-items: baseline; 187 | } 188 | .loadDiv div span, 189 | .loadDataFromUploadedFile div span { 190 | cursor: pointer; 191 | font-size: 14px; 192 | } 193 | 194 | .map-container { 195 | height: calc(100% - 50px); 196 | width: 100%; 197 | position: relative; 198 | } 199 | 200 | .map-panel-wrapper { 201 | margin: auto 0; 202 | } 203 | 204 | .geojson-url-or-latlong { 205 | display: inline-block; 206 | padding: 6px 12px; 207 | font-size: 16px; 208 | outline: none; 209 | border: 0; 210 | font-weight: 400; 211 | border-bottom: 1px solid #c7c7c7; 212 | margin-right: 10px; 213 | } 214 | 215 | .geojson-url-or-latlong:focus { 216 | background-color: #fff; 217 | border-bottom: 1px solid #08D473; 218 | } 219 | 220 | .geojson-url-or-latlong::-webkit-input-placeholder { 221 | font-size: 15px; 222 | font-style: italic; 223 | font-weight: 100; 224 | color: #919191; 225 | } 226 | 227 | /* Notification bar */ 228 | 229 | .alert-bar { 230 | position: absolute; 231 | top: 0; 232 | left: 0; 233 | height: 50px; 234 | width: 100%; 235 | line-height: 50px; 236 | background: #FBCA40; 237 | z-index: 111; 238 | padding: 0 20px; 239 | display: none; 240 | font-size: 17px; 241 | } 242 | 243 | .remove-bar { 244 | position: absolute; 245 | top: 0; 246 | right: 20px; 247 | font-weight: 600; 248 | font-size: 15px; 249 | cursor: pointer; 250 | } 251 | 252 | .prettyPrint { 253 | position: absolute; 254 | bottom: 20px; 255 | right: 20px; 256 | width: 20px; 257 | height: 23px; 258 | background-color: grey; 259 | text-align: center; 260 | color: #fff; 261 | cursor: pointer; 262 | font-weight: 600; 263 | padding: 3px; 264 | font-size: 14px; 265 | z-index: 111; 266 | } 267 | 268 | .mapSwitcher { 269 | position: absolute; 270 | right: 55px; 271 | bottom: 23px; 272 | padding: 0 5px; 273 | height: 40px; 274 | background: #fff; 275 | font-size: 13px; 276 | border-radius: 4px; 277 | z-index: 6; 278 | } 279 | 280 | .mapSwitcher:hover { 281 | box-sizing: border-box; 282 | position: absolute; 283 | right: 55px; 284 | bottom: 23px; 285 | padding: 0 5px; 286 | height: 40px; 287 | background: #fff; 288 | font-size: 13px; 289 | border-radius: 4px; 290 | z-index: 6; 291 | } 292 | 293 | .mapSwitcher img { 294 | display: none; 295 | } 296 | 297 | .mapSwitcher:hover img { 298 | display: inline-block; 299 | vertical-align: middle; 300 | color: #000; 301 | cursor: pointer; 302 | user-select: none; 303 | border: 1px solid #ddd; 304 | border-radius: 4px; 305 | padding: 5px; 306 | width: 50px; 307 | height: 40px; 308 | } 309 | 310 | .mapSwitcher span:first-child { 311 | border-left: 0; 312 | } 313 | 314 | .mapSwitcher .activeStyle{ 315 | display: inline-block; 316 | vertical-align: middle; 317 | color: #000; 318 | cursor: pointer; 319 | user-select: none; 320 | border: 1px solid #ddd; 321 | border-radius: 4px; 322 | padding: 5px; 323 | width: 50px; 324 | height: 40px; 325 | } 326 | 327 | #fullScreenToggle { 328 | position: absolute; 329 | top: 10px; 330 | right: 10px; 331 | cursor: pointer; 332 | background: #fff url("../images/full-screen.svg") 0 3px no-repeat; 333 | width: 24px; 334 | height: 25px; 335 | border-radius: 3px; 336 | } 337 | 338 | .error-tooltip:before { 339 | opacity: 0; 340 | pointer-events: none; 341 | content: attr(message); 342 | transition: opacity .4s; 343 | -moz-transition: opacity .4s; 344 | -webkit-transition: opacity .4s; 345 | -o-transition: opacity .4s; 346 | -ms-transition: opacity .4s; 347 | -webkit-transition: all 100ms; 348 | content: attr(message); 349 | width: 300px; 350 | max-width: 600px; 351 | font-size: 10pt; 352 | padding: 2px 5px; 353 | border: 1px solid black; 354 | border-radius: 4px 4px 4px 4px; 355 | position: absolute; 356 | background-color: #ffd; 357 | z-index: 999; 358 | } 359 | 360 | .error-tooltip:hover:before { 361 | opacity:1; 362 | margin-left:56px; 363 | } 364 | 365 | .json-formatter-dark.json-formatter-row .json-formatter-key { 366 | cursor: pointer; 367 | } 368 | 369 | .latlongBtn { 370 | background-color: #08D473; 371 | border: #00000000; 372 | cursor: pointer; 373 | color: #ffffff; 374 | padding: 7px; 375 | outline: none; 376 | text-align: center; 377 | text-decoration: none; 378 | display: inline-block; 379 | border-radius: 2px; 380 | font-size: 14px; 381 | width: 50px; 382 | } 383 | 384 | .tab { 385 | box-shadow: 10px -4px 8px 1px #696969; 386 | z-index: 9; 387 | position: relative; 388 | height: 50px; 389 | overflow: hidden; 390 | } 391 | 392 | .tab button { 393 | margin-top: 10px; 394 | margin-left: 10px; 395 | border: none; 396 | border-radius: 1px; 397 | outline: none; 398 | cursor: pointer; 399 | padding: 16px 20px 10px 20px; 400 | transition: 0.3s; 401 | font-size: 16px; 402 | background: transparent; 403 | border-bottom: 5px solid transparent; 404 | } 405 | 406 | .tab > button.selected { 407 | background-color: rgba(9, 148, 222, 0.1); 408 | color: #000; 409 | border-bottom: 5px solid rgb(9, 148, 222); 410 | } 411 | 412 | .tabContent { 413 | display: none; 414 | padding: 6px 12px; 415 | border: 1px solid #ccc; 416 | border-top: none; 417 | } 418 | .authorize, 419 | .geojsonFileInput, 420 | .getgeoJSONByUrl { 421 | background-color: #08D473; 422 | border: #00000000; 423 | font-size: 15px; 424 | cursor: pointer; 425 | color: #ffffff; 426 | padding: 8px 7px 7px 8px; 427 | outline: none; 428 | text-align: center; 429 | text-decoration: none; 430 | display: inline-block; 431 | width: 95px; 432 | user-select: none; 433 | height: 40px; 434 | border-radius: 2px; 435 | } 436 | 437 | .inputClass, 438 | .geojsonUrl { 439 | display: block; 440 | width: calc(100% - 110px); 441 | padding: 0 10px; 442 | color: inherit; 443 | font-size: inherit; 444 | background: #e4e6e9; 445 | border: 1px solid #e4e6e9; 446 | text-align: inherit; 447 | border-color: #babcc4; 448 | height: 40px; 449 | font-weight: 400; 450 | } 451 | .inputClass::placeholder, 452 | .geojsonUrl::placeholder { 453 | font-style: italic; 454 | font-weight: 100; 455 | } 456 | 457 | input:focus { 458 | border-color: white; 459 | background-color: white; 460 | transition-duration: 0.2s; 461 | transition-property: inherit; 462 | outline: none; 463 | } 464 | 465 | .loadDataFromUploadedFile, 466 | .resetEditor { 467 | display: flex; 468 | flex-direction: row; 469 | justify-content: space-between; 470 | align-items: baseline; 471 | } 472 | 473 | .xyzlogo { 474 | background: url('../images/xyz-logo.svg') no-repeat; 475 | width: 80px; 476 | height: 33px; 477 | margin: auto 0; 478 | } 479 | 480 | .navlinks { 481 | display: inline-block; 482 | } 483 | 484 | /* Loader */ 485 | 486 | 487 | .loader { 488 | position: fixed; 489 | width: 100%; 490 | height: 100%; 491 | background: rgba(0, 175, 170, 0.3); 492 | z-index: 999; 493 | display: none; 494 | } 495 | 496 | .loader div { 497 | padding: 20px; 498 | width: 236px; 499 | background: #fdfdfd; 500 | border-radius: 5px; 501 | border:0; 502 | color:#04a6a1; 503 | position: absolute; 504 | top:50%; 505 | left:50%; 506 | margin-left: -118px; 507 | margin-top: -30px; 508 | font-size: 16px; 509 | text-align: center; 510 | font-weight: 400; 511 | } 512 | 513 | /* Zoom Control */ 514 | 515 | .wrapper-zoomControl { 516 | position: absolute; 517 | right: 10px; 518 | bottom: 20px; 519 | text-align: center; 520 | font-family: sans-serif; 521 | color: #000; 522 | user-select: none; 523 | z-index: 1; 524 | } 525 | 526 | .wrapper-zoomControl div { 527 | background: #fff; 528 | border-radius: 4px; 529 | font-size: 12px; 530 | width: 28px; 531 | margin: 2px; 532 | } 533 | 534 | 535 | .wrapper-zoomControl .zoomButton { 536 | background: #fff; 537 | width: 28px; 538 | height: 28px; 539 | border: none; 540 | display: flex; 541 | align-items: center; 542 | justify-content: center; 543 | position: relative; 544 | transition: background 0.2s; 545 | cursor: pointer; 546 | line-height: 22px; 547 | font-weight: 200; 548 | font-size: 27px; 549 | border-radius: 4px; 550 | margin: 2px; 551 | outline: none; 552 | color: #000000; 553 | } 554 | 555 | .wrapper-zoomControl .button:hover { 556 | background-color: #e1e1e1; 557 | cursor: pointer; 558 | } 559 | 560 | /* Zoom Control */ 561 | 562 | 563 | /* To avoid FOUC */ 564 | 565 | .desktopNavigationBar { 566 | display: flex; 567 | flex-direction: row; 568 | justify-content: space-between; 569 | background-color: #fff; 570 | height: 50px; 571 | padding: 5px 30px; 572 | box-shadow: -12px -2px 8px 1px #696969; 573 | z-index: 9; 574 | position: relative; 575 | } 576 | .main-container {display: grid;} 577 | 578 | #editor-tab { 579 | z-index: 0; 580 | background: url("../images/light/code.svg") no-repeat center; 581 | } 582 | 583 | #load-data-tab { 584 | z-index: 0; 585 | background: url("../images/light/tool.svg") no-repeat center; 586 | } 587 | 588 | #load-sample-tab { 589 | z-index: 0; 590 | background: url("../images/light/gift.svg") no-repeat center; 591 | } 592 | 593 | #copyToClipboard { 594 | z-index: 0; 595 | background: url("../images/light/copy.svg") no-repeat center; 596 | } 597 | 598 | #clearContent { 599 | z-index: 0; 600 | background: url("../images/light/trash-2.svg") no-repeat center; 601 | } 602 | 603 | #darkMode { 604 | z-index: 0; 605 | background: url("../images/light/moon.svg") no-repeat center; 606 | } 607 | 608 | #showQuadkeys { 609 | background: #fff url("../images/quadkeys.png") no-repeat center; 610 | position: absolute; 611 | top: 40px; 612 | right: 10px; 613 | cursor: pointer; 614 | width: 24px; 615 | height: 20px; 616 | border-radius: 2px; 617 | } 618 | 619 | #changeFeatureColor { 620 | display: none; 621 | background: #00afaa; 622 | width: 20px; 623 | height: 16px; 624 | position: absolute; 625 | right: 55px; 626 | bottom: 70px; 627 | border: 2px solid rgba(29,87,84,0.0); 628 | } 629 | -------------------------------------------------------------------------------- /src/lib/jsonlint.js: -------------------------------------------------------------------------------- 1 | /* Jison generated parser */ 2 | let jsonlint = (function(){ 3 | let parser = {trace: function trace() { }, 4 | yy: {}, 5 | symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, 6 | terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, 7 | productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], 8 | performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { 9 | 10 | let $0 = $$.length - 1; 11 | switch (yystate) { 12 | case 1: // replace escaped characters with actual character 13 | this.$ = yytext.replace(/\\([\\"])/g, "$"+"1") 14 | .replace(/\\n/g,'\n') 15 | .replace(/\\r/g,'\r') 16 | .replace(/\\t/g,'\t') 17 | .replace(/\\v/g,'\v') 18 | .replace(/\\f/g,'\f') 19 | .replace(/\\b/g,'\b'); 20 | 21 | break; 22 | case 2:this.$ = Number(yytext); 23 | break; 24 | case 3:this.$ = null; 25 | break; 26 | case 4:this.$ = true; 27 | break; 28 | case 5:this.$ = false; 29 | break; 30 | case 6:return this.$ = $$[`${$0-1}`]; 31 | case 13:this.$ = {}; 32 | break; 33 | case 14:this.$ = $$[`${$0-1}`]; 34 | break; 35 | case 15: this.$ = [$$[`${$0-2}`], $$[`${$0}`]]; 36 | break; 37 | case 16:this.$ = {}; this.$[$$[`${$0}`][0]] = $$[`${$0}`][1]; 38 | break; 39 | case 17:this.$ = $$[`${$0-2}`]; $$[`${$0-2}`][$$[`${$0}`][0]] = $$[`${$0}`][1]; 40 | break; 41 | case 18:this.$ = []; 42 | break; 43 | case 19:this.$ = $$[`${$0-1}`]; 44 | break; 45 | case 20:this.$ = [$$[`${$0}`]]; 46 | break; 47 | case 21:this.$ = $$[`${$0-2}`]; $$[`${$0-2}`].push($$[`${$0}`]); 48 | break; 49 | } 50 | }, 51 | table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], 52 | defaultActions: {16:[2,6]}, 53 | parseError: function parseError(str, hash) { 54 | throw new Error(str); 55 | }, 56 | parse: function parse(input) { 57 | let self = this, 58 | stack = [0], 59 | vstack = [null], // semantic value stack 60 | lstack = [], // location stack 61 | table = this.table, 62 | yytext = '', 63 | yylineno = 0, 64 | yyleng = 0, 65 | recovering = 0, 66 | TERROR = 2, 67 | EOF = 1; 68 | 69 | //this.reductionCount = this.shiftCount = 0; 70 | 71 | this.lexer.setInput(input); 72 | this.lexer.yy = this.yy; 73 | this.yy.lexer = this.lexer; 74 | if (typeof this.lexer.yylloc == 'undefined') 75 | this.lexer.yylloc = {}; 76 | let yyloc = this.lexer.yylloc; 77 | lstack.push(yyloc); 78 | 79 | if (typeof this.yy.parseError === 'function') 80 | this.parseError = this.yy.parseError; 81 | 82 | function popStack (n) { 83 | stack.length = stack.length - 2*n; 84 | vstack.length = vstack.length - n; 85 | lstack.length = lstack.length - n; 86 | } 87 | 88 | function lex() { 89 | let token; 90 | token = self.lexer.lex() || 1; // $end = 1 91 | // if token isn't its numeric value, convert 92 | if (typeof token !== 'number') { 93 | token = self.symbols_[`${token}`] || token; 94 | } 95 | return token; 96 | } 97 | 98 | let symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; 99 | while (true) { 100 | // retrieve state number from top of stack 101 | state = stack[stack.length-1]; 102 | 103 | // use default actions if available 104 | if (this.defaultActions[`${state}`]) { 105 | action = this.defaultActions[`${state}`]; 106 | } else { 107 | if (symbol == null) 108 | symbol = lex(); 109 | // read action for current state and first input 110 | action = table[`${state}`] && table[`${state}`][`${symbol}`]; 111 | } 112 | 113 | // handle parse error 114 | _handle_error: 115 | if (typeof action === 'undefined' || !action.length || !action[0]) { 116 | 117 | if (!recovering) { 118 | // Report error 119 | expected = []; 120 | for (p in table[`${state}`]) if (this.terminals_[`${p}`] && p > 2) { 121 | expected.push("'"+this.terminals_[`${p}`]+"'"); 122 | } 123 | let errStr = ''; 124 | if (this.lexer.showPosition) { 125 | errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[`${symbol}`]+ "'"; 126 | } else { 127 | errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + 128 | (symbol === 1 /*EOF*/ ? "end of input" : 129 | ("'"+(this.terminals_[`${symbol}`] || symbol)+"'")); 130 | } 131 | this.parseError(errStr, 132 | {text: this.lexer.match, token: this.terminals_[`${symbol}`] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); 133 | } 134 | 135 | // just recovered from another error 136 | if (recovering === 3) { 137 | if (symbol === EOF) { 138 | throw new Error(errStr || 'Parsing halted.'); 139 | } 140 | 141 | // discard current lookahead and grab another 142 | yyleng = this.lexer.yyleng; 143 | yytext = this.lexer.yytext; 144 | yylineno = this.lexer.yylineno; 145 | yyloc = this.lexer.yylloc; 146 | symbol = lex(); 147 | } 148 | 149 | // try to recover from error 150 | while (1) { 151 | // check for error recovery rule in this state 152 | if ((TERROR.toString()) in table[`${state}`]) { 153 | break; 154 | } 155 | if (state === 0) { 156 | throw new Error(errStr || 'Parsing halted.'); 157 | } 158 | popStack(1); 159 | state = stack[stack.length-1]; 160 | } 161 | 162 | preErrorSymbol = symbol; // save the lookahead token 163 | symbol = TERROR; // insert generic error symbol as new lookahead 164 | state = stack[stack.length-1]; 165 | action = table[`${state}`] && table[`${state}`][`${TERROR}`]; 166 | recovering = 3; // allow 3 real symbols to be shifted before reporting a new error 167 | } 168 | 169 | // this shouldn't happen, unless resolve defaults are off 170 | if (action[0] instanceof Array && action.length > 1) { 171 | throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); 172 | } 173 | 174 | switch (action[0]) { 175 | 176 | case 1: // shift 177 | //this.shiftCount++; 178 | 179 | stack.push(symbol); 180 | vstack.push(this.lexer.yytext); 181 | lstack.push(this.lexer.yylloc); 182 | stack.push(action[1]); // push state 183 | symbol = null; 184 | if (!preErrorSymbol) { // normal execution/no error 185 | yyleng = this.lexer.yyleng; 186 | yytext = this.lexer.yytext; 187 | yylineno = this.lexer.yylineno; 188 | yyloc = this.lexer.yylloc; 189 | if (recovering > 0) 190 | recovering--; 191 | } else { // error just occurred, resume old lookahead f/ before error 192 | symbol = preErrorSymbol; 193 | preErrorSymbol = null; 194 | } 195 | break; 196 | 197 | case 2: // reduce 198 | //this.reductionCount++; 199 | 200 | len = this.productions_[action[1]][1]; 201 | 202 | // perform semantic action 203 | yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 204 | // default location, uses first token for firsts, last for lasts 205 | yyval._$ = { 206 | first_line: lstack[lstack.length-(len||1)].first_line, 207 | last_line: lstack[lstack.length-1].last_line, 208 | first_column: lstack[lstack.length-(len||1)].first_column, 209 | last_column: lstack[lstack.length-1].last_column 210 | }; 211 | r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); 212 | 213 | if (typeof r !== 'undefined') { 214 | return r; 215 | } 216 | 217 | // pop off stack 218 | if (len) { 219 | stack = stack.slice(0,-1*len*2); 220 | vstack = vstack.slice(0, -1*len); 221 | lstack = lstack.slice(0, -1*len); 222 | } 223 | 224 | stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) 225 | vstack.push(yyval.$); 226 | lstack.push(yyval._$); 227 | // goto new state = table[`${state}`][NONTERMINAL] 228 | newState = table[stack[stack.length-2]][stack[stack.length-1]]; 229 | stack.push(newState); 230 | break; 231 | 232 | case 3: // accept 233 | return true; 234 | } 235 | 236 | } 237 | }}; 238 | /* Jison generated lexer */ 239 | parser.lexer = (function () { 240 | let lexer = ({ 241 | EOF: 1, 242 | parseError: function parseError(str, hash) { 243 | if (this.yy.parseError) { 244 | this.yy.parseError(str, hash); 245 | } else { 246 | throw new Error(str); 247 | } 248 | }, 249 | setInput: function (input) { 250 | this._input = input; 251 | this._more = this._less = this.done = false; 252 | this.yylineno = this.yyleng = 0; 253 | this.yytext = this.matched = this.match = ''; 254 | this.conditionStack = ['INITIAL']; 255 | this.yylloc = {first_line: 1, first_column: 0, last_line: 1, last_column: 0}; 256 | return this; 257 | }, 258 | input: function () { 259 | let ch = this._input[0]; 260 | this.yytext += ch; 261 | this.yyleng++; 262 | this.match += ch; 263 | this.matched += ch; 264 | let lines = ch.match(/\n/); 265 | if (lines) this.yylineno++; 266 | this._input = this._input.slice(1); 267 | return ch; 268 | }, 269 | unput: function (ch) { 270 | this._input = ch + this._input; 271 | return this; 272 | }, 273 | more: function () { 274 | this._more = true; 275 | return this; 276 | }, 277 | less: function (n) { 278 | this._input = this.match.slice(n) + this._input; 279 | }, 280 | pastInput: function () { 281 | let past = this.matched.substr(0, this.matched.length - this.match.length); 282 | return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); 283 | }, 284 | upcomingInput: function () { 285 | let next = this.match; 286 | if (next.length < 20) { 287 | next += this._input.substr(0, 20 - next.length); 288 | } 289 | return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); 290 | }, 291 | showPosition: function () { 292 | let pre = this.pastInput(); 293 | let c = new Array(pre.length + 1).join("-"); 294 | return pre + this.upcomingInput() + "\n" + c + "^"; 295 | }, 296 | next: function () { 297 | if (this.done) { 298 | return this.EOF; 299 | } 300 | if (!this._input) this.done = true; 301 | 302 | let token, 303 | match, 304 | tempMatch, 305 | index, 306 | col, 307 | lines; 308 | if (!this._more) { 309 | this.yytext = ''; 310 | this.match = ''; 311 | } 312 | let rules = this._currentRules(); 313 | for (let i = 0; i < rules.length; i++) { 314 | tempMatch = this._input.match(this.rules[`${rules[i]}`]); 315 | if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { 316 | match = tempMatch; 317 | index = i; 318 | if (!this.options.flex) break; 319 | } 320 | } 321 | if (match) { 322 | lines = match[0].match(/\n.*/g); 323 | if (lines) this.yylineno += lines.length; 324 | this.yylloc = { 325 | first_line: this.yylloc.last_line, 326 | last_line: this.yylineno + 1, 327 | first_column: this.yylloc.last_column, 328 | last_column: lines ? lines[lines.length - 1].length - 1 : this.yylloc.last_column + match[0].length 329 | } 330 | this.yytext += match[0]; 331 | this.match += match[0]; 332 | this.yyleng = this.yytext.length; 333 | this._more = false; 334 | this._input = this._input.slice(match[0].length); 335 | this.matched += match[0]; 336 | token = this.performAction.call(this, this.yy, this, rules[`${index}`], this.conditionStack[this.conditionStack.length - 1]); 337 | if (this.done && this._input) this.done = false; 338 | if (token) return token; 339 | else return; 340 | } 341 | if (this._input === "") { 342 | return this.EOF; 343 | } else { 344 | this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), 345 | {text: "", token: null, line: this.yylineno}); 346 | } 347 | }, 348 | lex: function lex() { 349 | let r = this.next(); 350 | if (typeof r !== 'undefined') { 351 | return r; 352 | } else { 353 | return this.lex(); 354 | } 355 | }, 356 | begin: function begin(condition) { 357 | this.conditionStack.push(condition); 358 | }, 359 | popState: function popState() { 360 | return this.conditionStack.pop(); 361 | }, 362 | _currentRules: function _currentRules() { 363 | return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; 364 | }, 365 | topState: function () { 366 | return this.conditionStack[this.conditionStack.length - 2]; 367 | }, 368 | pushState: function begin(condition) { 369 | this.begin(condition); 370 | } 371 | }); 372 | lexer.options = {}; 373 | lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) { 374 | 375 | let YYSTATE = YY_START 376 | switch ($avoiding_name_collisions) { 377 | case 0:/* skip whitespace */ 378 | break; 379 | case 1: 380 | return 6 381 | case 2: 382 | yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2); 383 | return 4 384 | case 3: 385 | return 17 386 | case 4: 387 | return 18 388 | case 5: 389 | return 23 390 | case 6: 391 | return 24 392 | case 7: 393 | return 22 394 | case 8: 395 | return 21 396 | case 9: 397 | return 10 398 | case 10: 399 | return 11 400 | case 11: 401 | return 8 402 | case 12: 403 | return 14 404 | case 13: 405 | return 'INVALID' 406 | } 407 | }; 408 | lexer.rules = [/^\s+/, 409 | /^-?(?!0\d)\d+\.?\d*([eE][+-]?)?\d*\b/, 410 | /^"(?:\\[\\"bfnrt\/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*"/,/^{/,/^}/,/^\[/,/^]/,/^,/,/^:/, 411 | /^true\b/,/^false\b/,/^null\b/,/^$/,/^./]; 412 | lexer.conditions = {"INITIAL": {"rules": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], "inclusive": true}}; 413 | 414 | return lexer; 415 | })(); 416 | return parser; 417 | })(); 418 | if (typeof require !== 'undefined' && typeof exports !== 'undefined') { 419 | exports.parser = jsonlint; 420 | exports.parse = jsonlint.parse.bind(jsonlint); 421 | } 422 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 HERE Europe B.V. 3 | * Licensed under MIT, see full license in LICENSE 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | import { resizerX } from './lib/resizer' 8 | import geojsonValidation from 'geojson-validation' 9 | import './style/style' 10 | import isEqual from 'lodash.isequal' 11 | import JSONFormatter from 'json-formatter-js' 12 | 13 | import { featureProvider } from './components/hereMap/hereMap' 14 | 15 | import { 16 | handleMultipleLocalFiles, 17 | multipleHttpGetAsync, 18 | getFeatureByURLParam, 19 | spaceLayer, 20 | spaceProvider, 21 | displayGeoJSON 22 | } from './components/loadData' 23 | 24 | import { 25 | isPosition, 26 | clearURLParam, 27 | resizeX, 28 | getLatLong, 29 | IsJsonString 30 | } from './components/common' 31 | 32 | import { editor, startValue } from './components/editor' 33 | import { alertBar } from './components/alertBar.js' 34 | import './components/eventHandling' 35 | import { GeoRect } from "@here/xyz-maps-core"; 36 | import { Selection } from 'monaco-editor' 37 | import * as monaco from "monaco-editor"; 38 | 39 | let HERE = window.HERE, 40 | isPrettyPrint = false, 41 | clickedFeatureStyles = [], 42 | clickedFeatures, 43 | multipleHighlightedFeaturesStyles = [], 44 | multipleHighlightedFeatures, 45 | featuresTobeHighlighted = [], 46 | zoomValue = 2, 47 | isDebug = false; 48 | 49 | window.onload = function () { 50 | let mapEl = document.getElementById("map"); 51 | document.querySelector('.zoom-info').innerHTML = display.getZoomlevel().toPrecision(2).toString(); 52 | 53 | mapEl.addEventListener("dragover", function (ev) { 54 | ev.stopPropagation(); 55 | ev.preventDefault(); 56 | ev.dataTransfer.dropEffect = 'copy'; 57 | }, false); 58 | 59 | mapEl.addEventListener("drop", function (ev) { 60 | ev.stopPropagation(); 61 | ev.preventDefault(); 62 | handleMultipleLocalFiles(ev.dataTransfer.files); 63 | }, false); 64 | 65 | display = initMap(); 66 | display.addEventListener('dbltap', function (ev) { 67 | display.setZoomlevel(display.getZoomlevel() + 1, ev.mapX, ev.mapY); 68 | document.querySelector('.zoom-info').innerHTML = display.getZoomlevel().toPrecision(2).toString(); 69 | }); 70 | 71 | // to change zoomlevel on map scroll zoom 72 | display.addEventListener('mapviewchangeend', function (ev) { 73 | document.querySelector('.zoom-info').innerHTML = display.getZoomlevel().toPrecision(2).toString(); 74 | }); 75 | 76 | // add helpful comment to compass 77 | document.querySelector('div[class$="-ui-needle"]').setAttribute('title', "To pitch and/or rotate, right click on map, and hold the mouse button while dragging the map.\nTo reset the map, click on the compass") 78 | document.querySelector('div[class$="-ui-compass"]').style.bottom = "105px"; 79 | document.querySelector('div[class$="-ui-compass"]').style.right = "12px"; 80 | 81 | //add popstate event 82 | window.addEventListener('popstate', function (ev) { 83 | getFeatureByURLParam(); 84 | }) 85 | 86 | document.getElementById("editor").ondrop = function (ev) { 87 | ev.stopPropagation(); 88 | ev.preventDefault(); 89 | let fileFromTextarea = new File([editor.getValue()], "temp.geojson", { type: "application/json" }); 90 | let filesToMerge = Array.from(ev.dataTransfer.files).concat(fileFromTextarea); 91 | handleMultipleLocalFiles(filesToMerge); 92 | }; 93 | 94 | document.getElementById("editor").ondragover = function (e) { 95 | e = e || event; 96 | e.preventDefault(); 97 | }; 98 | 99 | const model = editor.getModel(); 100 | 101 | editor.onDidChangeModelContent(() => { 102 | const value = model.getValue(); 103 | if (IsJsonString(value) && !isPrettyPrint) { 104 | displayGeoJSON(JSON.parse(value)); 105 | document.getElementById('changeFeatureColor').style["display"] = 'block'; 106 | } else { 107 | document.getElementById('changeFeatureColor').style["display"] = 'none'; 108 | } 109 | }); 110 | 111 | resizerX("sliderPan", function (e) { 112 | resizeX(e.pageX); 113 | display.resize(); 114 | }); 115 | 116 | getFeatureByURLParam(); 117 | } 118 | 119 | function initMap() { 120 | display.addEventListener('pointerup', function (ev) { 121 | 122 | let target = ev.target, 123 | refresh = false, 124 | data = {}; 125 | document.querySelector('#info').innerHTML = ""; 126 | 127 | if (target && target.properties && !target.properties.sort_rank) { 128 | let currentPtGeometryType = ev.target.geometry.type; 129 | data.geometry = {}; 130 | data.geometry.type = ev.target.geometry.type; 131 | if (target.properties) { 132 | data.properties = target.properties; 133 | } else { 134 | data.properties = {}; 135 | } 136 | let formatter = new JSONFormatter(data, 1, { 137 | theme: 'dark' 138 | }); 139 | 140 | document.querySelector('#info').appendChild(formatter.render()); 141 | formatter.openAtDepth(2); 142 | 143 | let counter, startLineNr, 144 | startLine, currentLine = ''; 145 | 146 | for (counter = 1; counter <= editor.getModel().getLineCount(); counter++) { 147 | startLine = editor.getModel().getLineContent(counter); 148 | if (startLine.indexOf('"geometry"') > -1 && !(startLine.indexOf('null') > -1)) { 149 | startLineNr = counter; 150 | let geometryObj = ''; 151 | 152 | while (currentLine.indexOf('}') < 0) { 153 | currentLine = editor.getModel().getLineContent(counter); 154 | if (currentLine.indexOf("properties") > -1 && counter > 0) { 155 | currentLine = currentLine.slice(0, currentLine.indexOf("properties") - 1); 156 | } 157 | geometryObj = geometryObj + currentLine; 158 | counter++; 159 | } if (!geometryObj.endsWith("}")) { 160 | geometryObj = geometryObj.slice(0, geometryObj.lastIndexOf("}") + 1); 161 | } 162 | if (currentPtGeometryType === "Polygon" || currentPtGeometryType === "MultiPolygon") { 163 | delete ev.target.geometry._xyz; 164 | } 165 | if (isEqual(JSON.parse('{' + geometryObj.split('{')[1]), ev.target.geometry)) { 166 | editor.setSelection(new Selection(startLineNr, 1, counter, editor.getModel().getLineLength(counter))); 167 | editor.revealLineInCenter(startLineNr, 0); 168 | } 169 | } 170 | currentLine = ''; 171 | } 172 | 173 | if (multipleHighlightedFeatures) { 174 | resetHighlightedFeaturesStyle(); 175 | } // To reset previously highlighted ref features. 176 | 177 | if (target.properties['association_ids'] && target.properties['association_ids'].length > 0) { 178 | featuresTobeHighlighted = []; 179 | target.properties['association_ids'].forEach(function (id) { 180 | featuresTobeHighlighted.push(featureProvider.getFeature(id)); 181 | }); 182 | highlightMultipleFeatures(featuresTobeHighlighted); 183 | } //To highlight associated features if clicked feature contains 'association_ids' property 184 | 185 | } else { 186 | resetHighlightedFeaturesStyle(); 187 | alertBar(0); 188 | } 189 | 190 | highlightSelectedFeatures(ev.target); 191 | 192 | if (target || refresh) { 193 | display.refresh(display.getLayers(1)); 194 | } 195 | }); 196 | window.addEventListener("resize", display.resize()); 197 | return display; 198 | } 199 | 200 | function highlightSelectedFeatures(selectedFeatures) { 201 | let layerKey = 1; 202 | if (!Array.isArray(selectedFeatures)) { 203 | selectedFeatures = [selectedFeatures]; 204 | } 205 | 206 | if (spaceLayer) { 207 | layerKey = 2; 208 | } 209 | 210 | for (let i = 0; clickedFeatures && (i < clickedFeatures.length); i++) { 211 | // Restore default feature style 212 | if (clickedFeatures[`${i}`]) display.getLayers()[`${layerKey}`].setStyleGroup(clickedFeatures[`${i}`], clickedFeatureStyles[`${i}`]); 213 | 214 | } 215 | 216 | if (selectedFeatures[0] && selectedFeatures[0].properties.sort_rank && selectedFeatures[0].properties.kind) { 217 | clickedFeatures = null; // if mvt layer is enabled. 218 | } else { 219 | clickedFeatures = selectedFeatures; 220 | } 221 | 222 | for (let j = 0; clickedFeatures && (j < clickedFeatures.length); j++) { 223 | if (clickedFeatures[`${j}`]) { 224 | clickedFeatureStyles[`${j}`] = display.getLayers()[`${layerKey}`].getStyleGroup(clickedFeatures[`${j}`]); 225 | 226 | // Set new feature style if mouse clicks on a feature 227 | display.getLayers()[`${layerKey}`].setStyleGroup(clickedFeatures[`${j}`], setHighlightedStyle(clickedFeatures, j)); 228 | } 229 | } 230 | } 231 | 232 | function highlightMultipleFeatures(selectedFeatures) { 233 | let layerKey = 1; 234 | 235 | if (!Array.isArray(selectedFeatures)) { 236 | selectedFeatures = [selectedFeatures]; 237 | } 238 | 239 | if (spaceLayer) { 240 | layerKey = 2; 241 | } 242 | 243 | if (selectedFeatures[0] && selectedFeatures[0].properties.sort_rank && selectedFeatures[0].properties.kind) { 244 | clickedFeatures = null; // if mvt layer is enabled. 245 | } else { 246 | multipleHighlightedFeatures = selectedFeatures; 247 | } 248 | 249 | for (let j = 0; multipleHighlightedFeatures && (j < multipleHighlightedFeatures.length); j++) { 250 | 251 | if (multipleHighlightedFeatures[`${j}`]) { 252 | multipleHighlightedFeaturesStyles[`${j}`] = display.getLayers()[`${layerKey}`].getStyleGroup(multipleHighlightedFeatures[`${j}`]); 253 | 254 | // Set new feature style if mouse clicks on a feature 255 | display.getLayers()[`${layerKey}`].setStyleGroup(multipleHighlightedFeatures[`${j}`], setHighlightedStyle(multipleHighlightedFeatures, j, '#3A7BDB')); 256 | } 257 | } 258 | } 259 | 260 | function resetHighlightedFeaturesStyle() { 261 | let layerKey = 1; 262 | 263 | if (spaceLayer) { 264 | layerKey = 2; 265 | } 266 | 267 | for (let i = 0; multipleHighlightedFeatures && (i < multipleHighlightedFeatures.length); i++) { 268 | // Restore default feature style 269 | if (multipleHighlightedFeatures[`${i}`]) display.getLayers()[`${layerKey}`].setStyleGroup(multipleHighlightedFeatures[`${i}`], multipleHighlightedFeaturesStyles[`${i}`]); 270 | } 271 | } 272 | 273 | function setHighlightedStyle(clickedFeatures, j, color) { 274 | let currentBearing = clickedFeatures[`${j}`].properties.vehicleBearing || clickedFeatures[`${j}`].properties.heading_deg, 275 | currentMarker = clickedFeatures[`${j}`].properties["marker-url"], 276 | currentMarkerText = clickedFeatures[`${j}`].properties["marker-text"], 277 | currentGeometryType = clickedFeatures[`${j}`].geometry.type, 278 | geometryType = currentGeometryType === "LineString" || currentGeometryType === "MultiLineString" ? "Line" : 279 | currentGeometryType === "Polygon" || currentGeometryType === "MultiPolygon" ? "Polygon" : 280 | currentGeometryType === "Point" || currentGeometryType === "MultiPoint" ? "Circle" : 281 | currentGeometryType; 282 | let customStyle = { 283 | zIndex: 1000, 284 | stroke: currentMarkerText ? '' : color ? color : "magenta", 285 | strokeWidth: 8, 286 | radius: 5, 287 | width: 32, 288 | height: 32, 289 | text: currentMarkerText, 290 | font: "normal 14px Arial", 291 | rotation: currentBearing, 292 | fill: function (feature) { 293 | if (currentMarkerText) { 294 | return color ? 'black' : "magenta"; 295 | } else { 296 | return geometryType === "Line" ? '' : color ? color : "magenta"; 297 | } 298 | }, 299 | type: currentBearing || currentMarker ? 'Image' : currentMarkerText ? 'Text' : geometryType, 300 | opacity: function (feature) { 301 | if (currentBearing || currentMarker) { 302 | return 0.6; 303 | } else if (feature.geometry.type.indexOf('Point') > -1 || feature.geometry.type.indexOf('LineString') > -1) { 304 | return 1; 305 | } else { 306 | return 0.3; 307 | } 308 | }, 309 | src: function (feature) { 310 | if (currentMarker) { 311 | return currentMarker; 312 | } else if (currentBearing) { 313 | return getDirectionImage('magenta'); 314 | } 315 | } 316 | }; 317 | 318 | if (currentMarkerText) { 319 | customStyle.zIndex = 4; 320 | } 321 | return customStyle; 322 | } 323 | 324 | function getgeoJSONByUrl() { 325 | if (document.querySelector('#geojson-url').value !== '') { 326 | clearURLParam(); 327 | multipleHttpGetAsync(document.querySelector('#geojson-url').value); 328 | } 329 | } 330 | 331 | function getGeojsonByUrlOrLatlong() { 332 | let geojsonUrlOrLatlong = document.querySelector('#geojson-url-or-latlong').value, 333 | isURL = geojsonUrlOrLatlong.includes('/'); 334 | if (geojsonUrlOrLatlong.substring(0, 4) === 'http' && isURL) { 335 | clearURLParam(); 336 | multipleHttpGetAsync(geojsonUrlOrLatlong); 337 | } else { 338 | let lat = parseFloat(geojsonUrlOrLatlong.split(",")[1]), 339 | long = parseFloat(geojsonUrlOrLatlong.split(",")[0]); 340 | if (!isNaN(lat) && !isNaN(long)) { 341 | getLatLong(long, lat); 342 | } 343 | } 344 | } 345 | 346 | document.querySelector('.getgeoJSONByUrl').addEventListener('click', function () { 347 | getgeoJSONByUrl(); 348 | }); 349 | 350 | document.querySelector('.latlongBtn').addEventListener('click', function () { 351 | getGeojsonByUrlOrLatlong(); 352 | }); 353 | 354 | 355 | editor.onDidChangeCursorSelection(() => { 356 | let featureFromProvider, 357 | selectedString = editor.getModel().getValueInRange(editor.getSelection()), 358 | isPositionInEditor = isPosition(selectedString); 359 | if (isPositionInEditor) { 360 | document.getElementById('info').innerHTML = ""; 361 | display.setCenter(isPositionInEditor); 362 | display.setZoomlevel(20); 363 | } else if (IsJsonString(selectedString)) { 364 | let feature = JSON.parse(selectedString); 365 | if (geojsonValidation.isFeature(feature)) { 366 | for (let key in featureProvider.IDPOOL) { 367 | featureFromProvider = featureProvider.IDPOOL[`${key}`].feature; 368 | if (isEqual(featureFromProvider.geometry, feature.geometry)) { 369 | let minLon = featureFromProvider.bbox[0], 370 | minLat = featureFromProvider.bbox[1], 371 | maxLon = featureFromProvider.bbox[2], 372 | maxLat = featureFromProvider.bbox[3]; 373 | highlightSelectedFeatures(featureFromProvider); 374 | display.setViewBounds( 375 | new GeoRect(minLon, minLat, maxLon, maxLat) 376 | ); 377 | } 378 | } 379 | } 380 | } else { 381 | highlightSelectedFeatures(featureFromProvider); 382 | } 383 | }) 384 | 385 | document.getElementById('geojsonFileInput').onclick = function () { 386 | this.value = null; 387 | }; 388 | 389 | document.getElementById('geojsonFileInput').onchange = function () { 390 | handleMultipleLocalFiles(document.querySelector('#geojsonFileInput').files); 391 | }; 392 | 393 | document.getElementById("geojson-url-or-latlong").addEventListener("keyup", function (event) { 394 | event.preventDefault(); 395 | if (event.keyCode === 13) { 396 | getGeojsonByUrlOrLatlong(); 397 | } 398 | }); 399 | 400 | document.querySelector('#geojson-url').addEventListener("keyup", function (event) { 401 | event.preventDefault(); 402 | if (event.keyCode === 13) { 403 | getgeoJSONByUrl(); 404 | } 405 | }); 406 | 407 | document.body.addEventListener('click', function (event) { 408 | let provider = featureProvider; 409 | if (event.target.className === 'json-formatter-key' && event.target.nextSibling.innerText) { 410 | let propertyValue, 411 | featureFromProvider, 412 | featureTobeHighlight = [], 413 | totalFeatureCountOnMap = 0, 414 | propertyLabel = event.target.innerText.replace(/:\s*$/, ''); 415 | 416 | if (event.target.nextSibling.className === 'json-formatter-boolean') { 417 | propertyValue = JSON.parse(event.target.nextSibling.innerText.replace(/['"]+/g, '')); // Converting string boolean value to boolean 418 | } else { 419 | propertyValue = event.target.nextSibling.innerText.replace(/['"]+/g, ''); 420 | } 421 | 422 | if (spaceProvider) { 423 | provider = spaceProvider; 424 | } 425 | 426 | for (let id in provider.IDPOOL) { 427 | featureFromProvider = provider.IDPOOL[`${id}`].feature; 428 | 429 | for (let key in featureFromProvider.properties) { 430 | 431 | if (key === propertyLabel) { 432 | 433 | if (featureFromProvider.properties[`${key}`] === propertyValue) { 434 | 435 | featureTobeHighlight.push(featureFromProvider); 436 | } 437 | } 438 | } 439 | totalFeatureCountOnMap++; 440 | } 441 | 442 | highlightSelectedFeatures(featureTobeHighlight); 443 | 444 | if (featureTobeHighlight.length > 0) { 445 | alertBar(1, 'success', 'Displaying ' + totalFeatureCountOnMap + ' feature(s), highlighting ' + featureTobeHighlight.length + ' feature(s) with ' + propertyLabel + ' : ' + propertyValue + ''); 446 | } else { 447 | alertBar(0); 448 | } 449 | } 450 | }); 451 | 452 | document.getElementById('showQuadkeys').addEventListener('click', function () { 453 | if (isDebug) { 454 | display.debug(false); 455 | isDebug = false; 456 | } else { 457 | display.debug(true); 458 | isDebug = true; 459 | } 460 | }); 461 | 462 | document.getElementById("darkMode").addEventListener('click', function () { 463 | if (this.title === "Dark Mode") { 464 | //dark mode 465 | monaco.editor.setTheme('vs-dark'); 466 | document.getElementById('LineDark').click(); 467 | document.getElementById('desktopNavigationBar').style.backgroundColor = "#1e1e1e"; 468 | document.getElementById('tab').style.backgroundColor = "#1e1e1e"; 469 | document.getElementById('panelWrapper').style.backgroundColor = "#1e1e1e"; 470 | document.getElementById('load-sample-wrapper').style.backgroundColor = "#1e1e1e"; 471 | document.getElementById('geojson-url').style.color = "#000"; 472 | for (let it of document.getElementsByClassName("button")) { 473 | it.style.color = "#fff" 474 | } 475 | document.getElementById('load-data-wrapper').style.color = "#fff"; 476 | document.getElementById('load-data-wrapper').style.backgroundColor = "#1e1e1e"; 477 | document.getElementById('editor-tab').style.background = 'url("images/dark/code.svg") no-repeat center'; 478 | document.getElementById('load-data-tab').style.background = 'url("images/dark/tool.svg") no-repeat center'; 479 | document.getElementById('load-sample-tab').style.background = 'url("images/dark/gift.svg") no-repeat center'; 480 | document.getElementById('copyToClipboard').style.background = 'url("images/dark/copy.svg") no-repeat center'; 481 | document.getElementById('clearContent').style.background = 'url("images/dark/trash-2.svg") no-repeat center'; 482 | document.getElementById('sliderPan').className = 'sliderPanDark'; 483 | this.style.background = 'url("images/dark/sun.svg") no-repeat center'; 484 | this.title = "Light Mode" 485 | } else { 486 | ///light mode 487 | monaco.editor.setTheme('vs'); 488 | document.getElementById('SpringSoft').click(); 489 | document.getElementById('desktopNavigationBar').style.backgroundColor = "#fff"; 490 | document.getElementById('tab').style.backgroundColor = "#fff"; 491 | document.getElementById('panelWrapper').style.backgroundColor = "#fff"; 492 | document.getElementById('load-sample-wrapper').style.backgroundColor = "#f5f4f4"; 493 | document.getElementById('load-data-wrapper').style.backgroundColor = "#f5f4f4"; 494 | document.getElementById('load-data-wrapper').style.color = "#000"; 495 | for (let it of document.getElementsByClassName("button")) { 496 | it.style.color = "#000" 497 | } 498 | document.getElementById('editor-tab').style.background = 'url("images/light/code.svg") no-repeat center'; 499 | document.getElementById('load-data-tab').style.background = 'url("images/light/tool.svg") no-repeat center'; 500 | document.getElementById('load-sample-tab').style.background = 'url("images/light/gift.svg") no-repeat center'; 501 | document.getElementById('copyToClipboard').style.background = 'url("images/light/copy.svg") no-repeat center'; 502 | document.getElementById('clearContent').style.background = 'url("images/light/trash-2.svg") no-repeat center'; 503 | document.getElementById('sliderPan').className = 'sliderPan'; 504 | this.style.background = 'url("images/light/moon.svg") no-repeat center'; 505 | this.title = "Dark Mode" 506 | } 507 | document.getElementById('editor').style.display = "block"; 508 | document.getElementById('editor').className = "tabLinks selected"; 509 | }) 510 | 511 | setTimeout(() => display.resize(), 0); 512 | -------------------------------------------------------------------------------- /src/components/themes/WithLabel/here/lines_white.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2017-2019 HERE Europe B.V. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | * License-Filename: LICENSE 19 | * 20 | * 21 | */ 22 | 23 | /* eslint-disable */ 24 | const light = { 25 | mainColors: ['#FFFFFF', '#000000'], 26 | 27 | backgroundColor: '#FFFFFF', 28 | 29 | strokeWidthZoomScale: function(level) { 30 | return level > 17 ? 1 : level > 14 ? 0.5 : 0.25; 31 | }, 32 | 33 | styleGroups: { 34 | waterArea: [ 35 | { 36 | zIndex: 7, 37 | type: 'Polygon', 38 | fill: '#F2F2F2', 39 | }, 40 | ], 41 | 42 | riverLines: [ 43 | { 44 | zIndex: 7, 45 | type: 'Line', 46 | strokeWidth: 1, 47 | stroke: '#F2F2F2', 48 | }, 49 | ], 50 | 51 | riverLinesLabels: [ 52 | { 53 | zIndex: 7, 54 | type: 'Line', 55 | strokeWidth: 1, 56 | stroke: '#F2F2F2', 57 | }, 58 | { 59 | zLevel: 2, 60 | type: 'Text', 61 | font: 'italic 10px "OpenSans", sans-serif', 62 | text: f => f.properties.name, 63 | strokeWidth: 3, 64 | // stroke: '#707070', 65 | fill: '#B5B5B5', 66 | collide: false, 67 | }, 68 | ], 69 | 70 | oceanLabels: [ 71 | { 72 | zLevel: 2, 73 | type: 'Text', 74 | font: '10px "OpenSans", sans-serif', 75 | text: f => f.properties.name, 76 | text: f => f.properties['name:en'], 77 | text: feature => feature.properties.name.toUpperCase(), 78 | strokeWidth: 3, 79 | // stroke: '#707070', 80 | fill: '#B5B5B5', 81 | collide: false, 82 | }, 83 | ], 84 | 85 | bayLabels: [ 86 | { 87 | zLevel: 2, 88 | type: 'Text', 89 | font: 'italic 10px "OpenSans", sans-serif', 90 | text: f => f.properties.name, 91 | strokeWidth: 3, 92 | // stroke: '#707070', 93 | fill: '#807F7F', 94 | collide: false, 95 | }, 96 | ], 97 | 98 | lakeLabels: [ 99 | { 100 | zLevel: 2, 101 | type: 'Text', 102 | font: 'italic 10px "OpenSans", sans-serif', 103 | text: f => f.properties.name, 104 | strokeWidth: 3, 105 | // stroke: '#707070', 106 | fill: '#807F7F', 107 | collide: false, 108 | }, 109 | ], 110 | 111 | earth: [ 112 | { 113 | zIndex: 1, 114 | type: 'Polygon', 115 | fill: '#FFFFFF', 116 | }, 117 | ], 118 | 119 | countryBoundary: [ 120 | { 121 | zIndex: 11, 122 | type: 'Line', 123 | strokeWidth: 4, 124 | stroke: '#E6E6E6', 125 | }, 126 | ], 127 | 128 | countryBoundaryZ5: [ 129 | { 130 | zIndex: 11, 131 | type: 'Line', 132 | strokeWidth: 5, 133 | stroke: '#E6E6E6', 134 | }, 135 | ], 136 | 137 | countryBoundaryZ8: [ 138 | { 139 | zIndex: 11, 140 | type: 'Line', 141 | strokeWidth: 14, 142 | stroke: '#E6E6E6', 143 | }, 144 | ], 145 | 146 | dashed_boundary: [ 147 | { 148 | zIndex: 11, 149 | type: 'Line', 150 | strokeWidth: 5, 151 | stroke: '#E6E6E6', 152 | strokeDasharray: [3, 4], 153 | }, 154 | ], 155 | 156 | regionBoundary: [ 157 | { 158 | zIndex: 9, 159 | type: 'Line', 160 | strokeWidth: 3, 161 | stroke: '#E6E6E6', 162 | opacity: 0.75, 163 | }, 164 | ], 165 | 166 | runway: [ 167 | { 168 | zIndex: 6, 169 | type: 'Polygon', 170 | fill: '#E6E5E5', 171 | }, 172 | ], 173 | 174 | airportLabels: [ 175 | { 176 | zLevel: 2, 177 | type: 'Text', 178 | font: 'bold 11px "OpenSans", sans-serif', 179 | text: f => f.properties.name, 180 | strokeWidth: 3, 181 | // stroke: '#393939', 182 | fill: '#212121', 183 | collide: false, 184 | }, 185 | ], 186 | 187 | motorway: [ 188 | { 189 | zIndex: 27, 190 | type: 'Line', 191 | strokeWidth: 2, 192 | stroke: '#404040', 193 | }, 194 | ], 195 | 196 | motorwayZ13: [ 197 | { 198 | zIndex: 27, 199 | type: 'Line', 200 | strokeWidth: 4, 201 | stroke: '#000000', 202 | }, 203 | ], 204 | 205 | trunkRoads: [ 206 | { 207 | zIndex: 25, 208 | type: 'Line', 209 | strokeWidth: 2, 210 | stroke: '#404040', 211 | }, 212 | ], 213 | 214 | trunkRoadsZ13: [ 215 | { 216 | zIndex: 25, 217 | type: 'Line', 218 | strokeWidth: 4, 219 | stroke: '#000000', 220 | }, 221 | ], 222 | 223 | primaryRoads: [ 224 | { 225 | zIndex: 23, 226 | type: 'Line', 227 | strokeWidth: 2, 228 | stroke: '#757575', 229 | }, 230 | ], 231 | 232 | primaryRoadsZ16: [ 233 | { 234 | zIndex: 23, 235 | type: 'Line', 236 | strokeWidth: 3, 237 | stroke: '#333333', 238 | }, 239 | ], 240 | 241 | secondaryRoads: [ 242 | { 243 | zIndex: 21, 244 | type: 'Line', 245 | strokeWidth: 2, 246 | stroke: '#757575', 247 | }, 248 | ], 249 | 250 | secondaryRoadsZ16: [ 251 | { 252 | zIndex: 21, 253 | type: 'Line', 254 | strokeWidth: 3, 255 | stroke: '#404040', 256 | }, 257 | ], 258 | 259 | highway: [ 260 | { 261 | zIndex: 29, 262 | type: 'Line', 263 | strokeWidth: 2, 264 | stroke: '#757575', 265 | }, 266 | ], 267 | 268 | highwayZ16: [ 269 | { 270 | zIndex: 29, 271 | type: 'Line', 272 | strokeWidth: 3, 273 | stroke: '#333333', 274 | }, 275 | ], 276 | 277 | tertiaryRoads: [ 278 | { 279 | zIndex: 19, 280 | type: 'Line', 281 | strokeWidth: 2, 282 | stroke: '#A6A6A6', 283 | }, 284 | ], 285 | 286 | tertiaryRoadsZ16: [ 287 | { 288 | zIndex: 19, 289 | type: 'Line', 290 | strokeWidth: 3, 291 | stroke: '#9E9E9E', 292 | }, 293 | ], 294 | 295 | minorRoads: [ 296 | { 297 | zIndex: 17, 298 | type: 'Line', 299 | strokeWidth: 1, 300 | stroke: '#A6A6A6', 301 | }, 302 | ], 303 | 304 | minorRoadsZ16: [ 305 | { 306 | zIndex: 17, 307 | type: 'Line', 308 | strokeWidth: 2, 309 | stroke: '#9E9E9E', 310 | }, 311 | ], 312 | 313 | pathRoads: [ 314 | { 315 | zIndex: 15, 316 | type: 'Line', 317 | strokeWidth: 2, 318 | stroke: '#737373', 319 | strokeDasharray: [1, 3], 320 | }, 321 | ], 322 | 323 | pathRoadsZ18: [ 324 | { 325 | zIndex: 15, 326 | type: 'Line', 327 | strokeWidth: 2, 328 | stroke: '#9E9E9E', 329 | strokeDasharray: [2, 4], 330 | }, 331 | ], 332 | 333 | buildings: [ 334 | { zIndex: 31, type: 'Line', strokeWidth: 3, stroke: '#D9D9D9' }, 335 | { zIndex: 32, type: 'Polygon', fill: '#FFFFFF' }, 336 | ], 337 | 338 | countryL: [ 339 | { 340 | zLevel: 2, 341 | type: 'Text', 342 | text: f => f.properties['name:en'], 343 | text: feature => feature.properties.name.toUpperCase(), 344 | stroke: '#FFFFFF', 345 | fill: '#A6A6A6', 346 | font: 'bold 13px "OpenSans", sans-serif', 347 | strokeWidth: 4, 348 | collide: false, 349 | }, 350 | ], 351 | 352 | countryS: [ 353 | { 354 | zLevel: 2, 355 | type: 'Text', 356 | text: f => f.properties['name:en'], 357 | text: feature => feature.properties.name.toUpperCase(), 358 | stroke: '#FFFFFF', 359 | fill: '#A6A6A6', 360 | font: 'bold 9px "OpenSans", sans-serif', 361 | strokeWidth: 4, 362 | collide: false, 363 | }, 364 | ], 365 | 366 | region: [ 367 | { 368 | zLevel: 2, 369 | type: 'Text', 370 | text: f => f.properties['name:en'], 371 | stroke: '#FFFFFF', 372 | fill: '#B8B8B8', 373 | font: 'bold 13px "OpenSans", sans-serif', 374 | strokeWidth: 3, 375 | collide: false, 376 | }, 377 | ], 378 | 379 | capitalXL: [ 380 | { 381 | zLevel: 2, 382 | type: 'Text', 383 | text: f => f.properties['name:en'], 384 | stroke: '#FFFFFF', 385 | fill: '#000000', 386 | // fill: '#0000ff', 387 | font: 'bold 16px "OpenSans", sans-serif', 388 | strokeWidth: 4, 389 | collide: false, 390 | }, 391 | ], 392 | 393 | capitalL: [ 394 | { 395 | zLevel: 2, 396 | type: 'Text', 397 | text: f => f.properties['name:en'], 398 | stroke: '#FFFFFF', 399 | fill: '#000000', 400 | // fill: '#0000ff', 401 | font: 'bold 14px "OpenSans", sans-serif', 402 | strokeWidth: 4, 403 | collide: false, 404 | }, 405 | ], 406 | 407 | capitalM: [ 408 | { 409 | zLevel: 2, 410 | type: 'Text', 411 | text: f => f.properties['name:en'], 412 | stroke: '#FFFFFF', 413 | fill: '#000000', 414 | // fill: '#0000ff', 415 | font: 'bold 12px "OpenSans", sans-serif', 416 | strokeWidth: 4, 417 | collide: false, 418 | }, 419 | ], 420 | 421 | capitalS: [ 422 | { 423 | zLevel: 2, 424 | type: 'Text', 425 | text: f => f.properties['name:en'], 426 | stroke: '#FFFFFF', 427 | fill: '#000000', 428 | // fill: '#0000ff', 429 | font: 'bold 10px "OpenSans", sans-serif', 430 | strokeWidth: 3, 431 | collide: false, 432 | }, 433 | ], 434 | 435 | population10m: [ 436 | { 437 | zLevel: 2, 438 | type: 'Text', 439 | text: f => f.properties['name:en'], 440 | stroke: '#FFFFFF', 441 | fill: '#000000', 442 | // fill: '#ffff00', 443 | font: '16px "OpenSans", sans-serif', 444 | strokeWidth: 4, 445 | collide: false, 446 | }, 447 | ], 448 | 449 | population10mLarge: [ 450 | { 451 | zLevel: 2, 452 | type: 'Text', 453 | text: f => f.properties['name:en'], 454 | stroke: '#FFFFFF', 455 | fill: '#000000', 456 | // fill: '#ffff00', 457 | font: '18px "OpenSans", sans-serif', 458 | strokeWidth: 4, 459 | collide: false, 460 | }, 461 | ], 462 | 463 | population5m10m: [ 464 | { 465 | zLevel: 2, 466 | type: 'Text', 467 | text: f => f.properties['name:en'], 468 | stroke: '#FFFFFF', 469 | fill: '#000000', 470 | // fill: '#ffff00', 471 | font: '14px "OpenSans", sans-serif', 472 | strokeWidth: 4, 473 | collide: false, 474 | }, 475 | ], 476 | 477 | population5m10mLarge: [ 478 | { 479 | zLevel: 2, 480 | type: 'Text', 481 | text: f => f.properties['name:en'], 482 | stroke: '#FFFFFF', 483 | fill: '#000000', 484 | // fill: '#ffff00', 485 | font: '17px "OpenSans", sans-serif', 486 | strokeWidth: 4, 487 | collide: false, 488 | }, 489 | ], 490 | 491 | population1m5m: [ 492 | { 493 | zLevel: 2, 494 | type: 'Text', 495 | text: f => f.properties['name:en'], 496 | stroke: '#FFFFFF', 497 | fill: '#000000', 498 | // fill: '#ffff00', 499 | font: '13px "OpenSans", sans-serif', 500 | strokeWidth: 4, 501 | collide: false, 502 | }, 503 | ], 504 | 505 | population1m5mLarge: [ 506 | { 507 | zLevel: 2, 508 | type: 'Text', 509 | text: f => f.properties['name:en'], 510 | stroke: '#FFFFFF', 511 | fill: '#000000', 512 | // fill: '#ffff00', 513 | font: '16px "OpenSans", sans-serif', 514 | strokeWidth: 4, 515 | collide: false, 516 | }, 517 | ], 518 | 519 | population500k1m: [ 520 | { 521 | zLevel: 2, 522 | type: 'Text', 523 | text: f => f.properties['name:en'], 524 | stroke: '#FFFFFF', 525 | // fill: '#ff0000', 526 | fill: '#121212', 527 | font: '12px "OpenSans", sans-serif', 528 | strokeWidth: 4, 529 | collide: false, 530 | }, 531 | ], 532 | 533 | population500k1mLarge: [ 534 | { 535 | zLevel: 2, 536 | type: 'Text', 537 | text: f => f.properties['name:en'], 538 | stroke: '#FFFFFF', 539 | // fill: '#ff0000', 540 | fill: '#121212', 541 | font: '15px "OpenSans", sans-serif', 542 | strokeWidth: 4, 543 | collide: false, 544 | }, 545 | ], 546 | 547 | population200k500k: [ 548 | { 549 | zLevel: 2, 550 | type: 'Text', 551 | text: f => f.properties['name:en'], 552 | stroke: '#FFFFFF', 553 | // fill: '#ff0000', 554 | fill: '#121212', 555 | font: '12px "OpenSans", sans-serif', 556 | strokeWidth: 4, 557 | collide: false, 558 | }, 559 | ], 560 | 561 | population200k500kLarge: [ 562 | { 563 | zLevel: 2, 564 | type: 'Text', 565 | text: f => f.properties['name:en'], 566 | stroke: '#FFFFFF', 567 | // fill: '#ff0000', 568 | fill: '#121212', 569 | font: '15px "OpenSans", sans-serif', 570 | strokeWidth: 4, 571 | collide: false, 572 | }, 573 | ], 574 | 575 | population100k200k: [ 576 | { 577 | zLevel: 2, 578 | type: 'Text', 579 | text: f => f.properties['name:en'], 580 | stroke: '#FFFFFF', 581 | // fill: '#ff0000', 582 | fill: '#1C1C1C', 583 | font: '12px "OpenSans", sans-serif', 584 | strokeWidth: 4, 585 | collide: false, 586 | }, 587 | ], 588 | 589 | population100k200kLarge: [ 590 | { 591 | zLevel: 2, 592 | type: 'Text', 593 | text: f => f.properties['name:en'], 594 | stroke: '#FFFFFF', 595 | // fill: '#ff0000', 596 | fill: '#1C1C1C', 597 | font: '14px "OpenSans", sans-serif', 598 | strokeWidth: 4, 599 | collide: false, 600 | }, 601 | ], 602 | 603 | population50k100k: [ 604 | { 605 | zLevel: 2, 606 | type: 'Text', 607 | text: f => f.properties['name:en'], 608 | stroke: '#FFFFFF', 609 | // fill: '#ff0000', 610 | fill: '#1C1C1C', 611 | font: '12px "OpenSans", sans-serif', 612 | strokeWidth: 4, 613 | collide: false, 614 | }, 615 | ], 616 | 617 | population50k100kLarge: [ 618 | { 619 | zLevel: 2, 620 | type: 'Text', 621 | text: f => f.properties['name:en'], 622 | stroke: '#FFFFFF', 623 | // fill: '#ff0000', 624 | fill: '#1C1C1C', 625 | font: '14px "OpenSans", sans-serif', 626 | strokeWidth: 4, 627 | collide: false, 628 | }, 629 | ], 630 | 631 | population20k50k: [ 632 | { 633 | zLevel: 2, 634 | type: 'Text', 635 | text: f => f.properties['name:en'], 636 | stroke: '#FFFFFF', 637 | // fill: '#ff0000', 638 | fill: '#1C1C1C', 639 | font: '12px "OpenSans", sans-serif', 640 | strokeWidth: 4, 641 | collide: false, 642 | }, 643 | ], 644 | 645 | population10k20k: [ 646 | { 647 | zLevel: 2, 648 | type: 'Text', 649 | text: f => f.properties['name:en'], 650 | stroke: '#FFFFFF', 651 | // fill: '#ff0000', 652 | fill: '#1C1C1C', 653 | font: '11px "OpenSans", sans-serif', 654 | strokeWidth: 4, 655 | collide: false, 656 | }, 657 | ], 658 | 659 | population5k10k: [ 660 | { 661 | zLevel: 2, 662 | type: 'Text', 663 | text: f => f.properties['name:en'], 664 | stroke: '#FFFFFF', 665 | // fill: '#D4D4D4', 666 | fill: '#1C1C1C', 667 | font: '11px "OpenSans", sans-serif', 668 | strokeWidth: 4, 669 | collide: false, 670 | }, 671 | ], 672 | 673 | population1k5k: [ 674 | { 675 | zLevel: 2, 676 | type: 'Text', 677 | text: f => f.properties['name:en'], 678 | stroke: '#FFFFFF', 679 | // fill: '#D4D4D4', 680 | fill: '#1C1C1C', 681 | font: '11px "OpenSans", sans-serif', 682 | strokeWidth: 4, 683 | collide: false, 684 | }, 685 | ], 686 | 687 | neighbourhoodS: [ 688 | { 689 | zLevel: 2, 690 | type: 'Text', 691 | text: f => f.properties['name:en'], 692 | text: feature => feature.properties.name.toUpperCase(), 693 | stroke: '#FFFFFF', 694 | // fill: '#D4D4D4', 695 | fill: '#666666', 696 | font: '11px "OpenSans", sans-serif', 697 | strokeWidth: 3, 698 | collide: false, 699 | }, 700 | ], 701 | 702 | neighbourhoodL: [ 703 | { 704 | zLevel: 2, 705 | type: 'Text', 706 | text: f => f.properties['name:en'], 707 | text: feature => feature.properties.name.toUpperCase(), 708 | stroke: '#FFFFFF', 709 | // fill: '#D4D4D4', 710 | fill: '#666666', 711 | font: '13px "OpenSans", sans-serif', 712 | strokeWidth: 4, 713 | collide: false, 714 | }, 715 | ], 716 | }, 717 | 718 | assign: function(feature, level) { 719 | var props = feature.properties; 720 | var kind = props.kind; 721 | var layer = props.layer; 722 | var geom = feature.geometry.type; 723 | 724 | if (layer === 'water') { 725 | if (kind === 'river') { 726 | if (level >= 12) { 727 | return 'riverLinesLabels'; 728 | } 729 | return 'riverLines'; 730 | } 731 | 732 | if (geom === 'LineString' || geom === 'MultiLineString') { 733 | return; 734 | } 735 | 736 | if (kind === 'oceans') { 737 | if (feature.properties.min_zoom <= 6) { 738 | return 'oceanLabels'; 739 | } 740 | if (feature.properties.min_zoom === 7) { 741 | if (level >= 6) { 742 | return 'oceanLabels'; 743 | } 744 | } 745 | if (feature.properties.min_zoom >= 8) { 746 | if (level >= 9) { 747 | return 'oceanLabels'; 748 | } 749 | } 750 | } 751 | if (kind === 'bay') { 752 | if (feature.properties.min_zoom <= 9) { 753 | return 'bayLabels'; 754 | } 755 | if (feature.properties.min_zoom >= 10) { 756 | if (level >= 11) { 757 | return 'bayLabels'; 758 | } 759 | } 760 | } 761 | if (kind === 'lake') { 762 | if (feature.properties.min_zoom <= 9) { 763 | return 'lakeLabels'; 764 | } 765 | if (feature.properties.min_zoom >= 10) { 766 | if (level >= 13) { 767 | return 'lakeLabels'; 768 | } 769 | } 770 | } 771 | return 'waterArea'; 772 | } 773 | 774 | if (layer === 'boundaries') { 775 | if (kind === 'country') { 776 | if (level >= 8) { 777 | return 'countryBoundaryZ8'; 778 | } 779 | if (level >= 5) { 780 | return 'countryBoundaryZ5'; 781 | } 782 | if (level >= 1) { 783 | return 'countryBoundary'; 784 | } 785 | } 786 | 787 | if (kind === 'disputed') { 788 | return 'dashed_boundary'; 789 | } 790 | 791 | if (kind === 'region') { 792 | if (level >= 5) { 793 | return 'regionBoundary'; 794 | } 795 | } 796 | } 797 | 798 | if (layer === 'landuse') { 799 | if (kind === 'runway') { 800 | return 'runway'; 801 | } 802 | } 803 | 804 | if (layer === 'pois') { 805 | if (kind === 'airport') { 806 | if (level >= 15) { 807 | return 'airportLabels'; 808 | } 809 | } 810 | } 811 | 812 | if (layer === 'roads') { 813 | if (kind === 'rail' || kind === 'ferry') { 814 | return; 815 | } 816 | if (feature.properties.kind_detail === 'motorway') { 817 | if (level >= 13) { 818 | return 'motorwayZ13'; 819 | } 820 | return 'motorway'; 821 | } 822 | if (feature.properties.kind_detail === 'trunk') { 823 | if (level >= 13) { 824 | return 'trunkRoadsZ13'; 825 | } 826 | return 'trunkRoads'; 827 | } 828 | if (feature.properties.kind === 'highway') { 829 | if (level >= 16) { 830 | return 'highwayZ16'; 831 | } 832 | return 'highway'; 833 | } 834 | if (feature.properties.kind_detail === 'primary') { 835 | if (level >= 16) { 836 | return 'primaryRoadsZ16'; 837 | } 838 | return 'primaryRoads'; 839 | } 840 | if (feature.properties.kind_detail === 'secondary') { 841 | if (level >= 16) { 842 | return 'secondaryRoadsZ16'; 843 | } 844 | return 'secondaryRoads'; 845 | } 846 | if (feature.properties.kind_detail === 'tertiary') { 847 | if (level >= 16) { 848 | return 'tertiaryRoadsZ16'; 849 | } 850 | return 'tertiaryRoads'; 851 | } 852 | if (feature.properties.kind === 'minor_road') { 853 | if (level >= 16) { 854 | return 'minorRoadsZ16'; 855 | } 856 | return 'minorRoads'; 857 | } 858 | if (feature.properties.kind === 'path') { 859 | if (level >= 18) { 860 | return 'pathRoadsZ18'; 861 | } 862 | if (level >= 14) { 863 | return 'pathRoads'; 864 | } 865 | } 866 | } 867 | 868 | if (layer === 'buildings') { 869 | if (level >= 17) { 870 | return 'buildings'; 871 | } 872 | } 873 | 874 | if (layer === 'places') { 875 | if (kind === 'country') { 876 | if (level >= 5) { 877 | return 'countryL'; 878 | } 879 | if (level >= 2) { 880 | return 'countryS'; 881 | } 882 | } 883 | 884 | if (kind === 'region') { 885 | if (level > 5) { 886 | return 'region'; 887 | } 888 | } 889 | 890 | if (kind === 'locality') { 891 | if (props.population >= 10000000) { 892 | if (level >= 9) { 893 | return 'population10mLarge'; 894 | } 895 | if (level >= 4) { 896 | if (props.country_capital === true) { 897 | return 'capitalXL'; 898 | } 899 | return 'population10m'; 900 | } 901 | } 902 | 903 | if (props.population >= 5000000 && props.population < 10000000) { 904 | if (level >= 9) { 905 | return 'population5m10mLarge'; 906 | } 907 | if (level >= 4) { 908 | if (props.country_capital === true) { 909 | return 'capitalL'; 910 | } 911 | return 'population5m10m'; 912 | } 913 | } 914 | 915 | if (props.population >= 1000000 && props.population < 5000000) { 916 | if (level >= 10) { 917 | return 'population1m5mLarge'; 918 | } 919 | if (level >= 4) { 920 | if (props.country_capital === true) { 921 | return 'capitalL'; 922 | } 923 | return 'population1m5m'; 924 | } 925 | } 926 | 927 | if (props.population >= 500000 && props.population < 1000000) { 928 | if (level >= 11) { 929 | return 'population500k1mLarge'; 930 | } 931 | if (level >= 5) { 932 | if (props.country_capital === true) { 933 | return 'capitalM'; 934 | } 935 | return 'population500k1m'; 936 | } 937 | } 938 | 939 | if (props.population >= 200000 && props.population < 500000) { 940 | if (level >= 12) { 941 | return 'population200k500kLarge'; 942 | } 943 | if (level >= 6) { 944 | if (props.country_capital === true) { 945 | return 'capitalM'; 946 | } 947 | return 'population200k500k'; 948 | } 949 | } 950 | 951 | if (props.population >= 100000 && props.population < 200000) { 952 | if (level >= 12) { 953 | return 'population100k200kLarge'; 954 | } 955 | if (level >= 6) { 956 | if (props.country_capital === true) { 957 | return 'capitalS'; 958 | } 959 | return 'population100k200k'; 960 | } 961 | } 962 | 963 | if (props.population >= 50000 && props.population < 100000) { 964 | if (level >= 12) { 965 | return 'population50k100kLarge'; 966 | } 967 | if (level >= 6) { 968 | if (props.country_capital === true) { 969 | return 'capitalS'; 970 | } 971 | return 'population50k100k'; 972 | } 973 | } 974 | 975 | if (props.population >= 20000 && props.population < 50000) { 976 | if (level >= 9) { 977 | if (props.country_capital === true) { 978 | return 'capitalS'; 979 | } 980 | return 'population20k50k'; 981 | } 982 | } 983 | 984 | if (props.population >= 10000 && props.population < 20000) { 985 | if (level >= 10) { 986 | return 'population10k20k'; 987 | } 988 | } 989 | 990 | if (props.population >= 5000 && props.population < 10000) { 991 | if (level >= 11) { 992 | return 'population5k10k'; 993 | } 994 | } 995 | 996 | if (props.population >= 1000 && props.population < 5000) { 997 | if (level >= 12) { 998 | return 'population2k5k'; 999 | } 1000 | } 1001 | } 1002 | 1003 | if (kind === 'neighbourhood') { 1004 | if (level >= 15) { 1005 | return 'neighbourhoodL'; 1006 | } 1007 | if (level >= 13) { 1008 | return 'neighbourhoodS'; 1009 | } 1010 | } 1011 | } 1012 | }, 1013 | }; 1014 | 1015 | export default light; 1016 | --------------------------------------------------------------------------------