├── .editorconfig ├── .eslintrc.cjs ├── .gitignore ├── .jshintrc ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── babel.config.js ├── build ├── bundle.mjs └── intro.js ├── circle.yml ├── demos ├── app │ ├── gui.js │ ├── key.js │ ├── rStats.js │ └── url.js ├── css │ └── main.css ├── data │ └── school-districts-polygon.geojson ├── fonts │ └── montserrat.woff ├── images │ ├── LitSphere_test_02.jpg │ ├── matball01.jpg │ ├── pois.png │ ├── sunset.jpg │ └── wheel.png ├── lib │ ├── FileSaver.js │ ├── dat.gui.min.js │ ├── keymaster.js │ ├── rStats.css │ ├── rStats.extras.js │ └── rStats.js ├── main.js ├── scene.yaml └── styles │ ├── crosshatch.zip │ ├── dots.yaml │ ├── halftone.yaml │ ├── popup.yaml │ ├── rainbow.yaml │ ├── water.yaml │ └── wood.yaml ├── dist ├── tangram.debug.js ├── tangram.debug.js.map ├── tangram.debug.mjs ├── tangram.debug.mjs.map ├── tangram.min.js └── tangram.min.mjs ├── index.html ├── karma.conf.js ├── package-lock.json ├── package.json ├── rollup.config.mjs ├── src ├── builders │ ├── common.js │ ├── points.js │ ├── polygons.js │ ├── polylines.js │ └── wireframe.js ├── gl │ ├── constants.js │ ├── context.js │ ├── extensions.js │ ├── glsl.js │ ├── render_state.js │ ├── shader_program.js │ ├── texture.js │ ├── vao.js │ ├── vbo_mesh.js │ ├── vertex_data.js │ ├── vertex_elements.js │ └── vertex_layout.js ├── index.js ├── labels │ ├── collision.js │ ├── collision_grid.js │ ├── intersect.js │ ├── label.js │ ├── label_line.js │ ├── label_point.js │ ├── main_pass.js │ ├── point_anchor.js │ ├── point_placement.js │ └── repeat_group.js ├── leaflet_layer.js ├── lights │ ├── ambient_light.glsl │ ├── directional_light.glsl │ ├── light.js │ ├── material.glsl │ ├── material.js │ ├── point_light.glsl │ └── spot_light.glsl ├── scene │ ├── camera.js │ ├── globals.js │ ├── scene.js │ ├── scene_bundle.js │ ├── scene_debug.js │ ├── scene_loader.js │ ├── scene_worker.js │ └── view.js ├── selection │ ├── selection.js │ ├── selection_fragment.glsl │ ├── selection_globals.glsl │ └── selection_vertex.glsl ├── sources │ ├── data_source.js │ ├── geojson.js │ ├── mvt.js │ ├── raster.js │ ├── sources.js │ └── topojson.js ├── styles │ ├── filter.js │ ├── layer.js │ ├── lines │ │ ├── dasharray.js │ │ └── lines.js │ ├── points │ │ ├── points.js │ │ ├── points_fragment.glsl │ │ └── points_vertex.glsl │ ├── polygons │ │ ├── polygons.js │ │ ├── polygons_fragment.glsl │ │ └── polygons_vertex.glsl │ ├── raster │ │ ├── raster.js │ │ └── raster_globals.glsl │ ├── style.js │ ├── style_globals.glsl │ ├── style_manager.js │ ├── style_parser.js │ └── text │ │ ├── font_manager.js │ │ ├── text.js │ │ ├── text_canvas.js │ │ ├── text_labels.js │ │ ├── text_segments.js │ │ ├── text_settings.js │ │ └── text_wrap.js ├── tile │ ├── tile.js │ ├── tile_id.js │ ├── tile_manager.js │ └── tile_pyramid.js └── utils │ ├── debounce.js │ ├── debug_settings.js │ ├── errors.js │ ├── functions.js │ ├── geo.js │ ├── gl-matrix.js │ ├── hash.js │ ├── log.js │ ├── media_capture.js │ ├── merge.js │ ├── obb.js │ ├── props.js │ ├── slice.js │ ├── subscribe.js │ ├── task.js │ ├── thread.js │ ├── urls.js │ ├── utils.js │ ├── vector.js │ ├── version.js │ └── worker_broker.js └── test ├── data_source_spec.js ├── fixtures ├── sample-json-response.json ├── sample-layers.json ├── sample-scene.json ├── sample-scene.yaml ├── sample-tile.json ├── sample-topojson-response.json └── simple-polygon.json ├── geo_spec.js ├── helpers.js ├── layer_spec.js ├── leaflet_layer_spec.js ├── merge_spec.js ├── obb_spec.js ├── rollup.config.worker.js ├── scene_spec.js ├── style_spec.js ├── subscribe_spec.js ├── tile_manager_spec.js ├── tile_pyramid.js ├── tile_spec.js ├── vertex_data_spec.js └── vertex_layout_spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [{Makefile,makefile}] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "worker": true, 5 | "es6": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "ecmaVersion": 2020, 10 | "sourceType": "module" 11 | }, 12 | "rules": { 13 | "indent": ["error", 4 ], 14 | "linebreak-style": ["error", "unix"], 15 | "quotes": ["error", "single"], 16 | "semi": ["error", "always"] 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gitattributes 2 | 3 | # jshint config 4 | .jshintrc 5 | 6 | # build & test artifacts 7 | node_modules 8 | build 9 | 10 | # OS misc 11 | .DS_Store 12 | 13 | # 14 | *.sublime-project 15 | *.sublime-workspace 16 | 17 | # storing some screenshots here 18 | screenshots 19 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "node": true, 4 | "indent": 4, 5 | "browser": true, 6 | "freeze": true, 7 | "boss": true, 8 | "curly": true, 9 | "devel": true, 10 | "esnext": true, 11 | "eqnull": true, 12 | "eqeqeq": true, 13 | "expr": true, 14 | "notypeof": true, 15 | "noarg": true, 16 | "funcscope": true, 17 | "globalstrict": false, 18 | "loopfunc": true, 19 | "noempty": true, 20 | "nonstandard": true, 21 | "onecase": true, 22 | "sub": true, 23 | "regexdash": true, 24 | "trailing": true, 25 | "undef": true, 26 | "unused": "vars", 27 | "globals": { 28 | "L": true, 29 | 30 | "describe": true, 31 | "it": true, 32 | "sinon": true, 33 | "_": true, 34 | "before": true, 35 | "beforeEach": true, 36 | "afterEach": true, 37 | "WebGLRenderingContext": true, 38 | "makeScene": true 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Tangram 2 | 3 | The easiest way to help out is to submit bug reports and feature requests on our [issues](http://github.com/tangrams/tangram/issues) page. 4 | 5 | When submitting a bug report, please list: 6 | 7 | - your specific browser and operating system versions 8 | - steps required to recreate the issue 9 | - what happened 10 | - what you expected to happen 11 | 12 | Thanks, and happy mapping! 13 | 14 | ## Quickstart 15 | 16 | To get Tangram up and running locally: 17 | 18 | 1. Clone or download this repository: 19 | - clone in a terminal window with `git clone https://github.com/tangrams/tangram.git` 20 | - or download a zip directly: https://github.com/tangrams/tangram/archive/master.zip 21 | - or use [Bower](http://bower.io/): `bower install tangram` 22 | 2. Start a webserver in the repository's directory: 23 | - in a terminal window, enter: `python -m SimpleHTTPServer 8000` 24 | - if that doesn't work, try: `python -m http.server` 25 | 3. View the map at http://localhost:8000 (or whatever port you started the server on) 26 | 27 | ### Building 28 | 29 | If you'd like to contribute to the project or just make changes to the source code for fun, you'll need to install the development requirements and build the library: 30 | 31 | ```shell 32 | npm install 33 | npm run build 34 | ``` 35 | 36 | The library will be minified in `dist/`, and `index.html` provides an example for rendering from different sources and simple Leaflet integration. 37 | 38 | ### Incremental Building and Live Reloading 39 | 40 | For more rapid development of Tangram we provide a watcher with incremental building and live reloading, simply run 41 | 42 | ```shell 43 | npm start 44 | ``` 45 | 46 | and point your browser to http://localhost:8000 47 | 48 | Any changes you make to the the source files (including shader code) will rebuild and reload on save. 49 | 50 | ### Testing 51 | 52 | Tests are included to ensure that the code functions as expected. To run all of the tests: 53 | 54 | ```shell 55 | npm test 56 | ``` 57 | 58 | Every time this runs, a new browser instance is created. If you wish to have a single browser instance and run the test suite against that instance do the following, 59 | 60 | ```shell 61 | npm run karma-start 62 | ``` 63 | 64 | And then run the tests with, 65 | 66 | ```shell 67 | npm run karma-run 68 | ``` 69 | 70 | ### Lint 71 | We're using jshint to maintain code quality. 72 | 73 | ```shell 74 | npm run lint 75 | ``` 76 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **TANGRAM VERSION:** 2 | 3 | List the version of Tangram you're using here. 4 | 5 | _If you're not using the latest version, please try that first before filing an issue!_ 6 | 7 | - _Latest version:_ https://mapzen.com/tangram/tangram.min.js 8 | - _Notes for latest version:_ https://github.com/tangrams/tangram/releases/latest 9 | 10 | **ENVIRONMENT:** 11 | 12 | List the OS and browser version combinations which exhibit the behavior here. 13 | 14 | **TO REPRODUCE THE ISSUE, FOLLOW THESE STEPS:** 15 | 16 | - List the steps you used 17 | - To produce the result here 18 | - Don't leave any out 19 | 20 | **RESULT:** 21 | 22 | Describe the result here. 23 | 24 | **EXPECTED RESULT:** 25 | 26 | Describe what you expected to see here, plus any other relevant notes. 27 | Thanks for contributing! 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2016 Brett Camper and Mapzen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | export default function(context) { 2 | const ESM = (process.env.ESM !== 'false'); // default to ESM on 3 | const cache = context.cache(() => ESM); 4 | const targets = ESM ? 5 | { esmodules: true } : 6 | { browsers: ['ie >= 11'] }; 7 | 8 | return { 9 | presets: [ 10 | [ 11 | '@babel/preset-env', { 12 | targets, 13 | bugfixes: true, 14 | // debug: true, // uncomment for debugging build issues 15 | exclude: [ 16 | // we don't want these because we're using fast-async instead 17 | 'transform-async-to-generator', 18 | 'transform-regenerator', 19 | 'proposal-async-generator-functions' 20 | ] 21 | } 22 | ], 23 | ], 24 | plugins: [ 25 | '@babel/plugin-transform-runtime', 26 | ESM ? false : ['module:fast-async', { 27 | spec: true // spec setting sticks to pure promises 28 | },] 29 | ].filter(x => x) 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /build/bundle.mjs: -------------------------------------------------------------------------------- 1 | // Loads each of the chunks produced by the first Rollup pass. 2 | // The custom AMD define() in intro.js will combined the shared 3 | // and worker chunks into a worker bundle that can be instantiated 4 | // via blob URL. 5 | 6 | import './shared'; // shared code between main and worker threads 7 | import './scene_worker'; // worker code, gets turned into a blob URL used to instantiate workers 8 | import './index'; // main thread code, gets exported as main library below 9 | 10 | // This allows the rollup ESM build to work within a 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 43 | 44 | 45 |
46 | 47 | 48 | 49 |