Merge remote-tracking branch 'origin/master' into fix_triangulation

This commit is contained in:
philip
2020-04-02 22:58:59 +00:00
217 changed files with 6848 additions and 3791 deletions

View File

@@ -2,7 +2,7 @@ version: 2
jobs:
build:
docker:
- image: circleci/node:latest-browsers
- image: circleci/node:current-browsers
working_directory: ~/repo
@@ -11,7 +11,7 @@ jobs:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run:
@@ -21,7 +21,7 @@ jobs:
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
key: v1-dependencies-{{ checksum "package-lock.json" }}
- run:
name: Run Tests

View File

@@ -41,29 +41,17 @@ See the following examples for more detail on bundling OpenLayers with your appl
* Using [Parcel](https://github.com/openlayers/ol-parcel)
* Using [Browserify](https://github.com/openlayers/ol-browserify)
## IntelliSense support and type checking for VS Code
## Sponsors
The `ol` package contains a `src/` folder with JSDoc annotated sources. TypeScript can get type definitions from these sources with a `jsconfig.json` config file in the project root:
```js
{
"compilerOptions": {
"checkJs": true,
// Point to the JSDoc typed sources when using modules from the ol package
"baseUrl": "./",
"paths": {
"ol": ["node_modules/ol/src"],
"ol/*": ["node_modules/ol/src/*"]
}
},
"include": [
"**/*.js",
"node_modules/ol/**/*.js"
]
}
```
Project template with this configuration: https://gist.github.com/9a7253cb4712e8bf38d75d8ac898e36c.
OpenLayers appreciates contributions of all kinds. We especially want to thank our fiscal sponsors who contribute to ongoing project maintenance.
Note that the above only works when authoring in plain JavaScript. For similar configurations with a `tsconfig.json` in TypeScript projects, your mileage may vary.
![Pozi logo](./sponsor-logos/pozi.png)
> Pozi helps connect communities through spatial thinking.
> We love Openlayers and it forms a core part of our platform.
> https://pozi.com/ https://app.pozi.com/
See our [Open Collective](https://opencollective.com/openlayers/contribute/sponsors-214/checkout) page if you too are interested in becoming a regular sponsor.
## Supported Browsers

View File

@@ -1,5 +1,11 @@
## Upgrade notes
### v6.3.0
#### Vector source loading when extent crosses +/-180
Previously, when an extent crossed the date line, vector source loaders were called with an extent with 540 degrees of longitude. Now, two loader calls with the visible extent on both sides of the projection extent are issued. This should not require any application code changes, but may affect custom loaders.
### v6.0.0
#### Backwards incompatible changes
@@ -77,7 +83,7 @@ Generally, the responsibility of applying center/rotation/resolutions constraint
##### The view `extent` option now applies to the whole viewport
Previously, this options only constrained the view *center*. This behaviour can still be obtained by specifying `constrainCenterOnly` in the view options.
Previously, this options only constrained the view *center*. This behaviour can still be obtained by specifying `constrainOnlyCenter` in the view options.
As a side effect, the view `rotate` method is gone and has been replaced with `adjustRotation` which takes a delta as input.

View File

@@ -83,7 +83,7 @@ Generally, the responsibility of applying center/rotation/resolutions constraint
##### The view `extent` option now applies to the whole viewport
Previously, this options only constrained the view *center*. This behaviour can still be obtained by specifying `constrainCenterOnly` in the view options.
Previously, this options only constrained the view *center*. This behaviour can still be obtained by specifying `constrainOnlyCenter` in the view options.
As a side effect, the view `rotate` method is gone and has been replaced with `adjustRotation` which takes a delta as input.

196
changelog/v6.2.0.md Normal file
View File

@@ -0,0 +1,196 @@
# 6.2.0
With almost 90 pull requests, this release brings several new features, performance improvements and bug fixes. In addition to that, we once again improved the API documentation and the example pages.
## New features and improvements
* Mousewheel zooming now brings the same user experience as trackpad zooming. One click on the wheel no longer means a jump of a whole zoom level. Instead, depending on the speed of moving the wheel, the user has fine-grained control over zoom increments/decrements.
* Users now have better control over the initial map viewport when the aspect ratio of the map is different from a specified initial extent.
* Text rendering has been optimized for decluttering and improved for rotated views. This means lower memory footprint and no more blurry text when the map is rotated. **Note:** Whit this change, the label cache has been deprecated.
* A new `displacement` option for icon, circle and regular shape styles makes positioning of point symbolizers more flexible.
* Several improvements have been made to the KML parser for reading styles, bringing the rendered result much closer to Google Earth.
* OpenLayers is now less aggressive on stopping events and preventing event default behavior. This means that users have more control over events, making it easier to use interactive SVGs as layers and to embed maps on scrollable pages.
* Vector tile layers now have a `vector` render mode, which brings improved zooming experience for sources with not too much data.
* We replaced the previous pointer events polyfill to elm-pep, which should work better in web components.
## List of all changes
* [#10613](https://github.com/openlayers/openlayers/pull/10613) - Show KML name labels for Points in MultiGeometry ([@mike-000](https://github.com/mike-000))
* [#10632](https://github.com/openlayers/openlayers/pull/10632) - Draw interaction: Append coordinates to polygons and lines (reworked) ([@jahow](https://github.com/jahow))
* [#9565](https://github.com/openlayers/openlayers/pull/9565) - Make mousewheel zoom behave like trackpad zoom. ([@dbrnz](https://github.com/dbrnz))
* [#10580](https://github.com/openlayers/openlayers/pull/10580) - Fix KML Polystyle outline 0 conflict with Linestyle for linestrings ([@mike-000](https://github.com/mike-000))
* [#10612](https://github.com/openlayers/openlayers/pull/10612) - Make examples work in Internet Explorer ([@ahocevar](https://github.com/ahocevar))
* [#10587](https://github.com/openlayers/openlayers/pull/10587) - Adds option to View for using larger resolution value when clamping #10586 ([@jeremy-smith-maco](https://github.com/jeremy-smith-maco))
* [#10607](https://github.com/openlayers/openlayers/pull/10607) - Update elm-pep to fix builds for IE < 11 ([@ahocevar](https://github.com/ahocevar))
* [#10598](https://github.com/openlayers/openlayers/pull/10598) - Remove inheritDoc to work around JSDoc issue ([@ahocevar](https://github.com/ahocevar))
* [#10574](https://github.com/openlayers/openlayers/pull/10574) - Text rendering improvements ([@ahocevar](https://github.com/ahocevar))
* [#10591](https://github.com/openlayers/openlayers/pull/10591) - Remove obsolete license notice ([@ahocevar](https://github.com/ahocevar))
* [#10588](https://github.com/openlayers/openlayers/pull/10588) - Sort doc navigation properly and add missing modules ([@ahocevar](https://github.com/ahocevar))
* [#10581](https://github.com/openlayers/openlayers/pull/10581) - Use package-lock.json for the checksum calculation ([@DanielRuf](https://github.com/DanielRuf))
* [#10584](https://github.com/openlayers/openlayers/pull/10584) - fixed issue with version throwing an error if it is null ([@MrSoUndso](https://github.com/MrSoUndso))
* [#10575](https://github.com/openlayers/openlayers/pull/10575) - Fix ol/layer/Graticule rendercomplete problem ([@mike-000](https://github.com/mike-000))
* [#10562](https://github.com/openlayers/openlayers/pull/10562) - Zoomify: Separate the service pixel ratio and the device pixel ratio ([@crubier](https://github.com/crubier))
* [#10573](https://github.com/openlayers/openlayers/pull/10573) - Replace Bing layer with MapTiler in example ([@mike-000](https://github.com/mike-000))
* [#10570](https://github.com/openlayers/openlayers/pull/10570) - Use correct extent for the vector image ([@ahocevar](https://github.com/ahocevar))
* [#10572](https://github.com/openlayers/openlayers/pull/10572) - Assert each layer is only added to the map once ([@ahocevar](https://github.com/ahocevar))
* [#10563](https://github.com/openlayers/openlayers/pull/10563) - More compatible way of exporting a map as pdf ([@ahocevar](https://github.com/ahocevar))
* [#10545](https://github.com/openlayers/openlayers/pull/10545) - Make KML point feature styles compatible with declutter ([@mike-000](https://github.com/mike-000))
* [#10542](https://github.com/openlayers/openlayers/pull/10542) - Replace Bing layer with MapTiler in KML example ([@mike-000](https://github.com/mike-000))
* [#10543](https://github.com/openlayers/openlayers/pull/10543) - @api tag must not have a value. ([@MoonE](https://github.com/MoonE))
* [#10547](https://github.com/openlayers/openlayers/pull/10547) - Only generate module apidoc pages when it contains api tags ([@MoonE](https://github.com/MoonE))
* [#10502](https://github.com/openlayers/openlayers/pull/10502) - Stop events that originate with a removed target ([@walkermatt](https://github.com/walkermatt))
* [#10527](https://github.com/openlayers/openlayers/pull/10527) - Remove label cache, render text directly to target canvas ([@ahocevar](https://github.com/ahocevar))
* [#10534](https://github.com/openlayers/openlayers/pull/10534) - [GeoJSON] Read projection from CRS type EPSG ([@wussup](https://github.com/wussup))
* [#10430](https://github.com/openlayers/openlayers/pull/10430) - Offset regular shape ([@Razi91](https://github.com/Razi91))
* [#10513](https://github.com/openlayers/openlayers/pull/10513) - fixed flag-name in upgrade notes ([@fgubler](https://github.com/fgubler))
* [#10504](https://github.com/openlayers/openlayers/pull/10504) - Fix for reset north when rotation is 360 degrees ([@mike-000](https://github.com/mike-000))
* [#10510](https://github.com/openlayers/openlayers/pull/10510) - Remove build/apidoc before running jsdoc again ([@MoonE](https://github.com/MoonE))
* [#10498](https://github.com/openlayers/openlayers/pull/10498) - Fixing issue #10497 on behalf of LarryHuang ([@gazza0](https://github.com/gazza0))
* [#10496](https://github.com/openlayers/openlayers/pull/10496) - Do not stop events when dragging ([@ahocevar](https://github.com/ahocevar))
* [#10478](https://github.com/openlayers/openlayers/pull/10478) - Do not abort and dispose of tiles ([@ahocevar](https://github.com/ahocevar))
* [#10495](https://github.com/openlayers/openlayers/pull/10495) - typo in view.fit ([@danielklim](https://github.com/danielklim))
* [#10473](https://github.com/openlayers/openlayers/pull/10473) - Fix for undefined source in Vector layer ([@mike-000](https://github.com/mike-000))
* [#10484](https://github.com/openlayers/openlayers/pull/10484) - Use a function to get the value of the gradient ([@fredj](https://github.com/fredj))
* [#10262](https://github.com/openlayers/openlayers/pull/10262) - Rework to make Document and XMLSerializer lazy and injectable ([@bjornharrtell](https://github.com/bjornharrtell))
* [#10461](https://github.com/openlayers/openlayers/pull/10461) - Fix link in apidocs to ObjectEvent. ([@MoonE](https://github.com/MoonE))
* [#10413](https://github.com/openlayers/openlayers/pull/10413) - Limit the ZoomSlider's range to the view's constrained resolution. ([@MoonE](https://github.com/MoonE))
* [#10438](https://github.com/openlayers/openlayers/pull/10438) - Avoid accessing the DOM to read the viewport size too often ([@jahow](https://github.com/jahow))
* [#10439](https://github.com/openlayers/openlayers/pull/10439) - WebGL points layer / add support for symbol rotation ([@jahow](https://github.com/jahow))
* [#10434](https://github.com/openlayers/openlayers/pull/10434) - Disable image smoothing for the DEM source in the Sea Level example ([@mike-000](https://github.com/mike-000))
* [#10417](https://github.com/openlayers/openlayers/pull/10417) - Replace Bing layer with MapTiler ([@mike-000](https://github.com/mike-000))
* [#10415](https://github.com/openlayers/openlayers/pull/10415) - Control button span element pointer events ([@mike-000](https://github.com/mike-000))
* [#10409](https://github.com/openlayers/openlayers/pull/10409) - Improve viewport computation in WebGL Postprocessing ([@jahow](https://github.com/jahow))
* [#10119](https://github.com/openlayers/openlayers/pull/10119) - Add crossOrigin option to ol/format/KML for icons ([@mike-000](https://github.com/mike-000))
* [#10181](https://github.com/openlayers/openlayers/pull/10181) - add tags to example docs ([@roemhildtg](https://github.com/roemhildtg))
* [#10407](https://github.com/openlayers/openlayers/pull/10407) - Use render feature compatible extent check ([@ahocevar](https://github.com/ahocevar))
* [#10340](https://github.com/openlayers/openlayers/pull/10340) - Draw circles and custom geometry in user coordinates ([@mike-000](https://github.com/mike-000))
* [#10393](https://github.com/openlayers/openlayers/pull/10393) - getFeaturesInExtent function for ol/source/VectorTile ([@ahocevar](https://github.com/ahocevar))
* [#10402](https://github.com/openlayers/openlayers/pull/10402) - Do not preventDefault on pointerdown ([@ahocevar](https://github.com/ahocevar))
* [#10269](https://github.com/openlayers/openlayers/pull/10269) - Replace the BNG layer source in the Raster Reprojection example ([@mike-000](https://github.com/mike-000))
* [#10394](https://github.com/openlayers/openlayers/pull/10394) - Remove map renderer element when disposing ([@ahocevar](https://github.com/ahocevar))
* [#10391](https://github.com/openlayers/openlayers/pull/10391) - Use box-shadow css instead of filter ([@ahocevar](https://github.com/ahocevar))
* [#10392](https://github.com/openlayers/openlayers/pull/10392) - Fix interim tile handing for vector tiles ([@ahocevar](https://github.com/ahocevar))
* [#10380](https://github.com/openlayers/openlayers/pull/10380) - Adjust examples for layer canvas pixel ratio and rotation ([@mike-000](https://github.com/mike-000))
* [#10384](https://github.com/openlayers/openlayers/pull/10384) - Include Transform typedef in API ([@mike-000](https://github.com/mike-000))
* [#10385](https://github.com/openlayers/openlayers/pull/10385) - Import transpiled rbush ([@walkermatt](https://github.com/walkermatt))
* [#10363](https://github.com/openlayers/openlayers/pull/10363) - Interactive SVG layer example ([@ahocevar](https://github.com/ahocevar))
* [#10120](https://github.com/openlayers/openlayers/pull/10120) - Resolve constraints using anchor if following a cancelled animation ([@mike-000](https://github.com/mike-000))
* [#10370](https://github.com/openlayers/openlayers/pull/10370) - Replace Bing layer with MapTiler ([@mike-000](https://github.com/mike-000))
* [#10362](https://github.com/openlayers/openlayers/pull/10362) - Remove line that was accidently added with #10332 ([@ahocevar](https://github.com/ahocevar))
* [#10309](https://github.com/openlayers/openlayers/pull/10309) - Bring back vector render mode for vector tile layers ([@ahocevar](https://github.com/ahocevar))
* [#10332](https://github.com/openlayers/openlayers/pull/10332) - Conditional default prevention instead of touch-action: none ([@ahocevar](https://github.com/ahocevar))
* [#10301](https://github.com/openlayers/openlayers/pull/10301) - Create hit detection data per layer and without requestAnimationFrame ([@ahocevar](https://github.com/ahocevar))
* [#10347](https://github.com/openlayers/openlayers/pull/10347) - Set utfgrid tile as loaded after load instead of empty ([@adube](https://github.com/adube))
* [#10344](https://github.com/openlayers/openlayers/pull/10344) - Fix lazy UTFGrid loading ([@ahocevar](https://github.com/ahocevar))
* [#10321](https://github.com/openlayers/openlayers/pull/10321) - Support touch events for DragBox interaction ([@greggian](https://github.com/greggian))
* [#10315](https://github.com/openlayers/openlayers/pull/10315) - Replace Bing sources in some examples ([@mike-000](https://github.com/mike-000))
* [#10330](https://github.com/openlayers/openlayers/pull/10330) - Fix modifying circle geometries ([@greggian](https://github.com/greggian))
* [#10318](https://github.com/openlayers/openlayers/pull/10318) - Use a minimalist pointer events polyfill ([@ahocevar](https://github.com/ahocevar))
* [#10322](https://github.com/openlayers/openlayers/pull/10322) - Update tile grid option descriptions ([@mike-000](https://github.com/mike-000))
* [#10308](https://github.com/openlayers/openlayers/pull/10308) - Fix feature lookup after removal of alpha ([@ahocevar](https://github.com/ahocevar))
* [#10310](https://github.com/openlayers/openlayers/pull/10310) - Ensure that OverviewMap respects the initial rotation of attached Maps ([@brianhelba](https://github.com/brianhelba))
* [#10302](https://github.com/openlayers/openlayers/pull/10302) - Do not use Math.sign() to support very old browsers ([@ahocevar](https://github.com/ahocevar))
* [#10295](https://github.com/openlayers/openlayers/pull/10295) - Do not fail when hit detecting features without style ([@ahocevar](https://github.com/ahocevar))
* [#10293](https://github.com/openlayers/openlayers/pull/10293) - Do not hit detect while tile is loading ([@ahocevar](https://github.com/ahocevar))
* [#10292](https://github.com/openlayers/openlayers/pull/10292) - Fix typo in jsdoc in ol/source/WMTS ([@jomue](https://github.com/jomue))
* [#10291](https://github.com/openlayers/openlayers/pull/10291) - tabindex without focus condition ([@ahocevar](https://github.com/ahocevar))
* [#10286](https://github.com/openlayers/openlayers/pull/10286) - Use passive option to avoid Chrome warning ([@ahocevar](https://github.com/ahocevar))
* [#10285](https://github.com/openlayers/openlayers/pull/10285) - Fix WMS GetLegendGraphic example codesandbox error ([@mike-000](https://github.com/mike-000))
* [#10283](https://github.com/openlayers/openlayers/pull/10283) - Use the originalEvent in the targetNotEditable condition ([@fredj](https://github.com/fredj))
* [#10282](https://github.com/openlayers/openlayers/pull/10282) - Fix documentation of Stroke.lineDash default value ([@jansule](https://github.com/jansule))
* [#10259](https://github.com/openlayers/openlayers/pull/10259) - Remove all the sketch features in abortDrawing ([@fredj](https://github.com/fredj))
* [#10265](https://github.com/openlayers/openlayers/pull/10265) - Update operators doc in WebGL points layer example ([@fredj](https://github.com/fredj))
* [#10256](https://github.com/openlayers/openlayers/pull/10256) - Do not bypass measureTextWidth ([@ahocevar](https://github.com/ahocevar))
* [#10264](https://github.com/openlayers/openlayers/pull/10264) - Remove unused variable from vertex shader ([@fredj](https://github.com/fredj))
* [#10257](https://github.com/openlayers/openlayers/pull/10257) - Allow View.adjust* methods to take a null opt_anchor ([@brianhelba](https://github.com/brianhelba))
* [#10261](https://github.com/openlayers/openlayers/pull/10261) - WebGL / do not throw error when shader compilation gives a warning ([@jahow](https://github.com/jahow))
* [#10255](https://github.com/openlayers/openlayers/pull/10255) - Don't use instanceof HTMLElement in handleMapBrowserEvent ([@fredj](https://github.com/fredj))
<details>
<summary>Dependency Updates</summary>
* [#10629](https://github.com/openlayers/openlayers/pull/10629) - Bump ol-mapbox-style from 6.0.0 to 6.0.1 ([@openlayers](https://github.com/openlayers))
* [#10628](https://github.com/openlayers/openlayers/pull/10628) - Bump puppeteer from 2.1.0 to 2.1.1 ([@openlayers](https://github.com/openlayers))
* [#10627](https://github.com/openlayers/openlayers/pull/10627) - Bump handlebars from 4.7.2 to 4.7.3 ([@openlayers](https://github.com/openlayers))
* [#10626](https://github.com/openlayers/openlayers/pull/10626) - Bump webpack-dev-server from 3.10.2 to 3.10.3 ([@openlayers](https://github.com/openlayers))
* [#10600](https://github.com/openlayers/openlayers/pull/10600) - Bump puppeteer from 2.0.0 to 2.1.0 ([@openlayers](https://github.com/openlayers))
* [#10606](https://github.com/openlayers/openlayers/pull/10606) - Bump @babel/core from 7.8.3 to 7.8.4 ([@openlayers](https://github.com/openlayers))
* [#10605](https://github.com/openlayers/openlayers/pull/10605) - Bump webpack-dev-server from 3.10.1 to 3.10.2 ([@openlayers](https://github.com/openlayers))
* [#10604](https://github.com/openlayers/openlayers/pull/10604) - Bump rollup from 1.29.1 to 1.31.0 ([@openlayers](https://github.com/openlayers))
* [#10603](https://github.com/openlayers/openlayers/pull/10603) - Bump @babel/preset-env from 7.8.3 to 7.8.4 ([@openlayers](https://github.com/openlayers))
* [#10602](https://github.com/openlayers/openlayers/pull/10602) - Bump url-polyfill from 1.1.7 to 1.1.8 ([@openlayers](https://github.com/openlayers))
* [#10601](https://github.com/openlayers/openlayers/pull/10601) - Bump terser-webpack-plugin from 2.3.2 to 2.3.4 ([@openlayers](https://github.com/openlayers))
* [#10578](https://github.com/openlayers/openlayers/pull/10578) - Bump sinon from 8.1.0 to 8.1.1 ([@openlayers](https://github.com/openlayers))
* [#10577](https://github.com/openlayers/openlayers/pull/10577) - Bump mocha from 7.0.0 to 7.0.1 ([@openlayers](https://github.com/openlayers))
* [#10576](https://github.com/openlayers/openlayers/pull/10576) - Bump rollup from 1.29.0 to 1.29.1 ([@openlayers](https://github.com/openlayers))
* [#10551](https://github.com/openlayers/openlayers/pull/10551) - Bump handlebars from 4.7.1 to 4.7.2 ([@openlayers](https://github.com/openlayers))
* [#10550](https://github.com/openlayers/openlayers/pull/10550) - Bump @babel/preset-env from 7.8.2 to 7.8.3 ([@openlayers](https://github.com/openlayers))
* [#10549](https://github.com/openlayers/openlayers/pull/10549) - Bump sinon from 8.0.4 to 8.1.0 ([@openlayers](https://github.com/openlayers))
* [#10548](https://github.com/openlayers/openlayers/pull/10548) - Bump @babel/core from 7.8.0 to 7.8.3 ([@openlayers](https://github.com/openlayers))
* [#10518](https://github.com/openlayers/openlayers/pull/10518) - Bump front-matter from 3.0.2 to 3.1.0 ([@openlayers](https://github.com/openlayers))
* [#10516](https://github.com/openlayers/openlayers/pull/10516) - Bump handlebars from 4.5.3 to 4.7.1 ([@openlayers](https://github.com/openlayers))
* [#10514](https://github.com/openlayers/openlayers/pull/10514) - Bump terser-webpack-plugin from 2.3.1 to 2.3.2 ([@openlayers](https://github.com/openlayers))
* [#10523](https://github.com/openlayers/openlayers/pull/10523) - Bump sinon from 8.0.2 to 8.0.4 ([@openlayers](https://github.com/openlayers))
* [#10515](https://github.com/openlayers/openlayers/pull/10515) - Bump @babel/preset-env from 7.7.7 to 7.8.2 ([@openlayers](https://github.com/openlayers))
* [#10517](https://github.com/openlayers/openlayers/pull/10517) - Bump karma-firefox-launcher from 1.2.0 to 1.3.0 ([@openlayers](https://github.com/openlayers))
* [#10519](https://github.com/openlayers/openlayers/pull/10519) - Bump @babel/core from 7.7.7 to 7.8.0 ([@openlayers](https://github.com/openlayers))
* [#10520](https://github.com/openlayers/openlayers/pull/10520) - Bump globby from 10.0.1 to 11.0.0 ([@openlayers](https://github.com/openlayers))
* [#10521](https://github.com/openlayers/openlayers/pull/10521) - Bump rollup-plugin-terser from 5.1.3 to 5.2.0 ([@openlayers](https://github.com/openlayers))
* [#10522](https://github.com/openlayers/openlayers/pull/10522) - Bump rollup from 1.28.0 to 1.29.0 ([@openlayers](https://github.com/openlayers))
* [#10480](https://github.com/openlayers/openlayers/pull/10480) - Bump mocha from 6.2.2 to 7.0.0 ([@openlayers](https://github.com/openlayers))
* [#10482](https://github.com/openlayers/openlayers/pull/10482) - Bump sinon from 8.0.1 to 8.0.2 ([@openlayers](https://github.com/openlayers))
* [#10481](https://github.com/openlayers/openlayers/pull/10481) - Bump yargs from 15.0.2 to 15.1.0 ([@openlayers](https://github.com/openlayers))
* [#10479](https://github.com/openlayers/openlayers/pull/10479) - Bump rollup from 1.27.14 to 1.28.0 ([@openlayers](https://github.com/openlayers))
* [#10466](https://github.com/openlayers/openlayers/pull/10466) - Bump webpack from 4.41.4 to 4.41.5 ([@openlayers](https://github.com/openlayers))
* [#10467](https://github.com/openlayers/openlayers/pull/10467) - Bump sinon from 8.0.0 to 8.0.1 ([@openlayers](https://github.com/openlayers))
* [#10450](https://github.com/openlayers/openlayers/pull/10450) - Bump @babel/core from 7.7.5 to 7.7.7 ([@openlayers](https://github.com/openlayers))
* [#10449](https://github.com/openlayers/openlayers/pull/10449) - Bump eslint from 6.7.2 to 6.8.0 ([@openlayers](https://github.com/openlayers))
* [#10448](https://github.com/openlayers/openlayers/pull/10448) - Bump rollup from 1.27.13 to 1.27.14 ([@openlayers](https://github.com/openlayers))
* [#10447](https://github.com/openlayers/openlayers/pull/10447) - Bump @babel/preset-env from 7.7.6 to 7.7.7 ([@openlayers](https://github.com/openlayers))
* [#10446](https://github.com/openlayers/openlayers/pull/10446) - Bump sinon from 7.5.0 to 8.0.0 ([@openlayers](https://github.com/openlayers))
* [#10445](https://github.com/openlayers/openlayers/pull/10445) - Bump webpack from 4.41.2 to 4.41.4 ([@openlayers](https://github.com/openlayers))
* [#10444](https://github.com/openlayers/openlayers/pull/10444) - Bump terser-webpack-plugin from 2.3.0 to 2.3.1 ([@openlayers](https://github.com/openlayers))
* [#10443](https://github.com/openlayers/openlayers/pull/10443) - Bump webpack-dev-server from 3.9.0 to 3.10.1 ([@openlayers](https://github.com/openlayers))
* [#10425](https://github.com/openlayers/openlayers/pull/10425) - Bump elm-pep from 1.0.2 to 1.0.3 ([@openlayers](https://github.com/openlayers))
* [#10427](https://github.com/openlayers/openlayers/pull/10427) - Bump webpack-cli from 3.3.2 to 3.3.10 ([@openlayers](https://github.com/openlayers))
* [#10426](https://github.com/openlayers/openlayers/pull/10426) - Bump copy-webpack-plugin from 5.0.5 to 5.1.1 ([@openlayers](https://github.com/openlayers))
* [#10424](https://github.com/openlayers/openlayers/pull/10424) - Bump eslint from 6.7.1 to 6.7.2 ([@openlayers](https://github.com/openlayers))
* [#10423](https://github.com/openlayers/openlayers/pull/10423) - Bump marked from 0.7.0 to 0.8.0 ([@openlayers](https://github.com/openlayers))
* [#10422](https://github.com/openlayers/openlayers/pull/10422) - Bump url-polyfill from 1.1.5 to 1.1.7 ([@openlayers](https://github.com/openlayers))
* [#10421](https://github.com/openlayers/openlayers/pull/10421) - Bump rollup-plugin-terser from 5.1.2 to 5.1.3 ([@openlayers](https://github.com/openlayers))
* [#10420](https://github.com/openlayers/openlayers/pull/10420) - Bump terser-webpack-plugin from 2.2.2 to 2.3.0 ([@openlayers](https://github.com/openlayers))
* [#10419](https://github.com/openlayers/openlayers/pull/10419) - Bump rollup from 1.27.9 to 1.27.13 ([@openlayers](https://github.com/openlayers))
* [#10418](https://github.com/openlayers/openlayers/pull/10418) - Bump babel-loader from 8.0.5 to 8.0.6 ([@openlayers](https://github.com/openlayers))
* [#10399](https://github.com/openlayers/openlayers/pull/10399) - Bump rollup from 1.25.1 to 1.27.9 ([@openlayers](https://github.com/openlayers))
* [#10398](https://github.com/openlayers/openlayers/pull/10398) - Bump terser-webpack-plugin from 2.2.1 to 2.2.2 ([@openlayers](https://github.com/openlayers))
* [#10397](https://github.com/openlayers/openlayers/pull/10397) - Bump @babel/core from 7.7.4 to 7.7.5 ([@openlayers](https://github.com/openlayers))
* [#10396](https://github.com/openlayers/openlayers/pull/10396) - Bump @babel/preset-env from 7.7.4 to 7.7.6 ([@openlayers](https://github.com/openlayers))
* [#10365](https://github.com/openlayers/openlayers/pull/10365) - Bump @babel/preset-env from 7.6.3 to 7.7.4 ([@openlayers](https://github.com/openlayers))
* [#10366](https://github.com/openlayers/openlayers/pull/10366) - Bump karma-coverage-istanbul-reporter from 2.1.0 to 2.1.1 ([@openlayers](https://github.com/openlayers))
* [#10367](https://github.com/openlayers/openlayers/pull/10367) - Bump coveralls from 3.0.7 to 3.0.9 ([@openlayers](https://github.com/openlayers))
* [#10368](https://github.com/openlayers/openlayers/pull/10368) - Bump sinon from 7.3.2 to 7.5.0 ([@openlayers](https://github.com/openlayers))
* [#10369](https://github.com/openlayers/openlayers/pull/10369) - Bump @babel/core from 7.7.2 to 7.7.4 ([@openlayers](https://github.com/openlayers))
* [#10337](https://github.com/openlayers/openlayers/pull/10337) - Bump fs-extra from 8.0.1 to 8.1.0 ([@openlayers](https://github.com/openlayers))
* [#10336](https://github.com/openlayers/openlayers/pull/10336) - Bump eslint from 6.6.0 to 6.7.1 ([@openlayers](https://github.com/openlayers))
* [#10335](https://github.com/openlayers/openlayers/pull/10335) - Bump yargs from 14.2.0 to 15.0.2 ([@openlayers](https://github.com/openlayers))
* [#10334](https://github.com/openlayers/openlayers/pull/10334) - Bump webpack-dev-middleware from 3.6.2 to 3.7.2 ([@openlayers](https://github.com/openlayers))
* [#10333](https://github.com/openlayers/openlayers/pull/10333) - Bump copy-webpack-plugin from 5.0.4 to 5.0.5 ([@openlayers](https://github.com/openlayers))
* [#10306](https://github.com/openlayers/openlayers/pull/10306) - Bump puppeteer from 1.20.0 to 2.0.0 ([@openlayers](https://github.com/openlayers))
* [#10307](https://github.com/openlayers/openlayers/pull/10307) - Bump @babel/core from 7.6.4 to 7.7.2 ([@openlayers](https://github.com/openlayers))
* [#10305](https://github.com/openlayers/openlayers/pull/10305) - Bump proj4 from 2.5.0 to 2.6.0 ([@openlayers](https://github.com/openlayers))
* [#10304](https://github.com/openlayers/openlayers/pull/10304) - Bump handlebars from 4.4.5 to 4.5.3 ([@openlayers](https://github.com/openlayers))
* [#10303](https://github.com/openlayers/openlayers/pull/10303) - Bump glob from 7.1.5 to 7.1.6 ([@openlayers](https://github.com/openlayers))
* [#10280](https://github.com/openlayers/openlayers/pull/10280) - Bump rollup-plugin-commonjs from 10.0.0 to 10.1.0 ([@openlayers](https://github.com/openlayers))
* [#10279](https://github.com/openlayers/openlayers/pull/10279) - Bump rollup-plugin-terser from 5.0.0 to 5.1.2 ([@openlayers](https://github.com/openlayers))
* [#10278](https://github.com/openlayers/openlayers/pull/10278) - Bump eslint from 6.0.0 to 6.6.0 ([@openlayers](https://github.com/openlayers))
* [#10277](https://github.com/openlayers/openlayers/pull/10277) - Bump karma-webpack from 4.0.0-rc.6 to 4.0.2 ([@openlayers](https://github.com/openlayers))
* [#10276](https://github.com/openlayers/openlayers/pull/10276) - Bump webpack-dev-server from 3.3.1 to 3.9.0 ([@openlayers](https://github.com/openlayers))
* [#10251](https://github.com/openlayers/openlayers/pull/10251) - Bump @babel/preset-env from 7.4.4 to 7.6.3 ([@openlayers](https://github.com/openlayers))
* [#10250](https://github.com/openlayers/openlayers/pull/10250) - Bump buble from 0.19.7 to 0.19.8 ([@openlayers](https://github.com/openlayers))
* [#10249](https://github.com/openlayers/openlayers/pull/10249) - Bump karma-firefox-launcher from 1.1.0 to 1.2.0 ([@openlayers](https://github.com/openlayers))
* [#10248](https://github.com/openlayers/openlayers/pull/10248) - Bump html-to-image from 0.1.0 to 0.1.1 ([@openlayers](https://github.com/openlayers))
* [#10247](https://github.com/openlayers/openlayers/pull/10247) - Bump terser-webpack-plugin from 2.0.1 to 2.2.1 ([@openlayers](https://github.com/openlayers))
</details>

13
changelog/v6.2.1.md Normal file
View File

@@ -0,0 +1,13 @@
# 6.2.1
This is a bugfix release which resolves bundler issues due to a circular dependency, and brings a few documentation and example fixes.
## List of all changes
* [#10656](https://github.com/openlayers/openlayers/pull/10656) - Fix for export PDF example compatibility issues, and layer opacity handling. ([@mike-000](https://github.com/mike-000))
* [#10653](https://github.com/openlayers/openlayers/pull/10653) - More reliable check for module content beyond classes ([@ahocevar](https://github.com/ahocevar))
* [#10617](https://github.com/openlayers/openlayers/pull/10617) - Improve apidoc generation performance ([@MoonE](https://github.com/MoonE))
* [#10625](https://github.com/openlayers/openlayers/pull/10625) - Apidoc cleanup navigation html ([@MoonE](https://github.com/MoonE))
* [#10649](https://github.com/openlayers/openlayers/pull/10649) - Remove circular dependency ([@ahocevar](https://github.com/ahocevar))
* [#10637](https://github.com/openlayers/openlayers/pull/10637) - Develop on 6.2.1 ([@openlayers](https://github.com/openlayers))

123
changelog/v6.3.0.md Normal file
View File

@@ -0,0 +1,123 @@
# 6.3.0
With more than 70 pull requests, this release not only brings significant improvements to the API documentation. It also fixes some old bugs and brings frequently requested improvments. And good news for TypeScript users: OpenLayers now ships with type definitions in `.d.ts` files.
## New features and improvements
* Several improvements to the Graticule layer, like consistent labeling, no more missing graticule lines, and it now works for views that cross the date line.
* Better support for KML icon colors, as well as fills and outlines in PolyStyle
* Better `ol/Overlay` performance and support for panning off-screen overlays into view
* Most of the rendering code can now be run in web workers, e.g. to render to an OffscreenCanvas
* OpenLayers now works fine in web components with shadow root
* WebGL point layers now support rotation based on feature attributes
## List of all changes
* [#10490](https://github.com/openlayers/openlayers/pull/10490) - Select style multiple select interactions removed ([@bepremeg](https://github.com/bepremeg))
* [#10531](https://github.com/openlayers/openlayers/pull/10531) - Dynamically chose the number of subdivisions based on the size of the Image to reproject ([@pjsg](https://github.com/pjsg))
* [#10618](https://github.com/openlayers/openlayers/pull/10618) - Add apidoc-debug task to debug the apidoc generation process ([@MoonE](https://github.com/MoonE))
* [#10343](https://github.com/openlayers/openlayers/pull/10343) - Correct interactions with circle geometries when using user coordinates ([@mike-000](https://github.com/mike-000))
* [#10864](https://github.com/openlayers/openlayers/pull/10864) - Update dependencies ([@ahocevar](https://github.com/ahocevar))
* [#10859](https://github.com/openlayers/openlayers/pull/10859) - Add an example of clipping layer based on a vector source ([@SDaron](https://github.com/SDaron))
* [#10850](https://github.com/openlayers/openlayers/pull/10850) - API docs for enums ([@ahocevar](https://github.com/ahocevar))
* [#10857](https://github.com/openlayers/openlayers/pull/10857) - Make OSM XML example work at dateline and replace Bing with MapTiler ([@mike-000](https://github.com/mike-000))
* [#10858](https://github.com/openlayers/openlayers/pull/10858) - Perform auto-pan when adding an Overlay to a Map ([@ejn](https://github.com/ejn))
* [#10646](https://github.com/openlayers/openlayers/pull/10646) - Write fill and outline in KML PolyStyle ([@mike-000](https://github.com/mike-000))
* [#10800](https://github.com/openlayers/openlayers/pull/10800) - Make Overlay.panIntoView an API method ([@ejn](https://github.com/ejn))
* [#10807](https://github.com/openlayers/openlayers/pull/10807) - Handle Graticule wrapX without calculating excess meridians ([@mike-000](https://github.com/mike-000))
* [#10795](https://github.com/openlayers/openlayers/pull/10795) - Show graticule labels in wrapped worlds ([@mike-000](https://github.com/mike-000))
* [#10824](https://github.com/openlayers/openlayers/pull/10824) - Fix drawing svg icon with color option in ie11 ([@MoonE](https://github.com/MoonE))
* [#10802](https://github.com/openlayers/openlayers/pull/10802) - Apidoc add default-exported enums ([@MoonE](https://github.com/MoonE))
* [#10805](https://github.com/openlayers/openlayers/pull/10805) - make ImageSourceEventType available for consumers ([@regileeso](https://github.com/regileeso))
* [#10822](https://github.com/openlayers/openlayers/pull/10822) - parsing color from IconStyle in KML files ([@lysek](https://github.com/lysek))
* [#10848](https://github.com/openlayers/openlayers/pull/10848) - Speed up Overlay element positioning using CSS translate() ([@horsenit](https://github.com/horsenit))
* [#9590](https://github.com/openlayers/openlayers/pull/9590) - Calculate tile grid extent from extent of bottom-level tile matrix ([@mloskot](https://github.com/mloskot))
* [#10845](https://github.com/openlayers/openlayers/pull/10845) - Fix createHitDetectionImageData error for features with no size ([@gedaiu](https://github.com/gedaiu))
* [#10842](https://github.com/openlayers/openlayers/pull/10842) - Fix custom symbol example short description ([@mike-000](https://github.com/mike-000))
* [#10828](https://github.com/openlayers/openlayers/pull/10828) - Offscreen canvas example ([@ahocevar](https://github.com/ahocevar))
* [#10816](https://github.com/openlayers/openlayers/pull/10816) - Add 'funding' field to `package.json` ([@marcjansen](https://github.com/marcjansen))
* [#10813](https://github.com/openlayers/openlayers/pull/10813) - Add sponsors section to the readme ([@tschaub](https://github.com/tschaub))
* [#10474](https://github.com/openlayers/openlayers/pull/10474) - Fix for undefined source in Image layer ([@mike-000](https://github.com/mike-000))
* [#10785](https://github.com/openlayers/openlayers/pull/10785) - Detect Zoomify server-side retina tiles ([@ahocevar](https://github.com/ahocevar))
* [#10787](https://github.com/openlayers/openlayers/pull/10787) - Improved projection extent in the "Reprojection with EPSG.io Search" example ([@mike-000](https://github.com/mike-000))
* [#10792](https://github.com/openlayers/openlayers/pull/10792) - Add support for EventListener Object ([@flexjoly](https://github.com/flexjoly))
* [#10777](https://github.com/openlayers/openlayers/pull/10777) - Keep the render loop running during simulation ([@ahocevar](https://github.com/ahocevar))
* [#10791](https://github.com/openlayers/openlayers/pull/10791) - iOS 12 touchmove: Prevent touchmove event default when no preceding pointer event ([@sosmo](https://github.com/sosmo))
* [#10786](https://github.com/openlayers/openlayers/pull/10786) - Resolve constraints when updating size ([@ahocevar](https://github.com/ahocevar))
* [#10788](https://github.com/openlayers/openlayers/pull/10788) - Add safeguard to handleTouchMove ([@sosmo](https://github.com/sosmo))
* [#10722](https://github.com/openlayers/openlayers/pull/10722) - fix: handle layer clear event in case clear(true) called ([@jellyedwards](https://github.com/jellyedwards))
* [#10723](https://github.com/openlayers/openlayers/pull/10723) - Improve the extent transforms used by Graticule and handle extents crossing the dateline ([@mike-000](https://github.com/mike-000))
* [#10744](https://github.com/openlayers/openlayers/pull/10744) - Ensure the Modify Features Test example opens at correct zoom ([@mike-000](https://github.com/mike-000))
* [#10767](https://github.com/openlayers/openlayers/pull/10767) - Replace Bing layer with MapTiler in examples ([@mike-000](https://github.com/mike-000))
* [#10751](https://github.com/openlayers/openlayers/pull/10751) - Sort events / observables in all cases ([@MoonE](https://github.com/MoonE))
* [#10763](https://github.com/openlayers/openlayers/pull/10763) - TypeScript: Fix inconsistent optionality in various APIs ([@jumpinjackie](https://github.com/jumpinjackie))
* [#10758](https://github.com/openlayers/openlayers/pull/10758) - Allow using feature attributes for symbol rotation in WebGL layers ([@jahow](https://github.com/jahow))
* [#10748](https://github.com/openlayers/openlayers/pull/10748) - Fix "Cannot read property 'anchor' of undefined" in ol/View ([@mike-000](https://github.com/mike-000))
* [#10746](https://github.com/openlayers/openlayers/pull/10746) - Fix building apidoc on windows ([@MoonE](https://github.com/MoonE))
* [#10720](https://github.com/openlayers/openlayers/pull/10720) - Apidoc better search ([@MoonE](https://github.com/MoonE))
* [#10743](https://github.com/openlayers/openlayers/pull/10743) - Ignore user provided tile cache size when too small ([@ahocevar](https://github.com/ahocevar))
* [#10736](https://github.com/openlayers/openlayers/pull/10736) - Allow cluster source to unlisten from its source ([@M393](https://github.com/M393))
* [#10739](https://github.com/openlayers/openlayers/pull/10739) - Fix typo in trackpad timeout ([@ahocevar](https://github.com/ahocevar))
* [#10740](https://github.com/openlayers/openlayers/pull/10740) - Document tabindex behavior for MouseWheelZoom and DragPan ([@matthias-ccri](https://github.com/matthias-ccri))
* [#10738](https://github.com/openlayers/openlayers/pull/10738) - Fix text background decluttering ([@ahocevar](https://github.com/ahocevar))
* [#10715](https://github.com/openlayers/openlayers/pull/10715) - Fix disappearing graticule labels when rotation returns to 0 ([@mike-000](https://github.com/mike-000))
* [#10713](https://github.com/openlayers/openlayers/pull/10713) - Draw graticule labels in a postrender function ([@mike-000](https://github.com/mike-000))
* [#10711](https://github.com/openlayers/openlayers/pull/10711) - Make sure that optional args are typed accordingly ([@ahocevar](https://github.com/ahocevar))
* [#10710](https://github.com/openlayers/openlayers/pull/10710) - Fix stylefunction return type ([@ahocevar](https://github.com/ahocevar))
* [#10709](https://github.com/openlayers/openlayers/pull/10709) - Fix type and documentation of style function ([@ahocevar](https://github.com/ahocevar))
* [#10708](https://github.com/openlayers/openlayers/pull/10708) - Handle Select interactions with falsey select style ([@ahocevar](https://github.com/ahocevar))
* [#10707](https://github.com/openlayers/openlayers/pull/10707) - Get default projection for overview map from main map. ([@AugustusKling](https://github.com/AugustusKling))
* [#10699](https://github.com/openlayers/openlayers/pull/10699) - Make Select interaction work when there are multiple instances ([@ahocevar](https://github.com/ahocevar))
* [#10694](https://github.com/openlayers/openlayers/pull/10694) - Draw image with configured opacity ([@M393](https://github.com/M393))
* [#10703](https://github.com/openlayers/openlayers/pull/10703) - CI and test fixes ([@ahocevar](https://github.com/ahocevar))
* [#10698](https://github.com/openlayers/openlayers/pull/10698) - Shadow root ([@ahocevar](https://github.com/ahocevar))
* [#10688](https://github.com/openlayers/openlayers/pull/10688) - Publish type definition files ([@ahocevar](https://github.com/ahocevar))
* [#10691](https://github.com/openlayers/openlayers/pull/10691) - Do not exceed color range ([@ahocevar](https://github.com/ahocevar))
* [#10683](https://github.com/openlayers/openlayers/pull/10683) - Dispatch enterfullscreen and leavefullscreen from the FullScreen control ([@fredj](https://github.com/fredj))
* [#10676](https://github.com/openlayers/openlayers/pull/10676) - Document that overviewmap view must use same projection as main map ([@mike-000](https://github.com/mike-000))
* [#10678](https://github.com/openlayers/openlayers/pull/10678) - Add maxResolution option to ol/tilegrid.createXYZ() and ol/source/XYZ ([@mike-000](https://github.com/mike-000))
* [#10690](https://github.com/openlayers/openlayers/pull/10690) - Document minZoom and maxZoom options for all layers ([@mike-000](https://github.com/mike-000))
* [#10672](https://github.com/openlayers/openlayers/pull/10672) - Nicer mousewheel and trackpad zooming ([@ahocevar](https://github.com/ahocevar))
* [#10687](https://github.com/openlayers/openlayers/pull/10687) - Increase timeout in listenImage test ([@fredj](https://github.com/fredj))
* [#10684](https://github.com/openlayers/openlayers/pull/10684) - perf: only do expensive reload when texture changes ([@jellyedwards](https://github.com/jellyedwards))
* [#10675](https://github.com/openlayers/openlayers/pull/10675) - typo ([@jipexu](https://github.com/jipexu))
* [#10669](https://github.com/openlayers/openlayers/pull/10669) - More browser compatible Export Map example ([@mike-000](https://github.com/mike-000))
* [#10667](https://github.com/openlayers/openlayers/pull/10667) - Do not render label with the current linedash ([@ahocevar](https://github.com/ahocevar))
* [#10666](https://github.com/openlayers/openlayers/pull/10666) - Load polyfill before example specific scripts in examples template ([@mike-000](https://github.com/mike-000))
* [#6526](https://github.com/openlayers/openlayers/pull/6526) - Draw interaction: add abortDrawing method and drawabort event ([@tchandelle](https://github.com/tchandelle))
* [#10657](https://github.com/openlayers/openlayers/pull/10657) - Changelog for v6.2.1 ([@openlayers](https://github.com/openlayers))
<details>
<summary>Dependency Updates</summary>
* [#10855](https://github.com/openlayers/openlayers/pull/10855) - Bump rollup from 2.1.0 to 2.3.0 ([@openlayers](https://github.com/openlayers))
* [#10854](https://github.com/openlayers/openlayers/pull/10854) - Bump ol-mapbox-style from 6.1.0 to 6.1.1 ([@openlayers](https://github.com/openlayers))
* [#10853](https://github.com/openlayers/openlayers/pull/10853) - Bump buble from 0.19.8 to 0.20.0 ([@openlayers](https://github.com/openlayers))
* [#10852](https://github.com/openlayers/openlayers/pull/10852) - Bump webpack from 4.42.0 to 4.42.1 ([@openlayers](https://github.com/openlayers))
* [#10837](https://github.com/openlayers/openlayers/pull/10837) - Bump ol-mapbox-style from 6.0.1 to 6.1.0 ([@openlayers](https://github.com/openlayers))
* [#10836](https://github.com/openlayers/openlayers/pull/10836) - Bump coveralls from 3.0.9 to 3.0.11 ([@openlayers](https://github.com/openlayers))
* [#10835](https://github.com/openlayers/openlayers/pull/10835) - Bump @babel/preset-env from 7.8.7 to 7.9.0 ([@openlayers](https://github.com/openlayers))
* [#10834](https://github.com/openlayers/openlayers/pull/10834) - Bump rollup from 1.32.1 to 2.1.0 ([@openlayers](https://github.com/openlayers))
* [#10833](https://github.com/openlayers/openlayers/pull/10833) - Bump fs-extra from 8.1.0 to 9.0.0 ([@openlayers](https://github.com/openlayers))
* [#10832](https://github.com/openlayers/openlayers/pull/10832) - Bump @babel/core from 7.8.7 to 7.9.0 ([@openlayers](https://github.com/openlayers))
* [#10831](https://github.com/openlayers/openlayers/pull/10831) - Bump babel-loader from 8.0.6 to 8.1.0 ([@openlayers](https://github.com/openlayers))
* [#10830](https://github.com/openlayers/openlayers/pull/10830) - Bump mocha from 7.1.0 to 7.1.1 ([@openlayers](https://github.com/openlayers))
* [#10829](https://github.com/openlayers/openlayers/pull/10829) - Bump marked from 0.8.0 to 0.8.2 ([@openlayers](https://github.com/openlayers))
* [#10811](https://github.com/openlayers/openlayers/pull/10811) - Bump sinon from 9.0.0 to 9.0.1 ([@openlayers](https://github.com/openlayers))
* [#10810](https://github.com/openlayers/openlayers/pull/10810) - Bump rollup-plugin-terser from 5.2.0 to 5.3.0 ([@openlayers](https://github.com/openlayers))
* [#10809](https://github.com/openlayers/openlayers/pull/10809) - Bump yargs from 15.3.0 to 15.3.1 ([@openlayers](https://github.com/openlayers))
* [#10806](https://github.com/openlayers/openlayers/pull/10806) - [Security] Bump acorn from 6.1.1 to 6.4.1 ([@openlayers](https://github.com/openlayers))
* [#10755](https://github.com/openlayers/openlayers/pull/10755) - Bump rollup from 1.31.1 to 1.32.0 ([@openlayers](https://github.com/openlayers))
* [#10754](https://github.com/openlayers/openlayers/pull/10754) - Bump @babel/preset-env from 7.8.4 to 7.8.6 ([@openlayers](https://github.com/openlayers))
* [#10753](https://github.com/openlayers/openlayers/pull/10753) - Bump mocha from 7.0.1 to 7.1.0 ([@openlayers](https://github.com/openlayers))
* [#10752](https://github.com/openlayers/openlayers/pull/10752) - Bump @babel/core from 7.8.4 to 7.8.6 ([@openlayers](https://github.com/openlayers))
* [#10725](https://github.com/openlayers/openlayers/pull/10725) - Bump elm-pep from 1.0.4 to 1.0.6 ([@openlayers](https://github.com/openlayers))
* [#10726](https://github.com/openlayers/openlayers/pull/10726) - Bump sinon from 8.1.1 to 9.0.0 ([@openlayers](https://github.com/openlayers))
* [#10680](https://github.com/openlayers/openlayers/pull/10680) - Bump terser-webpack-plugin from 2.3.4 to 2.3.5 ([@openlayers](https://github.com/openlayers))
* [#10682](https://github.com/openlayers/openlayers/pull/10682) - Bump webpack from 4.41.5 to 4.41.6 ([@openlayers](https://github.com/openlayers))
* [#10681](https://github.com/openlayers/openlayers/pull/10681) - Bump webpack-cli from 3.3.10 to 3.3.11 ([@openlayers](https://github.com/openlayers))
* [#10679](https://github.com/openlayers/openlayers/pull/10679) - Bump rollup from 1.31.0 to 1.31.1 ([@openlayers](https://github.com/openlayers))
</details>

View File

@@ -4,7 +4,7 @@
*/
exports.defineTags = function(dictionary) {
dictionary.defineTag('api', {
mustHaveValue: false,
mustNotHaveValue: true,
canHaveType: false,
canHaveName: false,
onTagged: function(doclet, tag) {
@@ -21,15 +21,11 @@ exports.defineTags = function(dictionary) {
* from the documentation.
*/
const api = [];
const api = {};
const classes = {};
const types = {};
const modules = {};
function hasApiMembers(doclet) {
return doclet.longname.split('#')[0] == this.longname;
}
function includeAugments(doclet) {
// Make sure that `observables` and `fires` are taken from an already processed `class` doclet.
// This is necessary because JSDoc generates multiple doclets with the same longname.
@@ -77,9 +73,6 @@ function includeAugments(doclet) {
});
}
cls._hideConstructor = true;
if (!cls.undocumented) {
cls._documented = true;
}
}
}
}
@@ -110,16 +103,43 @@ function includeTypes(doclet) {
}
}
const defaultExports = {};
const path = require('path');
const moduleRoot = path.join(process.cwd(), 'src');
// Tag default exported Identifiers because their name should be the same as the module name.
exports.astNodeVisitor = {
visitNode: function(node, e, parser, currentSourceName) {
if (node.parent && node.parent.type === 'ExportDefaultDeclaration') {
const modulePath = path.relative(moduleRoot, currentSourceName).replace(/\.js$/, '');
const exportName = 'module:' + modulePath.replace(/\\/g, '/') + (node.name ? '~' + node.name : '');
defaultExports[exportName] = true;
}
}
};
function sortOtherMembers(doclet) {
if (doclet.fires) {
doclet.fires.sort(function(a, b) {
return a.split(/#?event:/)[1] < b.split(/#?event:/)[1] ? -1 : 1;
});
}
if (doclet.observables) {
doclet.observables.sort(function(a, b) {
return a.name < b.name ? -1 : 1;
});
}
}
exports.handlers = {
newDoclet: function(e) {
const doclet = e.doclet;
if (doclet.stability) {
modules[doclet.longname.split(/[~\.]/).shift()] = true;
api.push(doclet);
api[doclet.longname.split('#')[0]] = true;
}
if (doclet.kind == 'class') {
modules[doclet.longname.split(/[~\.]/).shift()] = true;
if (!(doclet.longname in classes)) {
classes[doclet.longname] = doclet;
} else if ('augments' in doclet) {
@@ -134,22 +154,14 @@ exports.handlers = {
parseComplete: function(e) {
const doclets = e.doclets;
const byLongname = doclets.index.longname;
for (let i = doclets.length - 1; i >= 0; --i) {
const doclet = doclets[i];
if (doclet.stability) {
if (doclet.kind == 'class') {
includeAugments(doclet);
}
if (doclet.fires) {
doclet.fires.sort(function(a, b) {
return a.split(/#?event:/)[1] < b.split(/#?event:/)[1] ? -1 : 1;
});
}
if (doclet.observables) {
doclet.observables.sort(function(a, b) {
return a.name < b.name ? -1 : 1;
});
}
sortOtherMembers(doclet);
// Always document namespaces and items with stability annotation
continue;
}
@@ -160,20 +172,32 @@ exports.handlers = {
if (doclet.isEnum || doclet.kind == 'typedef') {
continue;
}
if (doclet.kind == 'class' && api.some(hasApiMembers, doclet)) {
if (doclet.kind == 'class' && doclet.longname in api) {
// Mark undocumented classes with documented members as unexported.
// This is used in ../template/tmpl/container.tmpl to hide the
// constructor from the docs.
doclet._hideConstructor = true;
includeAugments(doclet);
} else if (!doclet._hideConstructor && !(doclet.kind == 'typedef' && doclet.longname in types)) {
sortOtherMembers(doclet);
} else if (!doclet._hideConstructor) {
// Remove all other undocumented symbols
doclet.undocumented = true;
}
if (doclet._documented) {
delete doclet.undocumented;
if (doclet.memberof && byLongname[doclet.memberof] &&
byLongname[doclet.memberof][0].isEnum &&
!byLongname[doclet.memberof][0].properties.some(p => p.stability)) {
byLongname[doclet.memberof][0].undocumented = true;
}
}
},
processingComplete(e) {
const byLongname = e.doclets.index.longname;
for (const name in defaultExports) {
byLongname[name].forEach(function(doclet) {
doclet.isDefaultExport = true;
});
}
}
};

View File

@@ -5,7 +5,7 @@
exports.defineTags = function(dictionary) {
dictionary.defineTag('inheritDoc', {
mustHaveValue: false,
mustNotHaveValue: true,
canHaveType: false,
canHaveName: false,
onTagged: function(doclet, tag) {
@@ -42,62 +42,62 @@ exports.handlers = {
parseComplete: function(e) {
let ancestors, candidate, candidates, doclet, i, j, k, l, key;
let incompleteDoclet, stability, incomplete, incompletes;
let stability, incomplete, incompletes;
const doclets = e.doclets;
for (i = doclets.length - 1; i >= 0; --i) {
doclet = doclets[i];
if (doclet.augments) {
ancestors = [].concat(doclet.augments);
}
incompletes = incompleteByClass[doclet.longname];
if (ancestors && incompletes) {
// collect ancestors from the whole hierarchy
for (j = 0; j < ancestors.length; ++j) {
candidates = lookup[ancestors[j]];
if (candidates) {
for (k = candidates.length - 1; k >= 0; --k) {
candidate = candidates[k];
if (candidate.augments) {
ancestors = ancestors.concat(candidate.augments);
}
if (!doclet.augments || !incompletes) {
continue;
}
ancestors = doclet.augments.slice();
// collect ancestors from the whole hierarchy
for (j = 0; j < ancestors.length; ++j) {
candidates = lookup[ancestors[j]];
if (candidates) {
for (k = candidates.length - 1; k >= 0; --k) {
candidate = candidates[k];
if (candidate.augments) {
Array.prototype.push.apply(ancestors, candidate.augments);
}
}
}
// walk through all inheritDoc members
for (j = incompletes.length - 1; j >= 0; --j) {
incomplete = incompletes[j];
candidates = lookup[doclet.longname + '#' + incomplete];
if (candidates) {
// get the incomplete doclet that needs to be augmented
for (k = candidates.length - 1; k >= 0; --k) {
incompleteDoclet = candidates[k];
if (incompleteDoclet.inheritdoc) {
break;
}
}
// walk through all inheritDoc members
let incompleteDoclet;
for (j = incompletes.length - 1; j >= 0; --j) {
incomplete = incompletes[j];
candidates = lookup[doclet.longname + '#' + incomplete];
if (candidates) {
// get the incomplete doclet that needs to be augmented
for (k = candidates.length - 1; k >= 0; --k) {
incompleteDoclet = candidates[k];
if (incompleteDoclet.inheritdoc) {
break;
}
}
// find the documented ancestor
for (k = ancestors.length - 1; k >= 0; --k) {
candidates = lookup[ancestors[k] + '#' + incomplete];
if (candidates) {
for (l = candidates.length - 1; l >= 0; --l) {
candidate = candidates[l];
if (candidate && !candidate.inheritdoc) {
stability = candidate.stability || incompleteDoclet.stability;
if (stability) {
incompleteDoclet.stability = stability;
for (key in candidate) {
if (candidate.hasOwnProperty(key) &&
keepKeys.indexOf(key) == -1) {
incompleteDoclet[key] = candidate[key];
}
}
// find the documented ancestor
for (k = ancestors.length - 1; k >= 0; --k) {
candidates = lookup[ancestors[k] + '#' + incomplete];
if (candidates) {
for (l = candidates.length - 1; l >= 0; --l) {
candidate = candidates[l];
if (candidate && !candidate.inheritdoc) {
stability = candidate.stability || incompleteDoclet.stability;
if (stability) {
incompleteDoclet.stability = stability;
for (key in candidate) {
if (candidate.hasOwnProperty(key) &&
keepKeys.indexOf(key) == -1) {
incompleteDoclet[key] = candidate[key];
}
// We have found a matching parent doc and applied it so we
// don't want to ignore this doclet anymore.
incompleteDoclet.ignore = false;
// We found a match so we can stop break
break;
}
// We have found a matching parent doc and applied it so we
// don't want to ignore this doclet anymore.
incompleteDoclet.ignore = false;
// We found a match so we can stop break
break;
}
}
}

View File

@@ -14,7 +14,6 @@ const path = require('jsdoc/lib/jsdoc/path');
const taffy = require('taffydb').taffy;
const handle = require('jsdoc/lib/jsdoc/util/error').handle;
const helper = require('jsdoc/lib/jsdoc/util/templateHelper');
const _ = require('underscore');
const htmlsafe = helper.htmlsafe;
const linkto = helper.linkto;
const resolveAuthorLinks = helper.resolveAuthorLinks;
@@ -188,6 +187,14 @@ function attachModuleSymbols(doclets, modules) {
});
}
function getPrettyName(doclet) {
const fullname = doclet.longname.replace('module:', '');
if (doclet.isDefaultExport) {
return fullname.split('~')[0];
}
return fullname;
}
/**
* Create the navigation sidebar.
* @param {object} members The members that will be used to create the sidebar.
@@ -203,27 +210,13 @@ function attachModuleSymbols(doclets, modules) {
*/
function buildNav(members) {
const nav = [];
// merge namespaces and classes, then sort
const merged = members.modules.concat(members.classes);
merged.sort(function(a, b) {
if (a.longname > b.longname) {
return 1;
}
if (a.longname < b.longname) {
return -1;
}
return 0;
});
_.each(merged, function(v) {
members.classes.forEach(function(v) {
// exclude interfaces from sidebar
if (v.interface !== true && v.kind === 'class') {
if (v.interface !== true) {
nav.push({
type: 'class',
longname: v.longname,
prettyname: v.longname
.split('~')[0]
.replace('module:', ''),
prettyname: getPrettyName(v),
name: v.name,
module: find({
kind: 'module',
@@ -247,45 +240,57 @@ function buildNav(members) {
memberof: v.longname
})
});
} else if (v.kind == 'module') {
const classes = find({
kind: 'class',
memberof: v.longname
});
const members = find({
kind: 'member',
memberof: v.longname
});
const methods = find({
kind: 'function',
memberof: v.longname
});
const typedefs = find({
kind: 'typedef',
memberof: v.longname
});
const events = find({
kind: 'event',
memberof: v.longname
});
// only add modules that have more to show than just a single class
if (classes.length !== 1 && (classes.length + members.length + methods.length + typedefs.length + events.length > 0)) {
nav.push({
type: 'module',
longname: v.longname,
prettyname: v.longname
.split('~')[0]
.replace('module:', ''),
name: v.name,
members: members,
methods: methods,
typedefs: typedefs,
fires: v.fires,
events: events
});
}
}
});
members.modules.forEach(function(v) {
const classes = find({
kind: 'class',
memberof: v.longname
});
const members = find({
kind: 'member',
memberof: v.longname
});
const methods = find({
kind: 'function',
memberof: v.longname
});
const typedefs = find({
kind: 'typedef',
memberof: v.longname
});
const events = find({
kind: 'event',
memberof: v.longname
});
// Only add modules that contain more than just classes with their
// associated Options typedef
if (typedefs.length > classes.length || members.length + methods.length > 0) {
nav.push({
type: 'module',
longname: v.longname,
prettyname: getPrettyName(v),
name: v.name,
members: members,
methods: methods,
typedefs: typedefs,
fires: v.fires,
events: events
});
}
});
nav.sort(function(a, b) {
const prettyNameA = a.prettyname.toLowerCase();
const prettyNameB = b.prettyname.toLowerCase();
if (prettyNameA > prettyNameB) {
return 1;
}
if (prettyNameA < prettyNameB) {
return -1;
}
return 0;
});
return nav;
}
@@ -472,6 +477,7 @@ exports.publish = function(taffyData, opts, tutorials) {
// index page displays information from package.json and lists files
const files = find({kind: 'file'});
view.navigationHtml = helper.resolveLinks(view.partial('navigation.tmpl'));
generate('Index',
[{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}].concat(files),
indexUrl);

View File

@@ -1,99 +1,258 @@
$(function () {
// Search Items
$('#include_modules').change(function (e) {
console.log('change');
if ($(this).is(':checked')) {
'use strict';
// Allow user configuration?
const allowRegex = true;
const minInputForSearch = 1;
const minInputForFullText = 2;
const expandAllOnInputWithoutSearch = true;
function constructRegex(searchTerm, makeRe, allowRegex) {
try {
if (allowRegex) {
return makeRe(searchTerm);
}
} catch (e) {
}
// In case of invalid regexp fall back to non-regexp, but still allow . to match /
return makeRe(searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\\\./g, '[./]'));
}
function getWeightFunction(searchTerm, allowRegex) {
function makeRe(searchTerm) {
return {
begin: new RegExp('\\b' + searchTerm), // Begin matches word boundary
baseName: new RegExp('\\b' + searchTerm + '[^/]*$'), // Begin matches word boundary of class / module name
fullName: new RegExp('\\b' + searchTerm + '(?:[~.]|$)'), // Complete word(s) of class / module matches
completeName: new RegExp('^' + searchTerm + '$') // Match from start to finish
}
}
const re = constructRegex(searchTerm, makeRe, allowRegex);
return function (matchedItem, beginOnly) {
// We could get smarter on the weight here
const name = matchedItem.dataset.name;
if (beginOnly) {
return re.baseName.test(name) ? 100 : 1;
}
// If everything else is equal, prefer shorter names, and prefer classes over modules
let weight = 10000 + matchedItem.dataset.longname.length - name.length * 100;
if (name.match(re.begin)) {
weight += 10000;
if (re.baseName.test(name)) {
weight += 10000;
if (re.fullName.test(name)) {
weight += 10000;
if (re.completeName.test(name)) {
weight += 10000;
}
}
}
}
return weight;
}
}
const search = (function () {
const $navList = $('.navigation-list');
const navListNode = $navList.get(0);
let $classItems;
let $members;
let stateClass = (function () {
$navList.removeClass('search-started searching');
$navList.addClass('search-empty');
return 'search-empty';
})();
let manualToggles = {};
// Show an item related a current documentation automatically
const longname = $('.page-title').data('filename')
.replace(/\.[a-z]+$/, '')
.replace('module-', 'module:')
.replace(/_/g, '/')
.replace(/-/g, '~');
const currentItem = navListNode.querySelector('.item[data-longname="' + longname + '"]');
if (currentItem) {
$navList.prepend(currentItem);
}
return {
$navList: $navList,
$currentItem: currentItem ? $(currentItem) : undefined,
lastSearchTerm: undefined,
lastState: {},
getClassList: function () {
return $classItems || ($classItems = $navList.find('li.item'));
},
getMembers: function () {
return $members || ($members = $navList.find('.item li'));
},
changeStateClass: function (newClass) {
if (newClass !== stateClass) {
navListNode.classList.remove(stateClass);
navListNode.classList.add(newClass);
stateClass = newClass;
}
},
manualToggle: function ($node, show) {
$node.addClass('toggle-manual');
$node.toggleClass('toggle-manual-hide', !show);
$node.toggleClass('toggle-manual-show', show);
manualToggles[$node.data('longname')] = $node;
},
clearManualToggles: function() {
for (let clsName in manualToggles) {
manualToggles[clsName].removeClass('toggle-manual toggle-manual-show toggle-manual-hide');
}
manualToggles = {};
},
};
})();
const dummy = {subItems: {}};
function clearOldMatches(lastState, searchState) {
for (let itemName in lastState) {
const lastItem = lastState[itemName];
const item = searchState[itemName];
if (!item) {
lastItem.item.classList.remove('match');
}
if (lastItem.subItems) {
clearOldMatches(lastItem.subItems, (item || dummy).subItems);
}
}
}
function doSearch(searchTerm) {
searchTerm = searchTerm.toLowerCase();
const lastSearchTerm = search.lastSearchTerm;
if (searchTerm === lastSearchTerm) {
return;
}
// Avoid layout reflow by scrolling to top first.
search.$navList.scrollTop(0);
search.lastSearchTerm = searchTerm;
search.clearManualToggles();
if (searchTerm.length < minInputForSearch) {
const state = searchTerm.length && expandAllOnInputWithoutSearch ? 'search-started' : 'search-empty';
search.changeStateClass(state);
if (lastSearchTerm !== undefined && lastSearchTerm.length >= minInputForSearch) {
// Restore the original, sorted order
search.$navList.append(search.getClassList());
}
if (state === 'search-empty' && search.$currentItem) {
search.manualToggle(search.$currentItem, true);
}
} else {
}
});
var getSearchWeight = function (searchTerm, $matchedItem) {
let weight = 0;
// We could get smarter on the weight here
if ($matchedItem.data('shortname')
&& $matchedItem.data('shortname').toLowerCase() === searchTerm.toLowerCase()) {
weight++;
}
return weight;
};
// sort function callback
var weightSorter = function (a, b) {
var aW = $(a).data('weight') || 0;
var bW = $(b).data('weight') || 0;
return bW - aW;
};
// Search Items
$('#search').on('keyup', function (e) {
var value = $(this).val();
var $el = $('.navigation');
if (value && value.length > 1) {
var regexp = new RegExp(value, 'i');
$el.find('li, .itemMembers').hide();
$el.find('li').each(function (i, v) {
const $item = $(v);
const name = $item.data('name');
if (name && regexp.test(name)) {
const $classEntry = $item.closest('.item');
const $members = $item.closest('.itemMembers');
// Do the weight thing
$classEntry.removeData('weight');
$classEntry.show();
const weight = getSearchWeight(value, $classEntry);
$classEntry.data('weight', weight);
$members.show();
$classEntry.show();
$item.show();
search.changeStateClass('searching');
searchTerm = searchTerm.toLowerCase();
const beginOnly = searchTerm.length < minInputForFullText;
const getSearchWeight = getWeightFunction(searchTerm, allowRegex);
const re = constructRegex(searchTerm, function (searchTerm) {
return new RegExp((beginOnly ? '\\b' : '') + searchTerm);
}, allowRegex);
const navList = search.$navList.get(0);
const classes = [];
const searchState = {};
search.getClassList().each(function (i, classEntry) {
const className = classEntry.dataset.longname;
if (!(className in searchState) && re.test(classEntry.dataset.name)) {
const cls = searchState[className] = {
item: classEntry,
// Do the weight thing
weight: getSearchWeight(classEntry, beginOnly) * 100000,
subItems: {}
};
classes.push(cls);
classEntry.classList.add('match');
}
});
search.getMembers().each(function (i, li) {
const name = li.dataset.name;
if (re.test(name)) {
const itemMember = li.parentElement.parentElement;
const classEntry = itemMember.parentElement;
const className = classEntry.dataset.longname;
let cls = searchState[className];
if (!cls) {
cls = searchState[className] = {
item: classEntry,
weight: 0,
subItems: {}
};
classes.push(cls);
classEntry.classList.add('match');
}
cls.weight += getSearchWeight(li, true);
const memberType = itemMember.dataset.type;
let members = cls.subItems[memberType];
if (!members) {
members = cls.subItems[memberType] = {
item: itemMember,
subItems: {}
};
itemMember.classList.add('match');
}
members.subItems[name] = { item: li };
li.classList.add('match');
}
});
clearOldMatches(search.lastState, searchState);
search.lastState = searchState;
$(".navigation ul.list li.item:visible")
.sort(weightSorter) // sort elements
.appendTo(".navigation ul.list"); // append again to the list
} else {
$el.find('.item, .itemMembers').show();
classes.sort(function (a, b) {
return a.weight - b.weight;
});
for (let i = classes.length - 1; i >= 0; --i) {
navList.appendChild(classes[i].item);
}
}
}
$el.find('.list').scrollTop(0);
});
const searchInput = $('#search').get(0);
// Skip searches when typing fast.
let key;
function queueSearch() {
if (!key) {
key = setTimeout(function () {
key = undefined;
const searchTerm = searchInput.value;
doSearch(searchTerm);
}, 0);
}
}
// Search Items
searchInput.addEventListener('input', queueSearch);
doSearch(searchInput.value);
// Toggle when click an item element
$('.navigation').on('click', '.toggle', function (e) {
$(this).parent().parent().find('.itemMembers').toggle();
search.$navList.on('click', '.toggle', function (e) {
if (event.target.tagName.toLowerCase() === 'a') {
return;
}
const clsItem = $(this).closest('.item');
let show;
if (clsItem.hasClass('toggle-manual-show')) {
show = false;
} else if (clsItem.hasClass('toggle-manual-hide')) {
show = true;
} else {
clsItem.find('.member-list li').each(function (i, v) {
show = $(v).is(':hidden');
return !show;
});
}
search.manualToggle(clsItem, !!show);
});
// Show an item related a current documentation automatically
var filename = $('.page-title').data('filename')
.replace(/\.[a-z]+$/, '')
.replace('module-', 'module:')
.replace(/_/g, '/')
.replace(/-/g, '~');
var $currentItem = $('.navigation .item[data-name*="' + filename + '"]:eq(0)');
if ($currentItem.length) {
$currentItem
.remove()
.prependTo('.navigation .list')
.show()
.find('.itemMembers')
.show();
}
// Auto resizing on navigation
var _onResize = function () {
var height = $(window).height();
var $el = $('.navigation');
$el.height(height).find('.list').height(height - 133);
$el.height(height).find('.navigation-list').height(height - 133);
};
$(window).on('resize', _onResize);
@@ -137,22 +296,4 @@ $(function () {
'<a href="' + link + textParts[1].replace('line ', '#L') + '">' +
textParts[1] + '</a>';
});
// Highlighting current anchor
var anchors = $('.anchor');
var _onHashChange = function () {
var activeHash = window.document.location.hash
.replace(/\./g, '\\.') // Escape dot in element id
.replace(/\~/g, '\\~'); // Escape tilde in element id
anchors.removeClass('highlighted');
if (activeHash.length > 0) {
anchors.filter(activeHash).addClass('highlighted');
}
};
$(window).on('hashchange', _onHashChange);
_onHashChange();
});

View File

@@ -51,7 +51,8 @@ body {
width: 0px;
height: 0px;
}
.nameContainer .anchor.highlighted + h4 {
/* Highlighting current anchor */
.nameContainer .anchor:target + h4 {
background-color: #faebcc;
}
a {
@@ -123,7 +124,7 @@ li {
color: #fff;
border-color: #555;
}
.navigation .list {
.navigation .navigation-list {
padding: 10px 15px 0 15px;
position: relative;
overflow: auto;
@@ -135,6 +136,24 @@ li {
border-bottom: 1px solid #333;
}
.navigation .glyphicon {
margin-right: 3px;
flex-shrink: 0;
}
.navigation .item .glyphicon:before {
display: inline-block;
}
.navigation .item.toggle-manual .glyphicon:before {
transition: transform .1s;
}
.navigation .item-class.toggle-manual-show .glyphicon:before {
/* With 90deg the icon slightly slides left at transition end */
transform: rotate(89.9deg);
}
.navigation .item-module.toggle-manual-show .glyphicon:before {
transform: rotate(45deg);
}
.navigation li.perfect-match {
border: 5px solid orange;
}
@@ -147,8 +166,8 @@ li {
}
.navigation li.item .title {
cursor: pointer;
position: relative;
display: block;
display: -ms-flexbox;
display: flex;
font-size: 0.85em;
}
.navigation li.item .title a {
@@ -183,10 +202,42 @@ li {
padding-left: 8px;
margin-top: 2px;
}
.navigation li.item .itemMembers {
display: none;
.navigation li.item .member-list {
padding-left: 8px;
}
/* search state */
/* show all classes when search is empty */
.navigation-list.search-empty .item {
display: block;
}
/* hide all members by default when search is empty */
.navigation-list.search-empty .item .member-list {
display: none;
}
/* expand all members when input in search field available but too short to search */
.navigation-list.search-started li,
.navigation-list.search-started .member-list {
display: block;
}
/* when searching hide everything that is not a match */
.navigation-list.searching li,
.navigation-list.searching .member-list {
display: none;
}
.navigation-list.searching .match {
display: block;
}
/* allow user to hide / show members */
.navigation-list .item.toggle-manual-show li,
.navigation-list .item.toggle-manual-show .member-list {
display: block!important;
}
.navigation-list:not(.searching) .item.toggle-manual-hide li,
.navigation-list:not(.searching) .item.toggle-manual-hide .member-list {
display: none!important;
}
.main {
padding: 20px 20px;
margin-left: 250px;

View File

@@ -92,7 +92,7 @@ var version = obj.packageInfo.version;
</div>
<div id="wrap" class="clearfix">
<?js= this.partial('navigation.tmpl', this) ?>
<?js= this.navigationHtml ?>
<div class="main">
<h1 class="page-title" data-filename="<?js= filename ?>"><?js= title ?></h1>
<div id="latest-check" class="alert alert-warning alert-dismissible" role="alert" style="display:none">

View File

@@ -64,7 +64,7 @@ var self = this;
<ul><?js fires.forEach(function(f) {
var parts = f.split(/#?event:/);
var type = parts.pop();
var eventClassName = parts[0];
var eventClass = self.find({longname: parts[0]})[0];
parts = type.split(' ');
type = parts.shift();
var description = parts.length ? parts.join(' ') : '';
@@ -74,12 +74,9 @@ var self = this;
}
?>
<li class="<?js= (eventDoclet || data).stability !== 'stable' ? 'unstable' : '' ?>">
<code><?js= eventClassName ? self.linkto(f, type) : type ?></code>
<?js if (eventClassName) {
var eventClass = self.find({longname: eventClassName})[0];
if (eventClass) { ?>
(<?js= self.linkto(eventClass.longname) ?>)
<?js } ?>
<code><?js= eventClass ? self.linkto(f, type) : type ?></code>
<?js if (eventClass) { ?>
(<?js= self.linkto(eventClass.longname) ?>)
<?js } ?>
<?js= self.partial('stability.tmpl', eventDoclet || (data.stability ? data : {})) ?>
<?js if (description) { ?> -

View File

@@ -1,95 +1,59 @@
<?js
var self = this;
function toShortName(name) {
return name.indexOf('module:') === 0 ? name.split('/').pop() : name;
}
function getItemCssClass(type) {
if (type === 'module') {
return 'glyphicon-plus';
} else if (type === 'class') {
return 'glyphicon-chevron-right';
}
return '';
}
const printList = v => { ?>
<li data-name="<?js= toShortName(v.name).toLowerCase() ?>"><?js
}
const printListWithStability = v => {
const cls = v.stability && v.stability !== 'stable' ? ' class="unstable"' : ''; ?>
<li data-name="<?js= toShortName(v.name).toLowerCase() ?>"<?js= cls ?>><?js
}
function listContent(item, title, listItemPrinter) {
const type = title.toLowerCase();
if (item[type] && item[type].length) { ?>
<div class="member-list" data-type="<?js= type ?>">
<span class="subtitle"><?js= title ?></span>
<ul><?js
item[type].forEach(function (v) {
listItemPrinter(v); ?><?js= self.linkto(v.longname, toShortName(v.name)) ?><?js
}); ?>
</ul>
</div><?js
}
}
?>
<div class="navigation">
<div class="search">
<input id="search" type="text" class="form-control input-sm" placeholder="Search Documentation">
</div>
<ul class="list">
<?js
this.nav.forEach(function (item) {
?>
<li class="item" data-name="<?js= item.longname ?>" data-shortname="<?js= item.name.toLowerCase() ?>">
<span class="title">
<?js if (item.type === 'module') { ?>
<span class="glyphicon glyphicon-plus toggle"></span>
<?js } else if (item.type === 'class') { ?>
<span class="glyphicon glyphicon-chevron-right toggle"></span>
<?js } ?>
<?js= self.linkto(item.longname, item.prettyname) ?>
<?js if (item.type === 'namespace' &&
(item.members.length + item.typedefs.length + item.methods.length +
item.events.length > 0)) { ?>
<?js } ?>
</span>
<ul class="members itemMembers">
<?js
if (item.members.length) {
?>
<span class="subtitle">Members</span>
<?js
item.members.forEach(function (v) {
?>
<li data-name="<?js= v.longname ?>"><?js= self.linkto(v.longname, toShortName(v.name)) ?></li>
<?js
});
}
?>
</ul>
<ul class="typedefs itemMembers">
<?js
if (item.typedefs.length) {
?>
<span class="subtitle">Typedefs</span>
<?js
item.typedefs.forEach(function (v) {
?>
<li data-name="<?js= v.longname ?>" class="<?js= (v.stability && v.stability !== 'stable') ? 'unstable' : ''?>">
<?js= self.linkto(v.longname, toShortName(v.name)) ?>
</li>
<?js
});
}
?>
</ul>
<ul class="methods itemMembers">
<?js
if (item.methods.length) {
?>
<span class="subtitle">Methods</span>
<?js
item.methods.forEach(function (v) {
?>
<li data-name="<?js= v.longname ?>" class="<?js= (v.stability && v.stability !== 'stable') ? 'unstable' : ''?>">
<?js= self.linkto(v.longname, toShortName(v.name)) ?>
</li>
<?js
});
}
?>
</ul>
<ul class="fires itemMembers">
<?js
if (item.fires && item.fires.length) {
?>
<span class="subtitle">Fires</span>
<?js
item.fires.forEach(function (v) {
v = self.find({longname: v})[0] || {longname: v, name: v.split(/#?event:/)[1]};
?>
<li data-name="<?js= v.longname ?>" class="<?js= (v.stability && v.stability != 'stable') ? 'unstable' : '' ?>">
<?js= self.linkto(v.longname, toShortName(v.name)) ?>
</li>
<?js
});
}
?>
</ul>
</li>
<?js }); ?>
<ul class="navigation-list search-empty"><?js
this.nav.forEach(function (item) { ?>
<li class="item item-<?js= item.type ?>" data-longname="<?js= item.longname ?>" data-name="<?js= item.prettyname.toLowerCase() ?>">
<span class="title toggle">
<span class="glyphicon <?js= getItemCssClass(item.type) ?>"></span>
<span><?js= self.linkto(item.longname, item.prettyname.replace(/[.~]/g, '\u200b$&')) ?></span>
</span><?js
listContent(item, 'Members', printList);
listContent(item, 'Typedefs', printListWithStability);
listContent(item, 'Methods', printListWithStability);
if (item.fires) {
const fires = item.fires.map(v => self.find({longname: v})[0] || {longname: v, name: v.split(/#?event:/)[1]});
listContent({fires: fires}, 'Fires', printListWithStability)
}
}); ?>
</ul>
</div>

View File

@@ -6,7 +6,7 @@ exports.defineTags = function(dictionary) {
const classTag = dictionary.lookUp('class');
dictionary.defineTag('interface', {
mustHaveValue: false,
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
classTag.onTagged.apply(this, arguments);
doclet.virtual = true;

View File

@@ -7,8 +7,8 @@
"allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "../build/ol", /* Redirect output structure to the directory. */

View File

@@ -245,3 +245,7 @@ Layer opacity must be a number.
`forEachFeatureAtCoordinate` cannot be used on a WebGL layer if the hit detection logic has not been enabled.
This is done by providing adequate shaders using the `hitVertexShader` and `hitFragmentShader` properties of `WebGLPointsLayerRenderer`.
### 67
A layer can only be added to the map once. Use either `layer.setMap()` or `map.addLayer()`, not both.

View File

@@ -6,7 +6,7 @@ docs: >
<p>When the Bing Maps tile service doesn't have tiles for a given resolution and region it returns "placeholder" tiles indicating that. Zoom the map beyond level 19 to see the "placeholder" tiles. If you want OpenLayers to display stretched tiles in place of "placeholder" tiles beyond zoom level 19 then set <code>maxZoom</code> to <code>19</code> in the options passed to <code>ol/source/BingMaps</code>.</p>
tags: "bing, bing-maps"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
---
<div id="map" class="map"></div>

View File

@@ -18,7 +18,7 @@ for (i = 0, ii = styles.length; i < ii; ++i) {
visible: false,
preload: Infinity,
source: new BingMaps({
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: styles[i]
// use maxZoom 19 to see stretched tiles instead of the BingMaps
// "no photos at this zoom level" tiles

View File

@@ -2,6 +2,6 @@
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
<g>
<rect width="20" height="20" style="fill:#fff" />
<rect width="20" height="20" style="fill:#fff; stroke-width:4px; stroke:#000" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 194 B

After

Width:  |  Height:  |  Size: 225 B

View File

@@ -4,10 +4,10 @@ title: Drag-and-Drop Image Vector
shortdesc: Example of using the drag-and-drop interaction with image vector rendering.
docs: >
Example of using the drag-and-drop interaction with an `ol/layer/VectorImage` layer. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. Each file is rendered to an image on the client.
tags: "drag-and-drop-image-vector, gpx, geojson, igc, kml, topojson, vector, image"
tags: "drag-and-drop-image-vector, gpx, geojson, igc, kml, topojson, maptiler, vector, image"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<div id="map" class="map"></div>
<div id="info">&nbsp;</div>

View File

@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
import {GPX, GeoJSON, IGC, KML, TopoJSON} from '../src/ol/format.js';
import {defaults as defaultInteractions, DragAndDrop} from '../src/ol/interaction.js';
import {VectorImage as VectorImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
import {BingMaps, Vector as VectorSource} from '../src/ol/source.js';
import {XYZ, Vector as VectorSource} from '../src/ol/source.js';
const dragAndDropInteraction = new DragAndDrop({
formatConstructors: [
@@ -15,13 +15,18 @@ const dragAndDropInteraction = new DragAndDrop({
]
});
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const map = new Map({
interactions: defaultInteractions().extend([dragAndDropInteraction]),
layers: [
new TileLayer({
source: new BingMaps({
imagerySet: 'Aerial',
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
source: new XYZ({
attributions: attributions,
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
maxZoom: 20
})
})
],

View File

@@ -4,10 +4,10 @@ title: Drag-and-Drop
shortdesc: Example of using the drag-and-drop interaction.
docs: >
Example of using the drag-and-drop interaction. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. There is no projection transform support, so this will only work with data in EPSG:4326 and EPSG:3857.
tags: "drag-and-drop, gpx, geojson, igc, kml, topojson"
tags: "drag-and-drop, gpx, geojson, igc, kml, topojson, maptiler"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<div id="map" class="map"></div>
<div id="info">&nbsp;</div>

View File

@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
import {GPX, GeoJSON, IGC, KML, TopoJSON} from '../src/ol/format.js';
import {defaults as defaultInteractions, DragAndDrop} from '../src/ol/interaction.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {BingMaps, Vector as VectorSource} from '../src/ol/source.js';
import {XYZ, Vector as VectorSource} from '../src/ol/source.js';
const dragAndDropInteraction = new DragAndDrop({
formatConstructors: [
@@ -15,13 +15,18 @@ const dragAndDropInteraction = new DragAndDrop({
]
});
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const map = new Map({
interactions: defaultInteractions().extend([dragAndDropInteraction]),
layers: [
new TileLayer({
source: new BingMaps({
imagerySet: 'Aerial',
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
source: new XYZ({
attributions: attributions,
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
maxZoom: 20
})
})
],

View File

@@ -1,7 +1,7 @@
---
layout: example.html
title: Earthquakes with custom symbols
shortdesc: Demonstrates the use of `toCanvas` to create custom icon symbols.
shortdesc: Demonstrates the use of `toContext` to create custom icon symbols.
docs: >
This example parses a KML file and renders the features as a vector layer. The layer is given a <code>style</code> that renders earthquake locations with a custom lightning symbol and a size relative to their magnitude.
tags: "KML, vector, style, canvas, symbol"

View File

@@ -0,0 +1,9 @@
---
layout: example.html
title: Custom map element
shortdesc: Example of a custom element with a map.
docs: >
The example creates and registers a custom element, `ol-map`, which contains a simple map. **Note:** Only works in browsers that supports `ShadowRoot`.
tags: "es2015, web-component, custom-element, shadow-dom"
---
<ol-map id="map" class="map"></ol-map>

View File

@@ -0,0 +1,43 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
class OLComponent extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({mode: 'open'});
const link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'css/ol.css');
this.shadow.appendChild(link);
const style = document.createElement('style');
style.innerText = `
:host {
display: block;
}
`;
this.shadow.appendChild(style);
const div = document.createElement('div');
div.style.width = '100%';
div.style.height = '100%';
this.shadow.appendChild(div);
this.map = new Map({
target: div,
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
center: [0, 0],
zoom: 2
})
});
}
}
customElements.define('ol-map', OLComponent);

View File

@@ -1,6 +0,0 @@
.overlay {
background-color: yellow;
border-radius: 6px;
padding: 4px;
white-space: nowrap;
}

View File

@@ -3,13 +3,9 @@ layout: example.html
title: Map Export
shortdesc: Example of exporting a map as a PNG image.
docs: >
Example of exporting a map as a PNG image. This example use the <a href="https://www.npmjs.com/package/html-to-image">html-to-image</a>
library.
Example of exporting a map as a PNG image.
tags: "export, png, openstreetmap"
---
<div id="map" class="map"></div>
<div style="display: none;">
<div class="overlay" id="null">Null Island</div>
</div>
<a id="export-png" class="btn btn-default"><i class="fa fa-download"></i> Download PNG</a>
<a id="image-download" download="map.png"></a>

View File

@@ -1,12 +1,9 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import Overlay from '../src/ol/Overlay.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {toPng} from 'html-to-image';
const map = new Map({
layers: [
new TileLayer({
@@ -16,7 +13,8 @@ const map = new Map({
source: new VectorSource({
url: 'data/geojson/countries.geojson',
format: new GeoJSON()
})
}),
opacity: 0.5
})
],
target: 'map',
@@ -26,28 +24,33 @@ const map = new Map({
})
});
map.addOverlay(new Overlay({
position: [0, 0],
element: document.getElementById('null')
}));
// export options for html-to-image.
// See: https://github.com/bubkoo/html-to-image#options
const exportOptions = {
filter: function(element) {
return element.className ? element.className.indexOf('ol-control') === -1 : true;
}
};
document.getElementById('export-png').addEventListener('click', function() {
map.once('rendercomplete', function() {
toPng(map.getTargetElement(), exportOptions)
.then(function(dataURL) {
const link = document.getElementById('image-download');
link.href = dataURL;
link.click();
});
const mapCanvas = document.createElement('canvas');
const size = map.getSize();
mapCanvas.width = size[0];
mapCanvas.height = size[1];
const mapContext = mapCanvas.getContext('2d');
Array.prototype.forEach.call(document.querySelectorAll('.ol-layer canvas'), function(canvas) {
if (canvas.width > 0) {
const opacity = canvas.parentNode.style.opacity;
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
const transform = canvas.style.transform;
// Get the transform parameters from the style's transform matrix
const matrix = transform.match(/^matrix\(([^\(]*)\)$/)[1].split(',').map(Number);
// Apply the transform to the export map context
CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
mapContext.drawImage(canvas, 0, 0);
}
});
if (navigator.msSaveBlob) {
// link download attribuute does not work on MS browsers
navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png');
} else {
const link = document.getElementById('image-download');
link.href = mapCanvas.toDataURL();
link.click();
}
});
map.renderSync();
});

View File

@@ -6,7 +6,7 @@ docs: >
Example of exporting a map as a PDF using the <a href="https://github.com/MrRio/jsPDF" target="_blank">jsPDF</a> library.
tags: "export, pdf, openstreetmap"
resources:
- https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js
- https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js
---
<div class="row-fluid">
<div class="span12">

View File

@@ -4,8 +4,6 @@ import WKT from '../src/ol/format/WKT.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {toJpeg} from 'html-to-image';
const raster = new TileLayer({
source: new OSM()
});
@@ -20,7 +18,8 @@ feature.getGeometry().transform('EPSG:4326', 'EPSG:3857');
const vector = new VectorLayer({
source: new VectorSource({
features: [feature]
})
}),
opacity: 0.5
});
@@ -44,14 +43,6 @@ const dims = {
};
// export options for html-to-image.
// See: https://github.com/bubkoo/html-to-image#options
const exportOptions = {
filter: function(element) {
return element.className.indexOf('ol-control') === -1;
}
};
const exportButton = document.getElementById('export-pdf');
exportButton.addEventListener('click', function() {
@@ -68,18 +59,30 @@ exportButton.addEventListener('click', function() {
const viewResolution = map.getView().getResolution();
map.once('rendercomplete', function() {
exportOptions.width = width;
exportOptions.height = height;
toJpeg(map.getViewport(), exportOptions).then(function(dataUrl) {
const pdf = new jsPDF('landscape', undefined, format);
pdf.addImage(dataUrl, 'JPEG', 0, 0, dim[0], dim[1]);
pdf.save('map.pdf');
// Reset original map size
map.setSize(size);
map.getView().setResolution(viewResolution);
exportButton.disabled = false;
document.body.style.cursor = 'auto';
const mapCanvas = document.createElement('canvas');
mapCanvas.width = width;
mapCanvas.height = height;
const mapContext = mapCanvas.getContext('2d');
Array.prototype.forEach.call(document.querySelectorAll('.ol-layer canvas'), function(canvas) {
if (canvas.width > 0) {
const opacity = canvas.parentNode.style.opacity;
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
const transform = canvas.style.transform;
// Get the transform parameters from the style's transform matrix
const matrix = transform.match(/^matrix\(([^\(]*)\)$/)[1].split(',').map(Number);
// Apply the transform to the export map context
CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
mapContext.drawImage(canvas, 0, 0);
}
});
const pdf = new jsPDF('landscape', undefined, format);
pdf.addImage(mapCanvas.toDataURL('image/jpeg'), 'JPEG', 0, 0, dim[0], dim[1]);
pdf.save('map.pdf');
// Reset original map size
map.setSize(size);
map.getView().setResolution(viewResolution);
exportButton.disabled = false;
document.body.style.cursor = 'auto';
});
// Set print size

View File

@@ -147,6 +147,7 @@ function updateView() {
view.setCenter(getCenterWithHeading(c, -c[2], view.getResolution()));
view.setRotation(-c[2]);
marker.setPosition(c);
map.render();
}
}

View File

@@ -25,6 +25,7 @@ rome.setStyle(new Style({
image: new Icon({
color: '#8959A8',
crossOrigin: 'anonymous',
imgSize: [20, 20],
src: 'data/square.svg'
})
}));

View File

@@ -4,10 +4,10 @@ title: KML
shortdesc: Rendering KML with a vector source.
docs: >
This example uses the <code>ol/format/KML</code> to parse KML for rendering with a vector source.
tags: "KML"
tags: "KML, maptiler"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<div id="map" class="map"></div>
<div id="info">&nbsp;</div>

View File

@@ -2,13 +2,18 @@ import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import KML from '../src/ol/format/KML.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import BingMaps from '../src/ol/source/BingMaps.js';
import XYZ from '../src/ol/source/XYZ.js';
import VectorSource from '../src/ol/source/Vector.js';
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const raster = new TileLayer({
source: new BingMaps({
imagerySet: 'Aerial',
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
source: new XYZ({
attributions: attributions,
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
maxZoom: 20
})
});

View File

@@ -0,0 +1,3 @@
#map {
background: transparent;
}

View File

@@ -0,0 +1,9 @@
---
layout: example.html
title: Vector Clipping Layer
shortdesc: Vector Clipping Layer example
docs: >
Example of a clipping layer based on a vector source
tags: "clipping, openstreetmap, vector"
---
<div id="map" class="map"></div>

View File

@@ -0,0 +1,46 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import VectorSource from '../src/ol/source/Vector.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import OSM from '../src/ol/source/OSM.js';
import {Fill, Style} from '../src/ol/style.js';
import {getVectorContext} from '../src/ol/render.js';
import {fromLonLat} from '../src/ol/proj.js';
const base = new TileLayer({
source: new OSM()
});
const clipLayer = new VectorLayer({
style: null,
source: new VectorSource({
url:
'./data/geojson/switzerland.geojson',
format: new GeoJSON()
})
});
const style = new Style({
fill: new Fill({
color: 'black'
})
});
base.on('postrender', function(e) {
e.context.globalCompositeOperation = 'destination-in';
const vectorContext = getVectorContext(e);
clipLayer.getSource().forEachFeature(function(feature) {
vectorContext.drawFeature(feature, style);
});
e.context.globalCompositeOperation = 'source-over';
});
const map = new Map({
layers: [base, clipLayer],
target: 'map',
view: new View({
center: fromLonLat([8.23, 46.86]),
zoom: 7
})
});

View File

@@ -0,0 +1,6 @@
.ol-rotate {
left: .5em;
bottom: .5em;
top: unset;
right: unset;
}

View File

@@ -1,5 +1,5 @@
---
layout: example-verbatim.html
layout: example.html
title: Vector tiles created from a Mapbox Style object
shortdesc: Example of using ol-mapbox-style with tiles from maptiler.com.
docs: >
@@ -10,26 +10,4 @@ cloak:
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>Mapbox Style objects with ol-mapbox-style</title>
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<style type="text/css">
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script src="common.js"></script>
<script src="mapbox-style.js"></script>
</body>
</html>
<div id="map" class="map"></div>

View File

@@ -1,3 +1,6 @@
import apply from 'ol-mapbox-style';
import FullScreen from '../src/ol/control/FullScreen.js';
apply('map', 'https://api.maptiler.com/maps/topo/style.json?key=get_your_own_D6rA4zTHduk6KOKTXzGB');
apply('map', 'https://api.maptiler.com/maps/topo/style.json?key=get_your_own_D6rA4zTHduk6KOKTXzGB').then(function(map) {
map.addControl(new FullScreen());
});

View File

@@ -4,7 +4,7 @@ title: Full-Screen Mobile
shortdesc: Example of a full screen map.
tags: "fullscreen, geolocation, mobile"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
---
<!doctype html>

View File

@@ -14,7 +14,7 @@ const map = new Map({
layers: [
new TileLayer({
source: new BingMaps({
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: 'RoadOnDemand'
})
})

View File

@@ -232,6 +232,7 @@ const map = new Map({
target: 'map',
view: new View({
center: [0, 1000000],
zoom: 2
zoom: 2,
multiWorld: true
})
});

View File

@@ -0,0 +1,9 @@
.map {
background: rgba(232, 230, 223, 1);
}
.ol-rotate {
left: .5em;
bottom: .5em;
top: unset;
right: unset;
}

View File

@@ -0,0 +1,10 @@
---
layout: example.html
title: Vector tiles rendered in an offscreen canvas
shortdesc: Example of a map that delegates rendering to a worker.
docs: >
The map in this example is rendered in a web worker, using `OffscreenCanvas`. **Note:** This is currently only supported in Chrome and Edge.
tags: "worker, offscreencanvas, vector-tiles"
experimental: true
---
<div id="map" class="map"></div>

View File

@@ -0,0 +1,125 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import Layer from '../src/ol/layer/Layer.js';
import Worker from 'worker-loader!./offscreen-canvas.worker.js'; //eslint-disable-line
import {compose, create} from '../src/ol/transform.js';
import {createTransformString} from '../src/ol/render/canvas.js';
import {createXYZ} from '../src/ol/tilegrid.js';
import {FullScreen} from '../src/ol/control.js';
import stringify from 'json-stringify-safe';
import Source from '../src/ol/source/Source.js';
const worker = new Worker();
let container, transformContainer, canvas, rendering, workerFrameState, mainThreadFrameState;
// Transform the container to account for the differnece between the (newer)
// main thread frameState and the (older) worker frameState
function updateContainerTransform() {
if (workerFrameState) {
const viewState = mainThreadFrameState.viewState;
const renderedViewState = workerFrameState.viewState;
const center = viewState.center;
const resolution = viewState.resolution;
const rotation = viewState.rotation;
const renderedCenter = renderedViewState.center;
const renderedResolution = renderedViewState.resolution;
const renderedRotation = renderedViewState.rotation;
const transform = create();
// Skip the extra transform for rotated views, because it will not work
// correctly in that case
if (!rotation) {
compose(transform,
(renderedCenter[0] - center[0]) / resolution,
(center[1] - renderedCenter[1]) / resolution,
renderedResolution / resolution, renderedResolution / resolution,
rotation - renderedRotation,
0, 0);
}
transformContainer.style.transform = createTransformString(transform);
}
}
const map = new Map({
layers: [
new Layer({
render: function(frameState) {
if (!container) {
container = document.createElement('div');
container.style.position = 'absolute';
container.style.width = '100%';
container.style.height = '100%';
transformContainer = document.createElement('div');
transformContainer.style.position = 'absolute';
transformContainer.style.width = '100%';
transformContainer.style.height = '100%';
container.appendChild(transformContainer);
canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
canvas.style.left = '0';
canvas.style.transformOrigin = 'top left';
transformContainer.appendChild(canvas);
}
mainThreadFrameState = frameState;
updateContainerTransform();
if (!rendering) {
rendering = true;
worker.postMessage({
action: 'render',
frameState: JSON.parse(stringify(frameState))
});
} else {
frameState.animate = true;
}
return container;
},
source: new Source({
attributions: [
'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a>',
'<a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>'
]
})
})
],
target: 'map',
view: new View({
resolutions: createXYZ({tileSize: 512}).getResolutions89,
center: [0, 0],
zoom: 2
})
});
map.addControl(new FullScreen());
// Worker messaging and actions
worker.addEventListener('message', message => {
if (message.data.action === 'loadImage') {
// Image loader for ol-mapbox-style
const image = new Image();
image.crossOrigin = 'anonymous';
image.addEventListener('load', function() {
createImageBitmap(image, 0, 0, image.width, image.height).then(imageBitmap => {
worker.postMessage({
action: 'imageLoaded',
image: imageBitmap,
src: message.data.src
}, [imageBitmap]);
});
});
image.src = event.data.src;
} else if (message.data.action === 'requestRender') {
// Worker requested a new render frame
map.render();
} else if (canvas && message.data.action === 'rendered') {
// Worker provies a new render frame
requestAnimationFrame(function() {
const imageData = message.data.imageData;
canvas.width = imageData.width;
canvas.height = imageData.height;
canvas.getContext('2d').drawImage(imageData, 0, 0);
canvas.style.transform = message.data.transform;
workerFrameState = message.data.frameState;
updateContainerTransform();
});
rendering = false;
}
});

View File

@@ -0,0 +1,136 @@
import VectorTileLayer from '../src/ol/layer/VectorTile.js';
import VectorTileSource from '../src/ol/source/VectorTile.js';
import MVT from '../src/ol/format/MVT.js';
import {Projection} from '../src/ol/proj.js';
import TileQueue from '../src/ol/TileQueue.js';
import {getTilePriority as tilePriorityFunction} from '../src/ol/TileQueue.js';
import {renderDeclutterItems} from '../src/ol/render.js';
import styleFunction from 'ol-mapbox-style/dist/stylefunction.js';
import {inView} from '../src/ol/layer/Layer.js';
import stringify from 'json-stringify-safe';
/** @type {any} */
const worker = self;
let frameState, pixelRatio, rendererTransform;
const canvas = new OffscreenCanvas(1, 1);
// OffscreenCanvas does not have a style, so we mock it
canvas.style = {};
const context = canvas.getContext('2d');
const sources = {
landcover: new VectorTileSource({
maxZoom: 9,
format: new MVT(),
url: 'https://api.maptiler.com/tiles/landcover/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
}),
contours: new VectorTileSource({
minZoom: 9,
maxZoom: 14,
format: new MVT(),
url: 'https://api.maptiler.com/tiles/contours/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
}),
openmaptiles: new VectorTileSource({
format: new MVT(),
maxZoom: 14,
url: 'https://api.maptiler.com/tiles/v3/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
})
};
const layers = [];
// Font replacement so we do not need to load web fonts in the worker
function getFont(font) {
return font[0]
.replace('Noto Sans', 'serif')
.replace('Roboto', 'sans-serif');
}
function loadStyles() {
const styleUrl = 'https://api.maptiler.com/maps/topo/style.json?key=get_your_own_D6rA4zTHduk6KOKTXzGB';
fetch(styleUrl).then(data => data.json()).then(styleJson => {
const buckets = [];
let currentSource;
styleJson.layers.forEach(layer => {
if (!layer.source) {
return;
}
if (currentSource !== layer.source) {
currentSource = layer.source;
buckets.push({
source: layer.source,
layers: []
});
}
buckets[buckets.length - 1].layers.push(layer.id);
});
const spriteUrl = styleJson.sprite + (pixelRatio > 1 ? '@2x' : '') + '.json';
const spriteImageUrl = styleJson.sprite + (pixelRatio > 1 ? '@2x' : '') + '.png';
fetch(spriteUrl).then(data => data.json()).then(spriteJson => {
buckets.forEach(bucket => {
const source = sources[bucket.source];
if (!source) {
return;
}
const layer = new VectorTileLayer({
declutter: true,
source,
minZoom: source.getTileGrid().getMinZoom()
});
layer.getRenderer().useContainer = function(target, transform) {
this.containerReused = this.getLayer() !== layers[0];
this.canvas = canvas;
this.context = context;
this.container = {
firstElementChild: canvas
};
rendererTransform = transform;
};
styleFunction(layer, styleJson, bucket.layers, undefined, spriteJson, spriteImageUrl, getFont);
layers.push(layer);
});
worker.postMessage({action: 'requestRender'});
});
});
}
// Minimal map-like functionality for rendering
const tileQueue = new TileQueue(
(tile, tileSourceKey, tileCenter, tileResolution) => tilePriorityFunction(frameState, tile, tileSourceKey, tileCenter, tileResolution),
() => worker.postMessage({action: 'requestRender'}));
const maxTotalLoading = 8;
const maxNewLoads = 2;
worker.addEventListener('message', event => {
if (event.data.action !== 'render') {
return;
}
frameState = event.data.frameState;
if (!pixelRatio) {
pixelRatio = frameState.pixelRatio;
loadStyles();
}
frameState.tileQueue = tileQueue;
frameState.viewState.projection.__proto__ = Projection.prototype;
layers.forEach(layer => {
if (inView(layer.getLayerState(), frameState.viewState)) {
const renderer = layer.getRenderer();
renderer.renderFrame(frameState, canvas);
}
});
renderDeclutterItems(frameState, null);
if (tileQueue.getTilesLoading() < maxTotalLoading) {
tileQueue.reprioritize();
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
}
const imageData = canvas.transferToImageBitmap();
worker.postMessage({
action: 'rendered',
imageData: imageData,
transform: rendererTransform,
frameState: JSON.parse(stringify(frameState))
}, [imageData]);
});

View File

@@ -6,7 +6,7 @@ docs: >
<p>The map on the top preloads low resolution tiles. The map on the bottom does not use any preloading. Try zooming out and panning to see the difference.</p>
tags: "preload, bing"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
---
<div id="map1" class="map"></div>

View File

@@ -14,7 +14,7 @@ const map1 = new Map({
new TileLayer({
preload: Infinity,
source: new BingMaps({
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: 'Aerial'
})
})
@@ -28,7 +28,7 @@ const map2 = new Map({
new TileLayer({
preload: 0, // default value
source: new BingMaps({
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: 'AerialWithLabelsOnDemand'
})
})

View File

@@ -5,7 +5,9 @@ shortdesc: Example of some Regular Shape styles.
docs: >
This example shows how several regular shapes
or symbols (representing `x`, `cross`, `star`,
`triangle` and `square`) can be created.
`triangle`, `square` and `stacked`) can be created.
Style `stacked` represents possility to stack multiple shapes with offset
tags: "vector, symbol, regularshape, style, square, cross, star, triangle, x"
---
<div id="map" class="map"></div>

View File

@@ -59,18 +59,39 @@ const styles = {
radius2: 0,
angle: Math.PI / 4
})
})
}),
'stacked': [
new Style({
image: new RegularShape({
fill: fill,
stroke: stroke,
points: 4,
radius: 5,
angle: Math.PI / 4,
displacement: [0, 10]
})
}),
new Style({
image: new RegularShape({
fill: fill,
stroke: stroke,
points: 4,
radius: 10,
angle: Math.PI / 4
})
})
]
};
const styleKeys = ['x', 'cross', 'star', 'triangle', 'square'];
const styleKeys = ['x', 'cross', 'star', 'triangle', 'square', 'stacked'];
const count = 250;
const features = new Array(count);
const e = 4500000;
for (let i = 0; i < count; ++i) {
const coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e];
features[i] = new Feature(new Point(coordinates));
features[i].setStyle(styles[styleKeys[Math.floor(Math.random() * 5)]]);
features[i].setStyle(styles[styleKeys[Math.floor(Math.random() * 6)]]);
}
const source = new VectorSource({

View File

@@ -6,12 +6,12 @@ docs: >
This example shows client-side raster reprojection capabilities from
OSM (EPSG:3857) to arbitrary projection by searching
in <a href="https://epsg.io/">EPSG.io</a> database.
tags: "reprojection, projection, proj4js, epsg.io"
tags: "reprojection, projection, proj4js, epsg.io, graticule"
---
<div id="map" class="map"></div>
<form class="form-inline">
<label for="epsg-query">Search projection:</label>
<input type="text" id="epsg-query" placeholder="4326, 27700, US National Atlas, Swiss, France, ..." class="form-control" size="50" />
<input type="text" id="epsg-query" placeholder="4326, 27700, 3031, US National Atlas, Swiss, France, ..." class="form-control" size="50" />
<button id="epsg-search" class="btn">Search</button>
<span id="epsg-result"></span>
<div>
@@ -19,5 +19,9 @@ tags: "reprojection, projection, proj4js, epsg.io"
Render reprojection edges
<input type="checkbox" id="render-edges">
</label>
<label for="show-graticule">
&nbsp;&nbsp;&nbsp;Show graticule
<input type="checkbox" id="show-graticule" />
</label>
</div>
</form>

View File

@@ -1,19 +1,34 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {applyTransform} from '../src/ol/extent.js';
import Graticule from '../src/ol/layer/Graticule.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {get as getProjection, getTransform} from '../src/ol/proj.js';
import {register} from '../src/ol/proj/proj4.js';
import OSM from '../src/ol/source/OSM.js';
import TileImage from '../src/ol/source/TileImage.js';
import Stroke from '../src/ol/style/Stroke.js';
import proj4 from 'proj4';
const graticule = new Graticule({
// the style to use for the lines, optional.
strokeStyle: new Stroke({
color: 'rgba(255,120,0,0.9)',
width: 2,
lineDash: [0.5, 4]
}),
showLabels: true,
visible: false,
wrapX: false
});
const map = new Map({
layers: [
new TileLayer({
source: new OSM()
})
}),
graticule
],
target: 'map',
view: new View({
@@ -28,6 +43,7 @@ const queryInput = document.getElementById('epsg-query');
const searchButton = document.getElementById('epsg-search');
const resultSpan = document.getElementById('epsg-result');
const renderEdgesCheckbox = document.getElementById('render-edges');
const showGraticuleCheckbox = document.getElementById('show-graticule');
function setProjection(code, name, proj4def, bbox) {
if (code === null || name === null || proj4def === null || bbox === null) {
@@ -48,9 +64,15 @@ function setProjection(code, name, proj4def, bbox) {
const newProj = getProjection(newProjCode);
const fromLonLat = getTransform('EPSG:4326', newProj);
// very approximate calculation of projection extent
const extent = applyTransform(
[bbox[1], bbox[2], bbox[3], bbox[0]], fromLonLat);
let worldExtent = [bbox[1], bbox[2], bbox[3], bbox[0]];
newProj.setWorldExtent(worldExtent);
// approximate calculation of projection extent,
// checking if the world extent crosses the dateline
if (bbox[1] > bbox[3]) {
worldExtent = [bbox[1], bbox[2], bbox[3] + 360, bbox[0]];
}
const extent = applyTransform(worldExtent, fromLonLat, undefined, 8);
newProj.setExtent(extent);
const newView = new View({
projection: newProj
@@ -98,7 +120,7 @@ searchButton.onclick = function(event) {
/**
* Handle change event.
* Handle checkbox change event.
*/
renderEdgesCheckbox.onchange = function() {
map.getLayers().forEach(function(layer) {
@@ -110,3 +132,10 @@ renderEdgesCheckbox.onchange = function() {
}
});
};
/**
* Handle checkbox change event.
*/
showGraticuleCheckbox.onchange = function() {
graticule.setVisible(showGraticuleCheckbox.checked);
};

View File

@@ -57,6 +57,8 @@
event.preventDefault();
const html = document.getElementById('example-html-source').innerText;
const js = document.getElementById('example-js-source').innerText;
const workerContainer = document.getElementById('example-worker-source');
const worker = workerContainer ? workerContainer.innerText : undefined;
const pkgJson = document.getElementById('example-pkg-source').innerText;
const form = document.getElementById('codepen-form');
@@ -68,22 +70,28 @@
Promise.all(promises)
.then(results => {
const data = {
files: {
'index.html': {
content: html
},
'index.js': {
content: js
},
"package.json": {
content: pkgJson
},
'sandbox.config.json': {
content: '{"template": "parcel"}'
}
const files = {
'index.html': {
content: html
},
'index.js': {
content: js
},
"package.json": {
content: pkgJson
},
'sandbox.config.json': {
content: '{"template": "parcel"}'
}
};
if (worker) {
files['worker.js'] = {
content: worker
}
}
const data = {
files: files
};
for (let i = 0; i < localResources.length; i++) {
data.files[localResources[i]] = results[i];

View File

@@ -309,4 +309,4 @@ function createMapboxStreetsV6Style(Style, Fill, Stroke, Icon, Text) {
styles.length = length;
return styles;
};
}
}

View File

@@ -10,7 +10,7 @@ docs: >
tags: "draw, edit, modify, vector, snap"
---
<div id="map" class="map"></div>
<form id="options-form" automplete="off">
<form id="options-form" autocomplete="off">
<div class="radio">
<label>
<input type="radio" name="interaction" value="draw" id="draw" checked>

View File

@@ -17,8 +17,8 @@ register(proj4);
// and a world extent. These are required for the Graticule.
const sphereMollweideProjection = new Projection({
code: 'ESRI:53009',
extent: [-9009954.605703328, -9009954.605703328,
9009954.605703328, 9009954.605703328],
extent: [-18019909.21177587, -9009954.605703328,
18019909.21177587, 9009954.605703328],
worldExtent: [-179, -89.99, 179, 89.99]
});
@@ -37,6 +37,6 @@ const map = new Map({
view: new View({
center: [0, 0],
projection: sphereMollweideProjection,
zoom: 0
zoom: 1
})
});

View File

@@ -67,9 +67,9 @@
<link rel="stylesheet" href="./resources/prism/prism.css" type="text/css">
<link rel="stylesheet" href="./css/ol.css" type="text/css">
<link rel="stylesheet" href="./resources/layout.css" type="text/css">
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,URL"></script>
{{{ extraHead.local }}}
{{{ css.tag }}}
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
<title>{{ title }}</title>
</head>
@@ -139,7 +139,7 @@
&lt;head&gt;
&lt;title&gt;{{ title }}&lt;/title&gt;
&lt;!-- The line below is only needed for old environments like Internet Explorer and Android 4.x --&gt;
&lt;script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"&gt;&lt;/script&gt;{{#if extraHead.remote}}
&lt;script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,URL"&gt;&lt;/script&gt;{{#if extraHead.remote}}
{{ indent extraHead.remote spaces=4 }}{{/if}}
&lt;style&gt;
.map {
@@ -160,6 +160,14 @@
<pre><legend>index.js</legend><code id="example-js-source" class="language-js">import 'ol/ol.css';
{{ js.source }}</code></pre>
</div>
{{#if worker.source}}
<div class="row-fluid">
<div class="source-controls">
<a class="copy-button" id="copy-worker-button" data-clipboard-target="#example-worker-source"><i class="fa fa-clipboard"></i> Copy</a>
</div>
<pre><legend>worker.js</legend><code id="example-worker-source" class="language-js">{{ worker.source }}</code></pre>
</div>
{{/if}}
<div class="row-fluid">
<div class="source-controls">
<a class="copy-button" id="copy-pkg-button" data-clipboard-target="#example-pkg-source"><i class="fa fa-clipboard"></i> Copy</a>
@@ -167,7 +175,6 @@
<pre><legend>package.json</legend><code id="example-pkg-source" class="language-js">{{ pkgJson }}</code></pre>
</div>
</div>
<script src="./resources/common.js"></script>
<script src="./resources/prism/prism.min.js"></script>
{{{ js.tag }}}

View File

@@ -1,19 +1,5 @@
This folder contains example templates. These templates are used to build the examples in the `examples/` folder. The resulting examples are written to the `build/examples` folder.
Although the main purpose of these examples is to demonstrate how to use the API, they also serve other purposes in the development cycle, and so are not exactly as they would be in normal application code:
* every time the library changes, they are compiled together with the library as a basic check that they remain in sync with the library
* they use a special loader script to enable defining at run time which build mode (raw/debug/advanced) to use
To enable this, examples have the following, not needed in application code:
* each html file loads `loader.js`; application code would not need this, but would instead load the appropriate library build file, either a hosted version or a custom build
* each js file starts with `goog.require` functions, used by the compiler; application code would only have these if the code is to be compiled together with the library and/or Closure library
* some js files use type definitions (comments with @type tags); these are also used by the compiler, and are only needed if the code is to be compiled together with the library
* html files load `resources/common.js` and some scripts use `common.getRendererFromQueryString()` to set the map renderer; application code would not need these
The examples are transpiled to es5. If the name of an example starts with `es2015-`, transpilation will be bypassed. This allows for showing es2015+ features in examples.
At the bottom of each example generated in the `build/examples` folder, a modified version of its source code is shown. That modified version can be run standalone and is usually used as starting point for users to extend examples into their own application.

22
examples/tracing.html Normal file
View File

@@ -0,0 +1,22 @@
---
layout: example.html
title: Tracing around a polygon
shortdesc: Example of setting up a draw interaction to easily snap to an existing feature.
docs: >
This example showcases how the draw interaction API can be set up to make snapping along
an existing geometry easier while preserving topology, which is sometimes called "tracing".
When the user clicks on two different points on the Idaho state border,
the part of the border comprised between these two points is added to
the currently drawn feature.
This leverages the `appendCoordinates` method of the `ol/interaction/Draw` interaction.
tags: "draw, trace, snap, vector, topology"
---
<div id="map" class="map"></div>
<form class="form-inline">
<label>Geometry type &nbsp;</label>
<select id="type">
<option value="Polygon">Polygon</option>
<option value="LineString">LineString</option>
<option value="None">None</option>
</select>
</form>

253
examples/tracing.js Normal file
View File

@@ -0,0 +1,253 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import Draw from '../src/ol/interaction/Draw.js';
import Snap from '../src/ol/interaction/Snap.js';
import Style from '../src/ol/style/Style.js';
import Stroke from '../src/ol/style/Stroke.js';
import Fill from '../src/ol/style/Fill.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import LineString from '../src/ol/geom/LineString.js';
import Feature from '../src/ol/Feature.js';
// math utilities
// coordinates; will return the length of the [a, b] segment
function length(a, b) {
return Math.sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
}
// coordinates; will return true if c is on the [a, b] segment
function isOnSegment(c, a, b) {
const lengthAc = length(a, c);
const lengthAb = length(a, b);
const dot = ((c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1])) / lengthAb;
return Math.abs(lengthAc - dot) < 1e-6 && lengthAc < lengthAb;
}
// modulo for negative values, eg: mod(-1, 4) returns 3
function mod(a, b) {
return ((a % b) + b) % b;
}
// returns a coordinates array which contains the segments of the feature's
// outer ring between the start and end points
// Note: this assumes the base feature is a single polygon
function getPartialRingCoords(feature, startPoint, endPoint) {
let polygon = feature.getGeometry();
if (polygon.getType() === 'MultiPolygon') {
polygon = polygon.getPolygon(0);
}
const ringCoords = polygon.getLinearRing().getCoordinates();
let i, pointA, pointB, startSegmentIndex = -1;
for (i = 0; i < ringCoords.length; i++) {
pointA = ringCoords[i];
pointB = ringCoords[mod(i + 1, ringCoords.length)];
// check if this is the start segment dot product
if (isOnSegment(startPoint, pointA, pointB)) {
startSegmentIndex = i;
break;
}
}
const cwCoordinates = [];
let cwLength = 0;
const ccwCoordinates = [];
let ccwLength = 0;
// build clockwise coordinates
for (i = 0; i < ringCoords.length; i++) {
pointA = i === 0 ? startPoint : ringCoords[mod(i + startSegmentIndex, ringCoords.length)];
pointB = ringCoords[mod(i + startSegmentIndex + 1, ringCoords.length)];
cwCoordinates.push(pointA);
if (isOnSegment(endPoint, pointA, pointB)) {
cwCoordinates.push(endPoint);
cwLength += length(pointA, endPoint);
break;
} else {
cwLength += length(pointA, pointB);
}
}
// build counter-clockwise coordinates
for (i = 0; i < ringCoords.length; i++) {
pointA = ringCoords[mod(startSegmentIndex - i, ringCoords.length)];
pointB = i === 0 ? startPoint : ringCoords[mod(startSegmentIndex - i + 1, ringCoords.length)];
ccwCoordinates.push(pointB);
if (isOnSegment(endPoint, pointA, pointB)) {
ccwCoordinates.push(endPoint);
ccwLength += length(endPoint, pointB);
break;
} else {
ccwLength += length(pointA, pointB);
}
}
// keep the shortest path
return ccwLength < cwLength ? ccwCoordinates : cwCoordinates;
}
// layers definition
const raster = new TileLayer({
source: new OSM()
});
// features in this layer will be snapped to
const baseVector = new VectorLayer({
source: new VectorSource({
format: new GeoJSON(),
url: 'https://ahocevar.com/geoserver/wfs?service=wfs&request=getfeature&typename=topp:states&cql_filter=STATE_NAME=\'Idaho\'&outputformat=application/json'
})
});
// this is were the drawn features go
const drawVector = new VectorLayer({
source: new VectorSource(),
style: new Style({
stroke: new Stroke({
color: 'rgba(100, 255, 0, 1)',
width: 2
}),
fill: new Fill({
color: 'rgba(100, 255, 0, 0.3)'
})
})
});
// this line only appears when we're tracing a feature outer ring
const previewLine = new Feature({
geometry: new LineString([])
});
const previewVector = new VectorLayer({
source: new VectorSource({
features: [previewLine]
}),
style: new Style({
stroke: new Stroke({
color: 'rgba(255, 0, 0, 1)',
width: 2
})
})
});
const map = new Map({
layers: [raster, baseVector, drawVector, previewVector],
target: 'map',
view: new View({
center: [-12986427, 5678422],
zoom: 5
})
});
let drawInteraction, tracingFeature, startPoint, endPoint;
let drawing = false;
const getFeatureOptions = {
hitTolerance: 10,
layerFilter: (layer) => {
return layer === baseVector;
}
};
// the click event is used to start/end tracing around a feature
map.on('click', (event) => {
if (!drawing) {
return;
}
let hit = false;
map.forEachFeatureAtPixel(
event.pixel,
(feature) => {
if (tracingFeature && feature !== tracingFeature) {
return;
}
hit = true;
const coord = map.getCoordinateFromPixel(event.pixel);
// second click on the tracing feature: append the ring coordinates
if (feature === tracingFeature) {
endPoint = tracingFeature.getGeometry().getClosestPoint(coord);
const appendCoords = getPartialRingCoords(tracingFeature, startPoint, endPoint);
drawInteraction.removeLastPoint();
drawInteraction.appendCoordinates(appendCoords);
tracingFeature = null;
}
// start tracing on the feature ring
tracingFeature = feature;
startPoint = tracingFeature.getGeometry().getClosestPoint(coord);
},
getFeatureOptions
);
if (!hit) {
// clear current tracing feature & preview
previewLine.getGeometry().setCoordinates([]);
tracingFeature = null;
}
});
// the pointermove event is used to show a preview of the result of the tracing
map.on('pointermove', (event) => {
if (tracingFeature && drawing) {
let coord = null;
map.forEachFeatureAtPixel(
event.pixel,
(feature) => {
if (tracingFeature === feature) {
coord = map.getCoordinateFromPixel(event.pixel);
}
},
getFeatureOptions
);
let previewCoords = [];
if (coord) {
endPoint = tracingFeature.getGeometry().getClosestPoint(coord);
previewCoords = getPartialRingCoords(tracingFeature, startPoint, endPoint);
}
previewLine.getGeometry().setCoordinates(previewCoords);
}
});
const snapInteraction = new Snap({
source: baseVector.getSource()
});
const typeSelect = document.getElementById('type');
function addInteraction() {
const value = typeSelect.value;
if (value !== 'None') {
drawInteraction = new Draw({
source: drawVector.getSource(),
type: typeSelect.value
});
drawInteraction.on('drawstart', () => {
drawing = true;
});
drawInteraction.on('drawend', () => {
drawing = false;
previewLine.getGeometry().setCoordinates([]);
tracingFeature = null;
});
map.addInteraction(drawInteraction);
map.addInteraction(snapInteraction);
}
}
typeSelect.onchange = function() {
map.removeInteraction(drawInteraction);
map.removeInteraction(snapInteraction);
addInteraction();
};
addInteraction();

View File

@@ -4,9 +4,9 @@ title: OSM XML
shortdesc: Example of using the OSM XML source.
docs: >
OSM XML vector data is loaded dynamically from a the [Overpass API](http://overpass-api.de) using a bbox strategy. Note that panning and zooming will eventually lead to "Too many requests" errors from the Overpass API.
tags: "vector, osmxml, loading, server, strategy, bbox"
tags: "vector, osmxml, loading, server, strategy, bbox, maptiler"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<div id="map" class="map"></div>

View File

@@ -4,7 +4,7 @@ import OSMXML from '../src/ol/format/OSMXML.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {bbox as bboxStrategy} from '../src/ol/loadingstrategy.js';
import {transformExtent} from '../src/ol/proj.js';
import BingMaps from '../src/ol/source/BingMaps.js';
import XYZ from '../src/ol/source/XYZ.js';
import VectorSource from '../src/ol/source/Vector.js';
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
@@ -85,8 +85,8 @@ const vectorSource = new VectorSource({
vectorSource.addFeatures(features);
});
const query = '(node(' +
epsg4326Extent[1] + ',' + epsg4326Extent[0] + ',' +
epsg4326Extent[3] + ',' + epsg4326Extent[2] +
epsg4326Extent[1] + ',' + Math.max(epsg4326Extent[0], -180) + ',' +
epsg4326Extent[3] + ',' + Math.min(epsg4326Extent[2], 180) +
');rel(bn)->.foo;way(bn);node(w)->.foo;rel(bw););out meta;';
client.send(query);
},
@@ -110,10 +110,15 @@ const vector = new VectorLayer({
}
});
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const raster = new TileLayer({
source: new BingMaps({
imagerySet: 'Aerial',
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
source: new XYZ({
attributions: attributions,
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
maxZoom: 20
})
});

View File

@@ -6,6 +6,8 @@ docs: >
Example showing vector tiles in EPSG:4326 (styled using `ol-mapbox-style`) loaded from maptiler.com.
**Note**: Make sure to get your own API key at https://www.maptiler.com/cloud/ when using this example. No map will be visible when the API key has expired.
tags: "vector tiles, epsg4326, mapbox style, ol-mapbox-style, maptiler"
resources:
- https://cdn.polyfill.io/v2/polyfill.min.js?features=String.prototype.startsWith,Object.assign"
cloak:
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/

View File

@@ -4,7 +4,7 @@ import VectorTileSource from '../src/ol/source/VectorTile.js';
import TileGrid from '../src/ol/tilegrid/TileGrid.js';
import olms from 'ol-mapbox-style';
import {defaultResolutions} from 'ol-mapbox-style/util.js';
import {defaultResolutions} from 'ol-mapbox-style/dist/util.js';
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';

View File

@@ -6,9 +6,9 @@ docs: >
This example generates a `GetFeature` request which uses a `PropertyIsEqualTo`
and a `PropertyIsLike` filter, and then posts the request to load the features
that match the query.
tags: "vector, WFS, GetFeature, filter"
tags: "vector, WFS, GetFeature, filter, maptiler"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<div id="map" class="map"></div>

View File

@@ -7,7 +7,7 @@ import {
} from '../src/ol/format/filter.js';
import {WFS, GeoJSON} from '../src/ol/format.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import BingMaps from '../src/ol/source/BingMaps.js';
import XYZ from '../src/ol/source/XYZ.js';
import VectorSource from '../src/ol/source/Vector.js';
import {Stroke, Style} from '../src/ol/style.js';
@@ -23,10 +23,15 @@ const vector = new VectorLayer({
})
});
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const raster = new TileLayer({
source: new BingMaps({
imagerySet: 'Aerial',
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
source: new XYZ({
attributions: attributions,
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
maxZoom: 20
})
});

View File

@@ -4,9 +4,9 @@ title: WFS
shortdesc: Example of using WFS with a BBOX strategy.
docs: >
This example loads new features from GeoServer WFS when the view extent changes.
tags: "vector, WFS, bbox, loading, server"
tags: "vector, WFS, bbox, loading, server, maptiler"
cloak:
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/
---
<div id="map" class="map"></div>

View File

@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {bbox as bboxStrategy} from '../src/ol/loadingstrategy.js';
import BingMaps from '../src/ol/source/BingMaps.js';
import XYZ from '../src/ol/source/XYZ.js';
import VectorSource from '../src/ol/source/Vector.js';
import {Stroke, Style} from '../src/ol/style.js';
@@ -30,10 +30,15 @@ const vector = new VectorLayer({
})
});
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>';
const raster = new TileLayer({
source: new BingMaps({
imagerySet: 'Aerial',
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
source: new XYZ({
attributions: attributions,
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
maxZoom: 20
})
});

View File

@@ -22,7 +22,7 @@ module.exports = {
stats: 'minimal',
module: {
rules: [{
test: /\.js$/,
test: /^((?!es2015-)[\s\S])*\.js$/,
use: {
loader: 'buble-loader'
},

View File

@@ -208,6 +208,10 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
jsSource = jsSource.replace(new RegExp(entry.key, 'g'), entry.value);
}
}
// Remove worker loader import and modify `new Worker()` to add source
jsSource = jsSource.replace(/import Worker from 'worker-loader![^\n]*\n/g, '');
jsSource = jsSource.replace('new Worker()', 'new Worker(\'./worker.js\')');
data.js = {
tag: `<script src="${this.common}.js"></script><script src="${jsName}"></script>`,
source: jsSource
@@ -218,9 +222,33 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
data.js.tag = prelude + data.js.tag;
}
// check for worker js
const workerName = `${name}.worker.js`;
const workerPath = path.join(dir, workerName);
let workerSource;
try {
workerSource = await readFile(workerPath, readOptions);
} catch (err) {
// pass
}
if (workerSource) {
// remove "../src/" prefix and ".js" to have the same import syntax as the documentation
workerSource = workerSource.replace(/'\.\.\/src\//g, '\'');
workerSource = workerSource.replace(/\.js';/g, '\';');
if (data.cloak) {
for (const entry of data.cloak) {
workerSource = workerSource.replace(new RegExp(entry.key, 'g'), entry.value);
}
}
data.worker = {
source: workerSource
};
assets[workerName] = workerSource;
}
data.pkgJson = JSON.stringify({
name: name,
dependencies: getDependencies(jsSource),
dependencies: getDependencies(jsSource + workerSource ? `\n${workerSource}` : ''),
devDependencies: {
parcel: '1.11.0'
},

View File

@@ -3,7 +3,7 @@ layout: example.html
title: ArcGIS REST with 512x512 Tiles
shortdesc: Example of a XYZ source in EPSG:4326 using Esri 512x512 tiles.
docs: >
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol/source/XYZ`. A custom tile url function is used to handle zoom level offsets.
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol/source/XYZ`.
tags: "xyz, esri, tilesize, custom projection"
---
<div id="map" class="map"></div>

View File

@@ -3,26 +3,18 @@ import View from '../src/ol/View.js';
import TileLayer from '../src/ol/layer/Tile.js';
import XYZ from '../src/ol/source/XYZ.js';
// The tile size supported by the ArcGIS tile service.
const tileSize = 512;
const urlTemplate = 'https://services.arcgisonline.com/arcgis/rest/services/' +
'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}';
const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
attributions: 'Copyright:© 2013 ESRI, i-cubed, GeoEye',
maxZoom: 16,
url: 'https://services.arcgisonline.com/arcgis/rest/services/' +
'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}',
maxZoom: 15,
projection: 'EPSG:4326',
tileSize: tileSize,
tileUrlFunction: function(tileCoord) {
return urlTemplate.replace('{z}', (tileCoord[0] - 1).toString())
.replace('{x}', tileCoord[1].toString())
.replace('{y}', tileCoord[2].toString());
},
tileSize: 512, // the tile size supported by the ArcGIS tile service
maxResolution: 180 / 512, // Esri's tile grid fits 180 degrees on one 512 px tile
wrapX: true
})
})

View File

@@ -10,7 +10,6 @@ tags: "zoomify, deep zoom, IIP, pixel, projection"
<div class="controls">
<select id="zoomifyProtocol">
<option value="zoomify">Zoomify</option>
<option value="iip">IIP</option>
<option value="zoomifyretina">Zoomify Retina</option>
</select>
</div>

View File

@@ -3,36 +3,42 @@ import View from '../src/ol/View.js';
import TileLayer from '../src/ol/layer/Tile.js';
import Zoomify from '../src/ol/source/Zoomify.js';
const imgWidth = 9911;
const imgHeight = 6100;
const imgWidth = 4000;
const imgHeight = 3000;
const zoomifyUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?zoomify=' +
'/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF/';
const iipUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?FIF=' + '/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF' + '&JTL={z},{tileIndex}';
const zoomifyUrl = 'https://ol-zoomify.surge.sh/zoomify/';
const layer = new TileLayer({
source: new Zoomify({
tileSize: 256,
tilePixelRatio: 1,
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
})
const source = new Zoomify({
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous',
zDirection: -1 // Ensure we get a tile with the screen resolution or higher
});
const extent = source.getTileGrid().getExtent();
const retinaPixelRatio = 2;
const retinaSource = new Zoomify({
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous',
zDirection: -1, // Ensure we get a tile with the screen resolution or higher
tilePixelRatio: retinaPixelRatio, // Display retina tiles
tileSize: 256 / retinaPixelRatio // from a higher zoom level
});
const extent = [0, -imgHeight, imgWidth, 0];
const resolutions = layer.getSource().getTileGrid().getResolutions();
const layer = new TileLayer({
source: source
});
const map = new Map({
layers: [layer],
target: 'map',
view: new View({
// adjust zoom levels to those provided by the source
minResolution: resolutions[resolutions.length - 1],
maxResolution: resolutions[0],
resolutions: layer.getSource().getTileGrid().getResolutions(),
// constrain the center: center cannot be set outside this extent
extent: extent
extent: extent,
constrainOnlyCenter: true
})
});
map.getView().fit(extent);
@@ -40,74 +46,11 @@ map.getView().fit(extent);
const control = document.getElementById('zoomifyProtocol');
control.addEventListener('change', function(event) {
const value = event.currentTarget.value;
if (value === 'iip') {
const extent = [0, -imgHeight, imgWidth, 0];
layer.setSource(
new Zoomify({
tileSize: 256,
tilePixelRatio: 1,
url: iipUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
})
);
const resolutions = layer.getSource().getTileGrid().getResolutions();
map.setView(
new View({
// adjust zoom levels to those provided by the source
minResolution: resolutions[resolutions.length - 1],
maxResolution: resolutions[0],
// constrain the center: center cannot be set outside this extent
extent: extent
})
);
map.getView().fit(extent);
} else if (value === 'zoomify') {
const extent = [0, -imgHeight, imgWidth, 0];
layer.setSource(
new Zoomify({
tileSize: 256,
tilePixelRatio: 1,
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
})
);
const resolutions = layer.getSource().getTileGrid().getResolutions();
map.setView(
new View({
// adjust zoom levels to those provided by the source
minResolution: resolutions[resolutions.length - 1],
maxResolution: resolutions[0],
// constrain the center: center cannot be set outside this extent
extent: extent
})
);
map.getView().fit(extent);
if (value === 'zoomify') {
layer.setSource(source);
} else if (value === 'zoomifyretina') {
const pixelRatio = 4;
// Be careful! Image extent will be modified by pixel ratio
const extent = [0, -imgHeight / pixelRatio, imgWidth / pixelRatio, 0];
layer.setSource(
new Zoomify({
tileSize: 256 / pixelRatio,
tilePixelRatio: pixelRatio,
url: zoomifyUrl,
size: [imgWidth / pixelRatio, imgHeight / pixelRatio],
crossOrigin: 'anonymous'
})
);
const resolutions = layer.getSource().getTileGrid().getResolutions();
map.setView(
new View({
// adjust zoom levels to those provided by the source
minResolution: resolutions[resolutions.length - 1] / pixelRatio,
maxResolution: resolutions[0],
// constrain the center: center cannot be set outside this extent
extent: extent
})
);
map.getView().fit(extent);
layer.setSource(retinaSource);
}
});

3855
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ol",
"version": "6.1.1",
"version": "6.3.1-dev",
"description": "OpenLayers mapping library",
"keywords": [
"map",
@@ -22,9 +22,10 @@
"build-index": "npm run build-package && node tasks/generate-index",
"build-legacy": "shx rm -rf build && npm run build-index && webpack --config config/webpack-config-legacy-build.js && cleancss --source-map src/ol/ol.css -o build/legacy/ol.css",
"copy-css": "shx cp src/ol/ol.css build/ol/ol.css",
"transpile": "shx rm -rf build/ol && shx mkdir -p build/ol && shx cp -rf src/ol build/ol/src && node tasks/serialize-workers && tsc --project config/tsconfig-build.json",
"transpile": "shx rm -rf build/ol && shx mkdir -p build/ol && shx cp -rf src/ol build/ol/src && node tasks/serialize-workers && npx --package typescript@3.8.1-rc tsc --project config/tsconfig-build.json",
"typecheck": "tsc --pretty",
"apidoc": "jsdoc -R config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
"apidoc-debug": "shx rm -rf build/apidoc && node --inspect-brk=9229 ./node_modules/jsdoc/jsdoc.js -R config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc",
"apidoc": "shx rm -rf build/apidoc && jsdoc -R config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
},
"main": "index.js",
"repository": {
@@ -35,8 +36,12 @@
"bugs": {
"url": "https://github.com/openlayers/openlayers/issues"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/openlayers"
},
"dependencies": {
"elm-pep": "^1.0.2",
"elm-pep": "^1.0.4",
"pbf": "3.2.1",
"pixelworks": "1.1.0",
"rbush": "^3.0.1"
@@ -50,58 +55,58 @@
"@types/pbf": "^3.0.2",
"@types/topojson-specification": "^1.0.1",
"babel-loader": "^8.0.5",
"buble": "^0.19.7",
"buble": "^0.20.0",
"buble-loader": "^0.5.1",
"chaikin-smooth": "^1.0.4",
"clean-css-cli": "4.3.0",
"copy-webpack-plugin": "^5.0.4",
"coveralls": "3.0.9",
"coveralls": "3.0.11",
"eslint": "^6.0.0",
"eslint-config-openlayers": "^13.0.0",
"expect.js": "0.3.1",
"front-matter": "^3.0.2",
"fs-extra": "^8.0.0",
"fs-extra": "^9.0.0",
"glob": "^7.1.5",
"globby": "^10.0.0",
"handlebars": "4.5.3",
"html-to-image": "^0.1.0",
"globby": "^11.0.0",
"handlebars": "4.7.4",
"istanbul": "0.4.5",
"istanbul-instrumenter-loader": "^3.0.1",
"jquery": "3.4.1",
"jsdoc": "3.6.3",
"jsdoc-plugin-typescript": "^2.0.5",
"json-stringify-safe": "^5.0.1",
"karma": "^4.4.1",
"karma-chrome-launcher": "3.1.0",
"karma-coverage": "^2.0.1",
"karma-coverage-istanbul-reporter": "^2.1.0",
"karma-coverage-istanbul-reporter": "^2.1.1",
"karma-firefox-launcher": "^1.1.0",
"karma-mocha": "1.3.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.0-rc.2",
"loglevelnext": "^3.0.1",
"marked": "0.8.0",
"mocha": "7.0.0",
"ol-mapbox-style": "^5.0.2",
"marked": "0.8.2",
"mocha": "7.1.1",
"ol-mapbox-style": "^6.1.1",
"pixelmatch": "^5.1.0",
"pngjs": "^3.4.0",
"proj4": "2.6.0",
"puppeteer": "~2.0.0",
"rollup": "^1.25.1",
"proj4": "2.6.1",
"puppeteer": "~2.1.0",
"rollup": "^2.1.0",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^5.0.0",
"serve-static": "^1.14.0",
"shx": "^0.3.2",
"sinon": "^8.0.0",
"sinon": "^9.0.0",
"terser-webpack-plugin": "^2.0.1",
"typescript": "3.5.3",
"url-polyfill": "^1.1.5",
"walk": "^2.3.9",
"webpack": "4.41.5",
"webpack": "4.42.1",
"webpack-cli": "^3.3.2",
"webpack-dev-middleware": "^3.6.2",
"webpack-dev-server": "^3.3.1",
"worker-loader": "^2.0.0",
"yargs": "^15.0.2"
},
"eslintConfig": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

View File

@@ -0,0 +1,47 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import {Vector as VectorLayer, Tile as TileLayer} from '../../../src/ol/layer.js';
import {Vector as VectorSource, XYZ} from '../../../src/ol/source.js';
import Point from '../../../src/ol/geom/Point.js';
import Feature from '../../../src/ol/Feature.js';
import {fromLonLat} from '../../../src/ol/proj.js';
import {Style, Icon} from '../../../src/ol/style.js';
const center = fromLonLat([8.6, 50.1]);
new Map({
layers: [
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg'
})
}),
new VectorLayer({
style: function() {
return new Style({
image: new Icon({
opacity: 0.5,
src: '/data/icon.png',
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels'
})
});
},
source: new VectorSource({
features: [
new Feature(
new Point(center)
)
]
})
})
],
target: 'map',
view: new View({
center: center,
zoom: 3
})
});
render();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -13,16 +13,17 @@ const vectorSource = new VectorSource();
function createFeatures(stroke, fill, offSet = [0, 0]) {
let feature;
feature = new Feature({
geometry: new Point([-15 + offSet[0], 15 + offSet[1]])
geometry: new Point([offSet[0], offSet[1]])
});
// square
// square with offset
feature.setStyle(new Style({
image: new RegularShape({
fill: fill,
stroke: stroke,
points: 4,
radius: 10,
angle: Math.PI / 4
angle: Math.PI / 4,
displacement: [-15, 15]
})
}));
vectorSource.addFeature(feature);

BIN
sponsor-logos/pozi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -26,7 +26,7 @@ export class CollectionEvent extends Event {
/**
* @param {CollectionEventType} type Type.
* @param {*=} opt_element Element.
* @param {number} opt_index The index of the added or removed element.
* @param {number=} opt_index The index of the added or removed element.
*/
constructor(type, opt_element, opt_index) {
super(type);

View File

@@ -275,7 +275,9 @@ class MapBrowserEventHandler extends EventTarget {
* @private
*/
handleTouchMove_(event) {
if (this.originalPointerMoveEvent_.defaultPrevented) {
// Due to https://github.com/mpizenberg/elm-pep/issues/2, `this.originalPointerMoveEvent_`
// may not be initialized yet when we get here on a platform without native pointer events.
if (!this.originalPointerMoveEvent_ || this.originalPointerMoveEvent_.defaultPrevented) {
event.preventDefault();
}
}

View File

@@ -51,7 +51,7 @@ class Observable extends EventTarget {
/**
* Listen for a certain type of event.
* @param {string|Array<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @param {import("./events.js").ListenerFunction} listener The listener function.
* @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If
* called with an array of event types as the first argument, the return
* will be an array of keys.

View File

@@ -37,15 +37,21 @@ import {containsExtent} from './extent.js';
* container as that of the controls (see the `stopEvent` option) you will
* probably set `insertFirst` to `true` so the overlay is displayed below the
* controls.
* @property {boolean} [autoPan=false] If set to `true` the map is panned when
* calling `setPosition`, so that the overlay is entirely visible in the current
* viewport.
* @property {PanOptions} [autoPanAnimation] The
* animation options used to pan the overlay into view. This animation is only
* used when `autoPan` is enabled. A `duration` and `easing` may be provided to
* customize the animation.
* @property {PanIntoViewOptions|boolean} [autoPan=false] Pan the map when calling
* `setPosition`, so that the overlay is entirely visible in the current viewport?
* If `true` (deprecated), then `autoPanAnimation` and `autoPanMargin` will be
* used to determine the panning parameters; if an object is supplied then other
* parameters are ignored.
* @property {PanOptions} [autoPanAnimation] The animation options used to pan
* the overlay into view. This animation is only used when `autoPan` is enabled.
* A `duration` and `easing` may be provided to customize the animation.
* Deprecated and ignored if `autoPan` is supplied as an object.
* @property {number} [autoPanMargin=20] The margin (in pixels) between the
* overlay and the borders of the map when autopanning.
* overlay and the borders of the map when autopanning. Deprecated and ignored
* if `autoPan` is supplied as an object.
* @property {PanIntoViewOptions} [autoPanOptions] The options to use for the
* autoPan. This is only used when `autoPan` is enabled and has preference over
* the individual `autoPanMargin` and `autoPanOptions`.
* @property {string} [className='ol-overlay-container ol-selectable'] CSS class
* name.
*/
@@ -60,6 +66,12 @@ import {containsExtent} from './extent.js';
* Default is {@link module:ol/easing~inAndOut}.
*/
/**
* @typedef {Object} PanIntoViewOptions
* @property {PanOptions} [animation={}] The animation parameters for the pan
* @property {number} [margin=20] The margin (in pixels) between the
* overlay and the borders of the map when panning into view.
*/
/**
* @enum {string}
@@ -137,38 +149,26 @@ class Overlay extends BaseObject {
options.className : 'ol-overlay-container ' + CLASS_SELECTABLE;
this.element.style.position = 'absolute';
let autoPan = options.autoPan;
if (autoPan && ('object' !== typeof autoPan)) {
autoPan = {
animation: options.autoPanAnimation,
margin: options.autoPanMargin
};
}
/**
* @protected
* @type {boolean}
* @type {PanIntoViewOptions|false}
*/
this.autoPan = options.autoPan !== undefined ? options.autoPan : false;
this.autoPan = /** @type {PanIntoViewOptions} */(autoPan) || false;
/**
* @protected
* @type {PanOptions}
*/
this.autoPanAnimation = options.autoPanAnimation || /** @type {PanOptions} */ ({});
/**
* @protected
* @type {number}
*/
this.autoPanMargin = options.autoPanMargin !== undefined ?
options.autoPanMargin : 20;
/**
* @protected
* @type {{bottom_: string,
* left_: string,
* right_: string,
* top_: string,
* @type {{transform_: string,
* visible: boolean}}
*/
this.rendered = {
bottom_: '',
left_: '',
right_: '',
top_: '',
transform_: '',
visible: true
};
@@ -300,6 +300,7 @@ class Overlay extends BaseObject {
} else {
container.appendChild(this.element);
}
this.performAutoPan();
}
}
@@ -322,9 +323,7 @@ class Overlay extends BaseObject {
*/
handlePositionChanged() {
this.updatePixelPosition();
if (this.get(Property.POSITION) && this.autoPan) {
this.panIntoView();
}
this.performAutoPan();
}
/**
@@ -378,14 +377,26 @@ class Overlay extends BaseObject {
}
/**
* Pan the map so that the overlay is entirely visible in the current viewport
* (if necessary).
* Pan the map so that the overlay is entirely visisble in the current viewport
* (if necessary) using the configured autoPan parameters
* @protected
*/
panIntoView() {
performAutoPan() {
if (this.autoPan) {
this.panIntoView(this.autoPan);
}
}
/**
* Pan the map so that the overlay is entirely visible in the current viewport
* (if necessary).
* @param {PanIntoViewOptions|undefined} panIntoViewOptions Options for the pan action
* @api
*/
panIntoView(panIntoViewOptions) {
const map = this.getMap();
if (!map || !map.getTargetElement()) {
if (!map || !map.getTargetElement() || !this.get(Property.POSITION)) {
return;
}
@@ -393,7 +404,7 @@ class Overlay extends BaseObject {
const element = this.getElement();
const overlayRect = this.getRect(element, [outerWidth(element), outerHeight(element)]);
const margin = this.autoPanMargin;
const myMargin = (panIntoViewOptions.margin === undefined) ? 20 : panIntoViewOptions.margin;
if (!containsExtent(mapRect, overlayRect)) {
// the overlay is not completely inside the viewport, so pan the map
const offsetLeft = overlayRect[0] - mapRect[0];
@@ -404,17 +415,17 @@ class Overlay extends BaseObject {
const delta = [0, 0];
if (offsetLeft < 0) {
// move map to the left
delta[0] = offsetLeft - margin;
delta[0] = offsetLeft - myMargin;
} else if (offsetRight < 0) {
// move map to the right
delta[0] = Math.abs(offsetRight) + margin;
delta[0] = Math.abs(offsetRight) + myMargin;
}
if (offsetTop < 0) {
// move map up
delta[1] = offsetTop - margin;
delta[1] = offsetTop - myMargin;
} else if (offsetBottom < 0) {
// move map down
delta[1] = Math.abs(offsetBottom) + margin;
delta[1] = Math.abs(offsetBottom) + myMargin;
}
if (delta[0] !== 0 || delta[1] !== 0) {
@@ -425,10 +436,11 @@ class Overlay extends BaseObject {
centerPx[1] + delta[1]
];
const panOptions = panIntoViewOptions.animation || {};
map.getView().animateInternal({
center: map.getCoordinateFromPixelInternal(newCenterPx),
duration: this.autoPanAnimation.duration,
easing: this.autoPanAnimation.easing
duration: panOptions.duration,
easing: panOptions.easing
});
}
}
@@ -506,63 +518,34 @@ class Overlay extends BaseObject {
this.setVisible(true);
let offsetX = offset[0];
let offsetY = offset[1];
const x = Math.round(pixel[0] + offset[0]) + 'px';
const y = Math.round(pixel[1] + offset[1]) + 'px';
let posX = '0%';
let posY = '0%';
if (positioning == OverlayPositioning.BOTTOM_RIGHT ||
positioning == OverlayPositioning.CENTER_RIGHT ||
positioning == OverlayPositioning.TOP_RIGHT) {
if (this.rendered.left_ !== '') {
this.rendered.left_ = '';
style.left = '';
}
const right = Math.round(mapSize[0] - pixel[0] - offsetX) + 'px';
if (this.rendered.right_ != right) {
this.rendered.right_ = right;
style.right = right;
}
} else {
if (this.rendered.right_ !== '') {
this.rendered.right_ = '';
style.right = '';
}
if (positioning == OverlayPositioning.BOTTOM_CENTER ||
positioning == OverlayPositioning.CENTER_CENTER ||
positioning == OverlayPositioning.TOP_CENTER) {
offsetX -= this.element.offsetWidth / 2;
}
const left = Math.round(pixel[0] + offsetX) + 'px';
if (this.rendered.left_ != left) {
this.rendered.left_ = left;
style.left = left;
}
posX = '-100%';
} else if (positioning == OverlayPositioning.BOTTOM_CENTER ||
positioning == OverlayPositioning.CENTER_CENTER ||
positioning == OverlayPositioning.TOP_CENTER) {
posX = '-50%';
}
if (positioning == OverlayPositioning.BOTTOM_LEFT ||
positioning == OverlayPositioning.BOTTOM_CENTER ||
positioning == OverlayPositioning.BOTTOM_RIGHT) {
if (this.rendered.top_ !== '') {
this.rendered.top_ = '';
style.top = '';
}
const bottom = Math.round(mapSize[1] - pixel[1] - offsetY) + 'px';
if (this.rendered.bottom_ != bottom) {
this.rendered.bottom_ = bottom;
style.bottom = bottom;
}
} else {
if (this.rendered.bottom_ !== '') {
this.rendered.bottom_ = '';
style.bottom = '';
}
if (positioning == OverlayPositioning.CENTER_LEFT ||
positioning == OverlayPositioning.CENTER_CENTER ||
positioning == OverlayPositioning.CENTER_RIGHT) {
offsetY -= this.element.offsetHeight / 2;
}
const top = Math.round(pixel[1] + offsetY) + 'px';
if (this.rendered.top_ != top) {
this.rendered.top_ = 'top';
style.top = top;
}
posY = '-100%';
} else if (positioning == OverlayPositioning.CENTER_LEFT ||
positioning == OverlayPositioning.CENTER_CENTER ||
positioning == OverlayPositioning.CENTER_RIGHT) {
posY = '-50%';
}
const transform = `translate(${posX}, ${posY}) translate(${x}, ${y})`;
if (this.rendered.transform_ != transform) {
this.rendered.transform_ = transform;
style.transform = transform;
// @ts-ignore IE9
style.msTransform = transform;
}
}

View File

@@ -12,7 +12,7 @@ import MapProperty from './MapProperty.js';
import RenderEventType from './render/EventType.js';
import BaseObject, {getChangeEventType} from './Object.js';
import ObjectEventType from './ObjectEventType.js';
import TileQueue from './TileQueue.js';
import TileQueue, {getTilePriority} from './TileQueue.js';
import View from './View.js';
import ViewHint from './ViewHint.js';
import {assert} from './asserts.js';
@@ -24,7 +24,6 @@ import {TRUE} from './functions.js';
import {DEVICE_PIXEL_RATIO, IMAGE_DECODE, PASSIVE_EVENT_LISTENERS} from './has.js';
import LayerGroup from './layer/Group.js';
import {hasArea} from './size.js';
import {DROP} from './structs/PriorityQueue.js';
import {create as createTransform, apply as applyTransform} from './transform.js';
import {toUserCoordinate, fromUserCoordinate} from './proj.js';
@@ -891,26 +890,7 @@ class PluggableMap extends BaseObject {
* @return {number} Tile priority.
*/
getTilePriority(tile, tileSourceKey, tileCenter, tileResolution) {
// Filter out tiles at higher zoom levels than the current zoom level, or that
// are outside the visible extent.
const frameState = this.frameState_;
if (!frameState || !(tileSourceKey in frameState.wantedTiles)) {
return DROP;
}
if (!frameState.wantedTiles[tileSourceKey][tile.getKey()]) {
return DROP;
}
// Prioritize the highest zoom level tiles closest to the focus.
// Tiles at higher zoom levels are prioritized using Math.log(tileResolution).
// Within a zoom level, tiles are prioritized by the distance in pixels between
// the center of the tile and the center of the viewport. The factor of 65536
// means that the prioritization should behave as desired for tiles up to
// 65536 * Math.log(2) = 45426 pixels from the focus.
const center = frameState.viewState.center;
const deltaX = tileCenter[0] - center[0];
const deltaY = tileCenter[1] - center[1];
return 65536 * Math.log(tileResolution) +
Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
return getTilePriority(this.frameState_, tile, tileSourceKey, tileCenter, tileResolution);
}
/**
@@ -932,13 +912,15 @@ class PluggableMap extends BaseObject {
// coordinates so interactions cannot be used.
return;
}
let target = /** @type {Node} */ (mapBrowserEvent.originalEvent.target);
const target = /** @type {Node} */ (mapBrowserEvent.originalEvent.target);
if (!mapBrowserEvent.dragging) {
while (target && target !== this.viewport_) {
if (target.parentElement === this.overlayContainerStopEvent_) {
return;
}
target = target.parentElement;
if (this.overlayContainerStopEvent_.contains(target) || !(document.body.contains(target) || this.viewport_.getRootNode && this.viewport_.getRootNode().contains(target))) {
// Abort if the event target is a child of the container that doesn't allow
// event propagation or is no longer in the page. It's possible for the target to no longer
// be in the page if it has been removed in an event listener, this might happen in a Control
// that recreates it's content based on user interaction either manually or via a render
// in something like https://reactjs.org/
return;
}
}
mapBrowserEvent.frameState = this.frameState_;

View File

@@ -7,7 +7,7 @@ import {fromKey, getKey} from './tilecoord.js';
class TileCache extends LRUCache {
/**
* @param {!Object<string, import("./TileRange.js").default>} usedTiles Used tiles.
* @param {!Object<string, boolean>} usedTiles Used tiles.
*/
expireCache(usedTiles) {
while (this.canExpireCache()) {

View File

@@ -3,7 +3,7 @@
*/
import TileState from './TileState.js';
import EventType from './events/EventType.js';
import PriorityQueue from './structs/PriorityQueue.js';
import PriorityQueue, {DROP} from './structs/PriorityQueue.js';
/**
@@ -119,3 +119,34 @@ class TileQueue extends PriorityQueue {
export default TileQueue;
/**
* @param {import('./PluggableMap.js').FrameState} frameState Frame state.
* @param {import("./Tile.js").default} tile Tile.
* @param {string} tileSourceKey Tile source key.
* @param {import("./coordinate.js").Coordinate} tileCenter Tile center.
* @param {number} tileResolution Tile resolution.
* @return {number} Tile priority.
*/
export function getTilePriority(frameState, tile, tileSourceKey, tileCenter, tileResolution) {
// Filter out tiles at higher zoom levels than the current zoom level, or that
// are outside the visible extent.
if (!frameState || !(tileSourceKey in frameState.wantedTiles)) {
return DROP;
}
if (!frameState.wantedTiles[tileSourceKey][tile.getKey()]) {
return DROP;
}
// Prioritize the highest zoom level tiles closest to the focus.
// Tiles at higher zoom levels are prioritized using Math.log(tileResolution).
// Within a zoom level, tiles are prioritized by the distance in pixels between
// the center of the tile and the center of the viewport. The factor of 65536
// means that the prioritization should behave as desired for tiles up to
// 65536 * Math.log(2) = 45426 pixels from the focus.
const center = frameState.viewState.center;
const deltaX = tileCenter[0] - center[0];
const deltaY = tileCenter[1] - center[1];
return 65536 * Math.log(tileResolution) +
Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
}

View File

@@ -129,6 +129,14 @@ import {createMinMaxResolution} from './resolutionconstraint.js';
* @property {boolean} [smoothResolutionConstraint=true] If true, the resolution
* min/max values will be applied smoothly, i. e. allow the view to exceed slightly
* the given resolution or zoom bounds.
* @property {boolean} [showFullExtent=false] Allow the view to be zoomed out to
* show the full configured extent. By default, when a view is configured with an
* extent, users will not be able to zoom out so the viewport exceeds the extent in
* either dimension. This means the full extent may not be visible if the viewport
* is taller or wider than the aspect ratio of the configured extent. If
* showFullExtent is true, the user will be able to zoom out so that the viewport
* exceeds the height or width of the configured extent, but not both, allowing the
* full extent to be shown.
* @property {import("./proj.js").ProjectionLike} [projection='EPSG:3857'] The
* projection. The default is Spherical Mercator.
* @property {number} [resolution] The initial resolution for the view. The
@@ -397,7 +405,6 @@ class View extends BaseObject {
} else if (options.zoom !== undefined) {
this.setZoom(options.zoom);
}
this.resolveConstraints(0);
this.setProperties(properties);
@@ -601,10 +608,15 @@ class View extends BaseObject {
if (series[0].callback) {
animationCallback(series[0].callback, false);
}
anchor = anchor ||
series.filter(function(animation) {
return !animation.complete;
})[0].anchor;
if (!anchor) {
for (let j = 0, jj = series.length; j < jj; ++j) {
const animation = series[j];
if (!animation.complete) {
anchor = animation.anchor;
break;
}
}
}
}
this.animations_.length = 0;
this.cancelAnchor_ = anchor;
@@ -754,6 +766,7 @@ class View extends BaseObject {
*/
setViewportSize(opt_size) {
this.viewportSize_ = Array.isArray(opt_size) ? opt_size.slice() : [100, 100];
this.resolveConstraints(0);
}
/**
@@ -785,6 +798,13 @@ class View extends BaseObject {
return this.constraints_;
}
/**
* @return {boolean} Resolution constraint is set
*/
getConstrainResolution() {
return this.options_.constrainResolution;
}
/**
* @param {Array<number>=} opt_hints Destination array.
* @return {Array<number>} Hint.
@@ -1611,6 +1631,9 @@ export function createResolutionConstraint(options) {
const smooth =
options.smoothResolutionConstraint !== undefined ? options.smoothResolutionConstraint : true;
const showFullExtent =
options.showFullExtent !== undefined ? options.showFullExtent : false;
const projection = createProjection(options.projection, 'EPSG:3857');
const projExtent = projection.getExtent();
let constrainOnlyCenter = options.constrainOnlyCenter;
@@ -1628,10 +1651,10 @@ export function createResolutionConstraint(options) {
if (options.constrainResolution) {
resolutionConstraint = createSnapToResolutions(resolutions, smooth,
!constrainOnlyCenter && extent);
!constrainOnlyCenter && extent, showFullExtent);
} else {
resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth,
!constrainOnlyCenter && extent);
!constrainOnlyCenter && extent, showFullExtent);
}
} else {
// calculate the default min and max resolution
@@ -1677,10 +1700,10 @@ export function createResolutionConstraint(options) {
if (options.constrainResolution) {
resolutionConstraint = createSnapToPower(
zoomFactor, maxResolution, minResolution, smooth,
!constrainOnlyCenter && extent);
!constrainOnlyCenter && extent, showFullExtent);
} else {
resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth,
!constrainOnlyCenter && extent);
!constrainOnlyCenter && extent, showFullExtent);
}
}
return {constraint: resolutionConstraint, maxResolution: maxResolution,

View File

@@ -325,7 +325,6 @@ class Attribution extends Control {
* Update the attribution element.
* @param {import("../MapEvent.js").default} mapEvent Map event.
* @this {Attribution}
* @api
*/
export function render(mapEvent) {
this.updateElement_(mapEvent.frameState);

View File

@@ -79,9 +79,10 @@ class Control extends BaseObject {
this.listenerKeys = [];
/**
* @private
* @type {function(import("../MapEvent.js").default): void}
*/
this.render = options.render ? options.render : VOID;
this.render_ = options.render ? options.render : VOID;
if (options.target) {
this.setTarget(options.target);
@@ -134,6 +135,16 @@ class Control extends BaseObject {
}
}
/**
* Update the projection. Rendering of the coordinates is done in
* `handleMouseMove` and `handleMouseUp`.
* @param {import("../MapEvent.js").default} mapEvent Map event.
* @api
*/
render(mapEvent) {
this.render_.call(this, mapEvent);
}
/**
* This function is used to set a target element for the control. It has no
* effect if it is called after the control has been added to the map (i.e.

View File

@@ -9,6 +9,29 @@ import EventType from '../events/EventType.js';
const events = ['fullscreenchange', 'webkitfullscreenchange', 'MSFullscreenChange'];
/**
* @enum {string}
*/
const FullScreenEventType = {
/**
* Triggered after the map entered fullscreen.
* @event FullScreenEventType#enterfullscreen
* @api
*/
ENTERFULLSCREEN: 'enterfullscreen',
/**
* Triggered after the map leave fullscreen.
* @event FullScreenEventType#leavefullscreen
* @api
*/
LEAVEFULLSCREEN: 'leavefullscreen'
};
/**
* @typedef {Object} Options
* @property {string} [className='ol-full-screen'] CSS class name.
@@ -38,6 +61,8 @@ const events = ['fullscreenchange', 'webkitfullscreenchange', 'MSFullscreenChang
* The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
* toggle the map in full screen mode.
*
* @fires FullScreenEventType#enterfullscreen
* @fires FullScreenEventType#leavefullscreen
* @api
*/
class FullScreen extends Control {
@@ -162,9 +187,11 @@ class FullScreen extends Control {
if (isFullScreen()) {
this.setClassName_(this.button_, true);
replaceNode(this.labelActiveNode_, this.labelNode_);
this.dispatchEvent(FullScreenEventType.ENTERFULLSCREEN);
} else {
this.setClassName_(this.button_, false);
replaceNode(this.labelNode_, this.labelActiveNode_);
this.dispatchEvent(FullScreenEventType.LEAVEFULLSCREEN);
}
if (map) {
map.updateSize();

View File

@@ -248,7 +248,6 @@ class MousePosition extends Control {
* `handleMouseMove` and `handleMouseUp`.
* @param {import("../MapEvent.js").default} mapEvent Map event.
* @this {MousePosition}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;

View File

@@ -17,6 +17,7 @@ import {replaceNode} from '../dom.js';
import {listen, listenOnce} from '../events.js';
import EventType from '../events/EventType.js';
import {containsExtent, equals as equalsExtent, getBottomRight, getTopLeft, scaleFromCenter} from '../extent.js';
import View from '../View.js';
/**
@@ -59,8 +60,8 @@ class ControlledMap extends PluggableMap {
* @property {HTMLElement|string} [target] Specify a target if you want the control
* to be rendered outside of the map's viewport.
* @property {string} [tipLabel='Overview map'] Text label to use for the button tip.
* @property {import("../View.js").default} [view] Custom view for the overview map. If not provided,
* a default view with an EPSG:3857 projection will be used.
* @property {View} [view] Custom view for the overview map (should use same projection as main map). If not provided,
* a default view with the same projection as the main map will be used.
*/
@@ -167,6 +168,13 @@ class OverviewMap extends Control {
this.ovmapDiv_ = document.createElement('div');
this.ovmapDiv_.className = 'ol-overviewmap-map';
/**
* Explicitly given view to be used instead of a view derived from the main map.
* @type {View}
* @private
*/
this.view_ = options.view;
/**
* @type {ControlledMap}
* @private
@@ -303,6 +311,14 @@ class OverviewMap extends Control {
* @private
*/
bindView_(view) {
if (!this.view_) {
// Unless an explicit view definition was given, derive default from whatever main map uses.
const newView = new View({
projection: view.getProjection()
});
this.ovmap_.setView(newView);
}
view.addEventListener(getChangeEventType(ViewProperty.ROTATION), this.boundHandleRotationChanged_);
// Sync once with the new view
this.handleRotationChanged_();
@@ -603,7 +619,6 @@ class OverviewMap extends Control {
* Update the overview map element.
* @param {import("../MapEvent.js").default} mapEvent Map event.
* @this {OverviewMap}
* @api
*/
export function render(mapEvent) {
this.validateExtent_();

View File

@@ -131,8 +131,9 @@ class Rotate extends Control {
// upon it
return;
}
if (view.getRotation() !== undefined) {
if (this.duration_ > 0) {
const rotation = view.getRotation();
if (rotation !== undefined) {
if (this.duration_ > 0 && rotation % (2 * Math.PI) !== 0) {
view.animate({
rotation: 0,
duration: this.duration_,
@@ -150,7 +151,6 @@ class Rotate extends Control {
* Update the rotate control element.
* @param {import("../MapEvent.js").default} mapEvent Map event.
* @this {Rotate}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;

View File

@@ -418,7 +418,6 @@ class ScaleLine extends Control {
* Update the scale line element.
* @param {import("../MapEvent.js").default} mapEvent Map event.
* @this {ScaleLine}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;

Some files were not shown because too many files have changed in this diff Show More