diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 77e9bb40a..0e55b878c 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -14,6 +14,7 @@ comma-dangle: 0, no-extra-boolean-cast: 0, brace-style: 0, + prefer-template: 0, no-multiple-empty-lines: 0, valid-jsdoc: 0, indent: [2, 2, { diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..e4bccbc26 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,17 @@ +name: Test + +on: + pull_request: + branches: + - master + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12 + - name: Make dist + run: make dist diff --git a/.gitignore b/.gitignore index 625dadedc..bc3ec3361 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ -/.build -/.idea -/dist -/node_modules +/.build/ +/dist/ +/node_modules/ /examples/example-list.js /package-lock.json /compilation-stats.json diff --git a/.npmignore b/.npmignore index 619ebd6f8..be2e62c53 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,4 @@ /.build -/.idea examples/example-list.js +/*.tgz +/*.zip diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b0c0795ca..000000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -sudo: false - -language: node_js - -node_js: - - "8" - -cache: - directories: - - node_modules - -script: - - make dist diff --git a/CHANGES.md b/CHANGES.md index 03e9fd0cc..234aba46b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,37 @@ # Changelog +# v 2.10 - 2019-10-10 + +* Changes + * Add a WMTS example. + * Port to Cesium 1.62. + * Port to OpenLayers 6 while staying compatible with OpenLayers 5. + +# v 2.9 - 2019-04-05 + +* Changes + * Port to Cesium 1.56.1. + +# v 2.8 - 2019-03-13 + +* Changes + * Port to Cesium 1.55. + +# v 2.7.2 - 2019-02-12 + +* Changes + * Fix a type + +# v 2.7.1 - 2019-02-08 + +* Changes + * Fix release + +# v 2.7 - 2019-02-08 +* Changes + * Port to Cesium 1.54. + * Document code using typescript. + # v 2.6 - 2018-12-06 * Changes diff --git a/Makefile b/Makefile index 6c4afb57c..3417d9655 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ help: .PHONY: serve serve: .build/node_modules.timestamp - npm run serve + npm start .PHONY: dist dist: dist/olcesium.js css/olcs.css CHANGES.md .build/jsdoc.timestamp .build/dist-examples.timestamp lint @@ -36,8 +36,7 @@ dist-examples: .build/dist-examples.timestamp dist-apidoc: .build/jsdoc.timestamp .build/jsdoc.timestamp: $(SRC_JS_FILES) .build/node_modules.timestamp - mkdir -p dist - node node_modules/.bin/jsdoc src/olcs -d dist/apidoc + npm run doc mkdir -p $(dir $@) touch $@ @@ -71,7 +70,7 @@ cleanall: TARGET=examples ./node_modules/.bin/eslint $(filter-out .build/node_modules.timestamp, $^) touch $@ -CS_BUILD=node_modules/@camptocamp/cesium/Build +CS_BUILD=node_modules/cesium/Build OL_CSS_DIR=node_modules/ol .build/dist-examples.timestamp: dist/examples/index.html $(EXAMPLES_FILES) $(WEBPACK_CONFIG_FILES) .build/node_modules.timestamp npm run build-examples diff --git a/README.md b/README.md index 112c8f00e..1db1caadf 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ ol3d.setEnabled(true); For Cesium integration see [ol-cesium-webpack-example](https://github.com/gberaudo/ol-cesium-webpack-example) based on the official `Cesium With Webpack` example. -### As an old-fashioned independant library +### As an old-fashioned independent library - build the library in dist/olcs.js: ```bash @@ -110,7 +110,7 @@ Limitations ----------- - OpenLayers unmanaged layers are not discoverable and as a consequence not -supported. Plain layers should be used instead or the synchronization managed +supported. Plain layers should be used instead of the synchronization managed manually. See https://github.com/openlayers/ol-cesium/issues/350. - OpenLayers interactions are not supported in 3d. See https://github.com/openlayers/ol-cesium/issues/655. diff --git a/examples/bing.js b/examples/bing.js index 46210c312..e45312924 100644 --- a/examples/bing.js +++ b/examples/bing.js @@ -1,8 +1,6 @@ /** * @module examples.main */ -const exports = {}; - import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -23,9 +21,9 @@ const ol2d = new olMap({ ], controls: olControlDefaults({ attribution: true, - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -45,5 +43,3 @@ scene.terrainProvider = Cesium.createWorldTerrain(); ol3d.setEnabled(true); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - -export default exports; diff --git a/examples/customProj.js b/examples/customProj.js index de31e1629..e49770e8e 100644 --- a/examples/customProj.js +++ b/examples/customProj.js @@ -1,7 +1,6 @@ /** * @module examples.customProj */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import olSourceImageWMS from 'ol/source/ImageWMS.js'; @@ -71,5 +70,3 @@ scene.terrainProvider = Cesium.createWorldTerrain(); ol3d.setEnabled(true); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - -export default exports; diff --git a/examples/exports.js b/examples/exports.js index 40949a63a..e3f24820b 100644 --- a/examples/exports.js +++ b/examples/exports.js @@ -1,7 +1,6 @@ /** * @module examples.exports */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import {transform} from 'ol/proj.js'; import olView from 'ol/View.js'; @@ -44,5 +43,3 @@ setInterval(printInfo, 100); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); window['camera'] = camera; window['olProjTransform'] = transform; - -export default exports; diff --git a/examples/fillstyle.js b/examples/fillstyle.js index 75c2a8d33..3a5e83614 100644 --- a/examples/fillstyle.js +++ b/examples/fillstyle.js @@ -1,7 +1,6 @@ /** * @module examples.vectors */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -66,9 +65,9 @@ const map = new olMap({ ], target: 'map2d', controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), view: new olView({ center: [-2e6, 1e6], @@ -97,5 +96,3 @@ window['toggleClampToGround'] = function() { map.removeLayer(vectorLayer); map.addLayer(vectorLayer); }; - -export default exports; diff --git a/examples/groundvectors.js b/examples/groundvectors.js index 586eb69e3..5bfb5826a 100644 --- a/examples/groundvectors.js +++ b/examples/groundvectors.js @@ -1,7 +1,6 @@ /** * @module examples.vectors */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -16,8 +15,8 @@ import olStyleCircle from 'ol/style/Circle.js'; import olSourceVector from 'ol/source/Vector.js'; import olFormatGeoJSON from 'ol/format/GeoJSON.js'; import olLayerVector from 'ol/layer/Vector.js'; -import olFeature from 'ol/Feature'; -import olCircle from 'ol/geom/Circle'; +import olFeature from 'ol/Feature.js'; +import olCircle from 'ol/geom/Circle.js'; const image = new olStyleCircle({ radius: 5, @@ -124,9 +123,9 @@ const map = new olMap({ ], target: 'map2d', controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), view: new olView({ center: [16880670.33392873, -3565966.2275828626], @@ -156,6 +155,3 @@ window['scene'] = scene; document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); ol3d.enableAutoRenderLoop(); - - -export default exports; diff --git a/examples/icon-position.js b/examples/icon-position.js index 8f800a49c..817e1c4c6 100644 --- a/examples/icon-position.js +++ b/examples/icon-position.js @@ -1,7 +1,6 @@ /** * @module examples.vectors */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -81,9 +80,9 @@ const map = new olMap({ ], target: 'map2d', controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), view: new olView({ center: [850000, 200000], @@ -124,6 +123,3 @@ if (pivot) { const rotateAroundAxis = olcsCore.rotateAroundAxis; rotateAroundAxis(camera, -Math.PI / 4, axis, transform, options); } - - -export default exports; diff --git a/examples/image-static.js b/examples/image-static.js index ad5e99f95..ca8a60948 100644 --- a/examples/image-static.js +++ b/examples/image-static.js @@ -1,7 +1,6 @@ /** * @module examples.image-static */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import {transform} from 'ol/proj.js'; import olView from 'ol/View.js'; @@ -32,9 +31,9 @@ const ol2d = new olMap({ }) ], controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -53,6 +52,3 @@ ol3d.setEnabled(true); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - - -export default exports; diff --git a/examples/imageWMS.js b/examples/imageWMS.js index a20cec9bf..f26c90212 100644 --- a/examples/imageWMS.js +++ b/examples/imageWMS.js @@ -1,8 +1,6 @@ /** * @module examples.main */ -const exports = {}; - import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -13,7 +11,7 @@ import olLayerTile from 'ol/layer/Tile.js'; import olMap from 'ol/Map.js'; const imageWMSSource = new olSourceImageWMS({ - url: 'https://demo.boundlessgeo.com/geoserver/wms', + url: 'https://ahocevar.com/geoserver/wms', params: {'LAYERS': 'topp:states'}, ratio: 1 }); @@ -30,9 +28,9 @@ const ol2d = new olMap({ }) ], controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -52,5 +50,3 @@ scene.terrainProvider = Cesium.createWorldTerrain(); ol3d.setEnabled(true); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - -export default exports; diff --git a/examples/inject_ol_cesium.js b/examples/inject_ol_cesium.js index 61360c3da..da4a12bd4 100644 --- a/examples/inject_ol_cesium.js +++ b/examples/inject_ol_cesium.js @@ -7,7 +7,7 @@ window.IS_DEV = isDev; var cs = isDev ? 'CesiumUnminified/Cesium.js' : 'Cesium/Cesium.js'; - window.CESIUM_URL = `../node_modules/@camptocamp/cesium/Build/${cs}`; + window.CESIUM_URL = `../node_modules/cesium/Build/${cs}`; if (!window.LAZY_CESIUM) { document.write(``); } diff --git a/examples/kml.js b/examples/kml.js index 756abc356..89752c735 100644 --- a/examples/kml.js +++ b/examples/kml.js @@ -1,7 +1,6 @@ /** * @module examples.kml */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import {transform} from 'ol/proj.js'; import olView from 'ol/View.js'; @@ -18,9 +17,9 @@ const ol2d = new olMap({ }) ], controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -42,5 +41,3 @@ ol3d.getDataSources().add(Cesium.KmlDataSource.load( )); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - -export default exports; diff --git a/examples/layer-group.js b/examples/layer-group.js index ff0acb6fe..2284e65d0 100644 --- a/examples/layer-group.js +++ b/examples/layer-group.js @@ -1,7 +1,6 @@ /** * @module examples.layer-group */ -const exports = {}; import olMap from 'ol/Map.js'; import olView from 'ol/View.js'; import olLayerGroup from 'ol/layer/Group.js'; @@ -15,16 +14,18 @@ const layer0 = new olLayerTile({ source: new olSourceOSM() }); +const key = 'pk.eyJ1IjoiZ2JvMiIsImEiOiJjazFraHV4N3gwZHliM2JucHYxdTNnNXh1In0.tzs3TxoVCaMNQf455mh-3w'; + const layer10 = new olLayerTile({ source: new olSourceTileJSON({ - url: 'https://api.tiles.mapbox.com/v3/mapbox.20110804-hoa-foodinsecurity-3month.json?secure', + url: 'https://api.tiles.mapbox.com/v4/mapbox.20110804-hoa-foodinsecurity-3month.json?secure&access_token=' + key, crossOrigin: 'anonymous' }) }); const layer11 = new olLayerTile({ source: new olSourceTileJSON({ - url: 'https://api.tiles.mapbox.com/v3/mapbox.world-borders-light.json?secure', + url: 'https://api.tiles.mapbox.com/v4/mapbox.world-borders-light.json?secure&access_token=' + key, crossOrigin: 'anonymous' }) }); @@ -69,5 +70,3 @@ window['toggleLayer'] = function(element, name) { window['setLayerOpacity'] = function(element, name) { getLayer(name).setOpacity(parseFloat(element.value)); }; - -export default exports; diff --git a/examples/lazy.js b/examples/lazy.js index 3cbaf2351..1a46f11cd 100644 --- a/examples/lazy.js +++ b/examples/lazy.js @@ -1,7 +1,6 @@ /** * @module examples.lazy */ -const exports = {}; import {transform} from 'ol/proj.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -18,9 +17,9 @@ const ol2d = new olMap({ }) ], controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -31,6 +30,3 @@ const ol2d = new olMap({ window['manager'] = new olcsContribManager(window.CESIUM_URL, {map: ol2d}); - - -export default exports; diff --git a/examples/main.js b/examples/main.js index 10498f988..57b779c32 100644 --- a/examples/main.js +++ b/examples/main.js @@ -1,7 +1,6 @@ /** * @module examples.main */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import {transform} from 'ol/proj.js'; import olView from 'ol/View.js'; @@ -18,9 +17,9 @@ const ol2d = new olMap({ }) ], controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -58,6 +57,3 @@ window['toggleTime'] = function() { timeElt.style.display = 'none'; } }; - - -export default exports; diff --git a/examples/oldfashioned.html b/examples/oldfashioned.html index e02e46f13..8fbdd36d7 100644 --- a/examples/oldfashioned.html +++ b/examples/oldfashioned.html @@ -1,14 +1,14 @@ - + - + - +

Old-fashioned example

diff --git a/examples/overlay.js b/examples/overlay.js index fd71d07f2..eafb9be8b 100644 --- a/examples/overlay.js +++ b/examples/overlay.js @@ -1,7 +1,6 @@ /** * @module examples.overlay */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olMap from 'ol/Map.js'; import olSourceOSM from 'ol/source/OSM.js'; @@ -23,9 +22,9 @@ const ol2d = new olMap({ }) ], controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), target: 'map', view: new olView({ @@ -173,5 +172,3 @@ class OverlayHandler { new OverlayHandler(ol2d, ol3d, scene); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - -export default exports; diff --git a/examples/rastersync.html b/examples/rastersync.html index da2cc8a02..22cbf570c 100644 --- a/examples/rastersync.html +++ b/examples/rastersync.html @@ -29,27 +29,27 @@ OpenAerial layer - + - +
- + - +
- + - +
diff --git a/examples/rastersync.js b/examples/rastersync.js index 227efff8f..81d3b8d67 100644 --- a/examples/rastersync.js +++ b/examples/rastersync.js @@ -1,7 +1,6 @@ /** * @module examples.rastersync */ -const exports = {}; import olSourceTileWMS from 'ol/source/TileWMS.js'; import olSourceStamen from 'ol/source/Stamen.js'; import OLCesium from 'olcs/OLCesium.js'; @@ -29,8 +28,9 @@ const layer1 = new olLayerTile({ }) }); +const key = 'pk.eyJ1IjoiZ2JvMiIsImEiOiJjazFraHV4N3gwZHliM2JucHYxdTNnNXh1In0.tzs3TxoVCaMNQf455mh-3w'; const tileJsonSource = new olSourceTileJSON({ - url: 'https://api.tiles.mapbox.com/v3/mapbox.world-borders-light.json', + url: 'https://api.tiles.mapbox.com/v4/mapbox.world-borders-light.json?access_token=' + key, crossOrigin: 'anonymous' }); @@ -61,7 +61,7 @@ const addStamen = function() { // eslint-disable-line no-unused-vars }; const tileWMSSource = new olSourceTileWMS({ - url: 'http://demo.boundlessgeo.com/geoserver/wms', + url: 'https://ahocevar.com/geoserver/wms', params: {'LAYERS': 'topp:states', 'TILED': true}, serverType: 'geoserver', crossOrigin: 'anonymous' @@ -106,5 +106,3 @@ window['global'] = { layer1, layer2 }; - -export default exports; diff --git a/examples/reprojection.html b/examples/reprojection.html new file mode 100644 index 000000000..ce62651c6 --- /dev/null +++ b/examples/reprojection.html @@ -0,0 +1,16 @@ + + + + + + + Reprojection example + + + +
+ + + + + \ No newline at end of file diff --git a/examples/reprojection.js b/examples/reprojection.js new file mode 100644 index 000000000..c2b399f50 --- /dev/null +++ b/examples/reprojection.js @@ -0,0 +1,59 @@ +/** + * @module examples.reprojection + */ +const exports = {}; + +import proj4 from 'proj4'; +import {register} from 'ol/proj/proj4.js'; +import {get as getProjection} from 'ol/proj.js'; +import olTileWMS from 'ol/source/TileWMS.js'; +import olMap from 'ol/Map.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olView from 'ol/View.js'; +import OLCesium from 'olcs/OLCesium.js'; +import olSourceOSM from 'ol/source/OSM.js'; + +proj4.defs('EPSG:21781', '+proj=somerc +lat_0=46.95240555555556 ' + + '+lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel ' + + '+towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs'); +register(proj4); +const proj21781 = getProjection('EPSG:21781'); +proj21781.setExtent([485071.54, 75346.36, 828515.78, 299941.84]); +const source = new olTileWMS({ + attributions: ['© ' + + '' + + 'Pixelmap 1:1000000 / geo.admin.ch'], + crossOrigin: 'anonymous', + params: { + 'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale', + 'FORMAT': 'image/jpeg' + }, + url: 'http://wms.geo.admin.ch/', + projection: 'EPSG:21781' +}); +const ol2d = new olMap({ + layers: [ + new olLayerTile({source: new olSourceOSM()}), + new olLayerTile({ + source + }) + ], + target: 'map', + view: new olView({ + projection: 'EPSG:4326', + center: [6.56273, 46.51781], + zoom: 6 + }) +}); +const ol3d = new OLCesium({map: ol2d}); +const scene = ol3d.getCesiumScene(); +const terrainProvider = new Cesium.CesiumTerrainProvider({ + url: '//assets.agi.com/stk-terrain/world' +}); +scene.terrainProvider = terrainProvider; +ol3d.setEnabled(true); + +document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); + +export default exports; diff --git a/examples/rotate.js b/examples/rotate.js index 5b20a165b..c9d896025 100644 --- a/examples/rotate.js +++ b/examples/rotate.js @@ -1,7 +1,6 @@ /** * @module examples.rotate */ -const exports = {}; import olcsCore from 'olcs/core.js'; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; @@ -19,9 +18,9 @@ const map = new olMap({ ], target: 'map2d', controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), view: new olView({ center: [333333, 1500000], @@ -172,5 +171,3 @@ OlcsControl.prototype.tiltOnGlobe = function(angle) { window['control'] = new OlcsControl(ol3d); // eslint-disable-line no-unused-vars - -export default exports; diff --git a/examples/selection.js b/examples/selection.js index 8804f4025..4a995507d 100644 --- a/examples/selection.js +++ b/examples/selection.js @@ -1,7 +1,6 @@ /** * @module examples.selection */ -const exports = {}; import olStyleStroke from 'ol/style/Stroke.js'; import olStyleFill from 'ol/style/Fill.js'; import olStyleStyle from 'ol/style/Style.js'; @@ -63,6 +62,3 @@ map.on('click', (e) => { selectedFeature.setStyle(selectionStyle); } }); - - -export default exports; diff --git a/examples/sidebyside.js b/examples/sidebyside.js index dedc29ab3..acdca25a5 100644 --- a/examples/sidebyside.js +++ b/examples/sidebyside.js @@ -1,7 +1,6 @@ /** * @module examples.sidebyside */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olSourceOSM from 'ol/source/OSM.js'; import olLayerTile from 'ol/layer/Tile.js'; @@ -33,5 +32,3 @@ scene.terrainProvider = Cesium.createWorldTerrain(); ol3d.setEnabled(true); document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); - -export default exports; diff --git a/examples/synthvectors.js b/examples/synthvectors.js index 74450454a..c84d31227 100644 --- a/examples/synthvectors.js +++ b/examples/synthvectors.js @@ -1,7 +1,6 @@ /** * @module examples.synthvectors */ -const exports = {}; import olLayerVector from 'ol/layer/Vector.js'; import olSourceVector from 'ol/source/Vector.js'; import olStyleFill from 'ol/style/Fill.js'; @@ -118,6 +117,3 @@ window['addFeatures'] = function() { document.getElementById('created').innerHTML = `Features created in ${created}ms.`; document.getElementById('added').innerHTML = `Features added in ${added}ms.`; }; - - -export default exports; diff --git a/examples/tracking.js b/examples/tracking.js index bd0c72f26..206e703ec 100644 --- a/examples/tracking.js +++ b/examples/tracking.js @@ -1,7 +1,6 @@ /** * @module examples.tracking */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -54,9 +53,9 @@ const map = new olMap({ ], target: 'map2d', controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), view: new olView({ center: [0, 0], @@ -86,6 +85,3 @@ setInterval(() => { ]); iconFeature.changed(); }, 100); - - -export default exports; diff --git a/examples/vectors.js b/examples/vectors.js index 60bdba660..89bbeedd5 100644 --- a/examples/vectors.js +++ b/examples/vectors.js @@ -1,7 +1,6 @@ /** * @module examples.vectors */ -const exports = {}; import OLCesium from 'olcs/OLCesium.js'; import olView from 'ol/View.js'; import {defaults as olControlDefaults} from 'ol/control.js'; @@ -274,9 +273,9 @@ const cartographicRectangle2 = new olFeature({ cartographicRectangle2.setStyle(cartographicRectangleStyle); const vectorLayer = new olLayerVector({ - style: styleFunction + style: styleFunction, + source: vectorSource }); -setTimeout(() => vectorLayer.setSource(vectorSource), 2000); const vectorSource2 = new olSourceVector({ features: [iconFeature, textFeature, cervinFeature, ...modelFeatures, cartographicRectangle, @@ -307,9 +306,9 @@ const map = new olMap({ ], target: 'map2d', controls: olControlDefaults({ - attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + attributionOptions: { collapsible: false - }) + } }), view: new olView({ center: [0, 0], @@ -410,6 +409,3 @@ window['scene'] = scene; document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); ol3d.enableAutoRenderLoop(); - - -export default exports; diff --git a/examples/wmts.html b/examples/wmts.html new file mode 100644 index 000000000..12c821079 --- /dev/null +++ b/examples/wmts.html @@ -0,0 +1,15 @@ + + + + + + + olcesium wmts example + + + +
+ + + + diff --git a/examples/wmts.js b/examples/wmts.js new file mode 100644 index 000000000..9e7300e1e --- /dev/null +++ b/examples/wmts.js @@ -0,0 +1,71 @@ +/** + * @module examples.wmts + */ +import OLCesium from 'olcs/OLCesium.js'; + +Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0MzAyNzUyYi0zY2QxLTQxZDItODRkOS1hNTA3MDU3ZTBiMDUiLCJpZCI6MjU0MSwiaWF0IjoxNTMzNjI1MTYwfQ.oHn1SUWJa12esu7XUUtEoc1BbEbuZpRocLetw6M6_AA'; + +import Map from 'ol/Map.js'; +import View from 'ol/View.js'; +import {getWidth, getTopLeft} from 'ol/extent.js'; +import TileLayer from 'ol/layer/Tile.js'; +import {get as getProjection} from 'ol/proj.js'; +import OSM from 'ol/source/OSM.js'; +import WMTS from 'ol/source/WMTS.js'; +import WMTSTileGrid from 'ol/tilegrid/WMTS.js'; + + +const projection = getProjection('EPSG:3857'); +const projectionExtent = projection.getExtent(); +const size = getWidth(projectionExtent) / 256; +const resolutions = new Array(14); +const matrixIds = new Array(14); +for (let z = 0; z < 14; ++z) { + // generate resolutions and matrixIds arrays for this WMTS + resolutions[z] = size / Math.pow(2, z); + matrixIds[z] = z; +} + +const map = new Map({ + layers: [ + new TileLayer({ + source: new OSM(), + opacity: 0.7 + }), + new TileLayer({ + opacity: 0.7, + source: new WMTS({ + attributions: 'Tiles © ArcGIS', + url: 'https://services.arcgisonline.com/arcgis/rest/' + + 'services/Demographics/USA_Population_Density/MapServer/WMTS/', + layer: '0', + matrixSet: 'EPSG:3857', + format: 'image/png', + projection, + tileGrid: new WMTSTileGrid({ + origin: getTopLeft(projectionExtent), + resolutions, + matrixIds + }), + style: 'default', + wrapX: true + }) + }) + ], + target: 'map', + view: new View({ + center: [-11158582, 4813697], + zoom: 4 + }) +}); + +const ol2d = map; +const ol3d = new OLCesium({ + map: ol2d, +}); +const scene = ol3d.getCesiumScene(); +scene.terrainProvider = Cesium.createWorldTerrain(); +ol3d.setEnabled(true); + +document.getElementById('enable').addEventListener('click', () => ol3d.setEnabled(!ol3d.getEnabled())); diff --git a/externs/olcsx.js b/externs/olcsx.js deleted file mode 100644 index 38587f92d..000000000 --- a/externs/olcsx.js +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @externs - */ - -/** - * @const - */ -const olcsx = {}; - - -/** - * @typedef {{ - * map: (!ol.Map), - * target: (Element|string|undefined), - * createSynchronizers: (undefined|function(!ol.Map, !Cesium.Scene, !Cesium.DataSourceCollection): Array.), - * time: (undefined|function(): Cesium.JulianDate), - * stopOpenLayersEventsPropagation: (boolean|undefined), - * sceneOptions: (Cesium.SceneOptions|undefined) - * }} - * @api - */ -olcsx.OLCesiumOptions; - - -/** - * The OpenLayers map we want to show on a Cesium scene. - * @type {!ol.Map} - * @api - */ -olcsx.OLCesiumOptions.prototype.map; - -/** - * Control the current time used by Cesium. - * @type {undefined|function(): Cesium.JulianDate} - * @api - */ -olcsx.OLCesiumOptions.prototype.time; - -/** - * Allows the passing of property value to the `Cesium.Scene`. - * @type {Cesium.SceneOptions|undefined} - * @api - */ -olcsx.OLCesiumOptions.prototype.sceneOptions; - -/** - * Target element for the Cesium scene. - * @type {Element|string|undefined} - * @api - */ -olcsx.OLCesiumOptions.prototype.target; - -/** - * Callback function which will be called by the {@link olcs.OLCesium} - * constructor to create custom synchronizers. Receives an `ol.Map` and a - * `Cesium.Scene` as arguments, and needs to return an array of - * {@link olcs.AbstractSynchronizer}. - * @type {undefined|function(!ol.Map, !Cesium.Scene, !Cesium.DataSourceCollection): Array.} - * @api - */ -olcsx.OLCesiumOptions.prototype.createSynchronizers; - -/** - * Prevent propagation of mouse/touch events to OpenLayers when Cesium is active. - * @type {boolean|undefined} - */ -olcsx.OLCesiumOptions.prototype.stopOpenLayersEventsPropagation; - - -/** - * Core namespace. - * @const - */ -olcsx.core = {}; - - -/** - * Context for feature conversion. - * @typedef {{ - * projection: (!(ol.proj.Projection|string)), - * primitives: (!Cesium.PrimitiveCollection), - * featureToCesiumMap: (Object.< - * number, - * Array>), - * billboards: (!Cesium.BillboardCollection) - * }} - * @api - */ -olcsx.core.OlFeatureToCesiumContext; - - -/** - * Options for rotate around axis core function. - * @typedef {{ - * duration: (number|undefined), - * easing: (function(number):number|undefined), - * callback: (function()|undefined) - * }} - * @api - */ -olcsx.core.RotateAroundAxisOption; - - -/** - * @typedef {{ - * url: string, - * subdomains: string - * }} - * @api - */ -olcsx.core.CesiumUrlDefinition; - - -/** - * @typedef {{ - * layer: !ol.layer.Base, - * parents: Array - * }} - */ -olcsx.LayerWithParents; - - -/** - * Options for SynchronizedOverlay - * @typedef {{ - * scene: !Cesium.Scene, - * parent: !ol.Overlay, - * synchronizer: !olcs.OverlaySynchronizer - * }} - * @api - */ -olcsx.SynchronizedOverlayOptions; - - -/** - * @const - */ -olcsx.contrib = {}; - -/** - * @typedef {{ - * map: ol.Map, - * cameraExtentInRadians: (ol.Extent|undefined) - * }} - * @api - */ -olcsx.contrib.ManagerOptions; - - -/** - * @typedef {{ - * debugModelMatrix: (Cesium.Matrix4|undefined), - * cesiumOptions: Cesium.ModelFromGltfOptions - * }} - */ -olcsx.ModelStyle; diff --git a/gh-pages-template/_config.yml b/gh-pages-template/_config.yml index 6cf898ed6..dcfb52c0a 100644 --- a/gh-pages-template/_config.yml +++ b/gh-pages-template/_config.yml @@ -3,6 +3,6 @@ description: OpenLayers - Cesium integration library google_analytics: show_downloads: true theme: jekyll-theme-architect - +exclude: [] gems: - jekyll-mentions diff --git a/package.json b/package.json index 10f0bf5ec..358fb6bf9 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,15 @@ { "name": "ol-cesium", - "version": "2.6.0", + "version": "2.10.0", "description": "OpenLayers Cesium integration library", "scripts": { "build-examples": "cross-env NODE_ENV=production TARGET=examples webpack --progress --bail", "build-library": "cross-env NODE_ENV=production TARGET=library webpack --progress --bail", "build-library-debug": "cross-env NODE_ENV=development TARGET=library webpack --progress --bail", "build-umd": "cross-env NODE_ENV=production TARGET=umd webpack --progress --bail", - "serve": "cross-env DEV_SERVER=1 TARGET=examples webpack-dev-server --port 3000 --progress --watch --bail --debug" + "start": "cross-env DEV_SERVER=1 TARGET=examples webpack-dev-server --port 3000 --progress --watch --bail --debug", + "typecheck": "tsc --pretty", + "doc": "typedoc --name ol-cesium --excludeExternals --out dist/apidoc" }, "main": "./dist/olcesium.js", "module": "./dist/olcesium.umd.js", @@ -20,29 +22,32 @@ "url": "https://github.com/openlayers/ol-cesium/issues" }, "devDependencies": { - "@babel/core": "7.2.0", - "@babel/preset-env": "7.2.0", - "@camptocamp/cesium": "1.52.0", - "@mapbox/geojsonhint": "2.0.1", - "babel-loader": "8.0.4", - "copy-webpack-plugin": "4.6.0", - "cross-env": "5.2.0", - "eslint": "5.9.0", - "eslint-config-openlayers": "11.0.0", - "eslint-import-resolver-webpack": "0.10.1", - "fs-extra": "7.0.1", + "@babel/core": "^7.6.3", + "@babel/preset-env": "^7.6.3", + "@mapbox/geojsonhint": "3.0.0", + "@types/cesium": "^1.59.1", + "babel-loader": "^8.0.6", + "cesium": "^1.62.0", + "copy-webpack-plugin": "^5.0.4", + "cross-env": "^6.0.3", + "eslint": "^6.5.1", + "eslint-config-openlayers": "^12.0.0", + "eslint-import-resolver-webpack": "^0.11.1", + "fs-extra": "^8.1.0", "html-loader": "0.5.5", "html-webpack-plugin": "3.2.0", - "htmlparser2": "3.10.0", - "jsdoc": "3.5.5", + "htmlparser2": "^4.0.0", + "jsdoc": "^3.6.3", "ls": "0.2.1", "nomnom": "1.8.1", - "ol": "5.3.0", + "ol": "^6.0.1", "proj4": "2.5.0", - "temp": "0.8.3", - "webpack": "4.27.1", - "webpack-cli": "3.1.2", - "webpack-dev-server": "3.1.10", - "webpack-merge": "4.1.4" + "temp": "^0.9.0", + "typedoc": "^0.15.0", + "typescript": "^3.6.4", + "webpack": "^4.41.0", + "webpack-cli": "^3.3.9", + "webpack-dev-server": "^3.8.2", + "webpack-merge": "^4.2.2" } } diff --git a/src/olcs/AbstractSynchronizer.js b/src/olcs/AbstractSynchronizer.js index 77ce1efce..eff30a408 100644 --- a/src/olcs/AbstractSynchronizer.js +++ b/src/olcs/AbstractSynchronizer.js @@ -91,7 +91,7 @@ class AbstractSynchronizer { * @private */ addLayers_(root) { - /** @type {Array} */ + /** @type {Array} */ const fifo = [{ layer: root, parents: [] @@ -325,7 +325,7 @@ class AbstractSynchronizer { removeAllCesiumObjects(destroy) {} /** - * @param {olcsx.LayerWithParents} olLayerWithParents + * @param {import('olsc/core.js').LayerWithParents} olLayerWithParents * @return {?Array.} * @abstract * @protected diff --git a/src/olcs/FeatureConverter.js b/src/olcs/FeatureConverter.js index 616e0e879..5276d19f5 100644 --- a/src/olcs/FeatureConverter.js +++ b/src/olcs/FeatureConverter.js @@ -12,6 +12,14 @@ import olcsCore from './core.js'; import olcsCoreVectorLayerCounterpart from './core/VectorLayerCounterpart.js'; import olcsUtil, {getUid, isGroundPolylinePrimitiveSupported} from './util.js'; + +/** + * @typedef {Object} ModelStyle + * @property {Cesium.Matrix4} [debugModelMatrix] + * @property {Cesium.ModelFromGltfOptions} cesiumOptions + */ + + class FeatureConverter { /** * Concrete base class for converting from OpenLayers3 vectors to Cesium @@ -706,13 +714,14 @@ class FeatureConverter { color = new Cesium.Color(1.0, 1.0, 1.0, opacity); } + const scale = imageStyle.getScale(); const heightReference = this.getHeightReference(layer, feature, olGeometry); const bbOptions = /** @type {Cesium.optionsBillboardCollectionAdd} */ ({ // always update Cesium externs before adding a property image, color, - scale: imageStyle.getScale(), + scale, heightReference, position }); @@ -720,7 +729,7 @@ class FeatureConverter { if (imageStyle instanceof olStyleIcon) { const anchor = imageStyle.getAnchor(); if (anchor) { - bbOptions.pixelOffset = new Cesium.Cartesian2(image.width / 2 - anchor[0], image.height / 2 - anchor[1]); + bbOptions.pixelOffset = new Cesium.Cartesian2((image.width / 2 - anchor[0]) * scale, (image.height / 2 - anchor[1]) * scale); } } @@ -1096,7 +1105,7 @@ class FeatureConverter { * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature. * @param {!ol.style.Style} style - * @param {!olcsx.core.OlFeatureToCesiumContext} context + * @param {!import('olcs/core/VectorLayerConterpart.js').OlFeatureToCesiumContext} context * @param {!ol.geom.Geometry=} opt_geom Geometry to be converted. * @return {Cesium.Primitive} primitives * @api @@ -1256,7 +1265,7 @@ class FeatureConverter { * @param {!(ol.layer.Vector|ol.layer.Image)} layer * @param {!ol.View} view * @param {!ol.Feature} feature - * @param {!olcsx.core.OlFeatureToCesiumContext} context + * @param {!import('olcs/core/VectorLayerConterpart.js').OlFeatureToCesiumContext} context * @return {Cesium.Primitive} * @api */ @@ -1275,7 +1284,7 @@ class FeatureConverter { const styles = this.computePlainStyle(layer, feature, layerStyle, resolution); - if (!styles.length) { + if (!styles || !styles.length) { // only 'render' features with a style return null; } diff --git a/src/olcs/OLCesium.js b/src/olcs/OLCesium.js index 2a2eb2df7..fed4133b0 100644 --- a/src/olcs/OLCesium.js +++ b/src/olcs/OLCesium.js @@ -11,9 +11,26 @@ import olcsRasterSynchronizer from './RasterSynchronizer.js'; import olcsVectorSynchronizer from './VectorSynchronizer.js'; import olcsOverlaySynchronizer from './OverlaySynchronizer.js'; + +/** + * @typedef {Object} OLCesiumOptions + * @property {import('ol/Map.js').default} map The OpenLayers map we want to show on a Cesium scene. + * @property {Element|string} [target] Target element for the Cesium scene. + * @property {function(!import('ol/Map.js').default, !Cesium.Scene, !Cesium.DataSourceCollection): Array} + * [createSynchronizers] Callback function which will be called by the {@link olcs.OLCesium} + * constructor to create custom synchronizers. Receives an `ol.Map` and a `Cesium.Scene` as arguments, + * and needs to return an array of {@link import('olcs/AbstractSynchronizer.js').default}. + * @property {function(): Cesium.JulianDate} [time] Control the current time used by Cesium. + * @property {boolean} [stopOpenLayersEventsPropagation] Prevent propagation of mouse/touch events to + * OpenLayers when Cesium is active. + * @property {Cesium.SceneOptions} [sceneOptions] Allows the passing of property value to the + * `Cesium.Scene`. + */ + + class OLCesium { /** - * @param {!olcsx.OLCesiumOptions} options Options. + * @param {!OLCesiumOptions} options Options. * @constructor * @api */ @@ -87,10 +104,8 @@ class OLCesium { } targetElement.appendChild(this.container_); } else { - const oc = this.map_.getViewport().querySelector('.ol-overlaycontainer'); - if (oc && oc.parentNode) { - oc.parentNode.insertBefore(this.container_, oc); - } + const seOverlayContainer = this.map_.getViewport().querySelector('.ol-overlaycontainer-stopevent'); + seOverlayContainer.insertBefore(this.container_, seOverlayContainer.firstChild); } /** @@ -507,7 +522,6 @@ class OLCesium { } this.map_.getOverlayContainer().classList.add('olcs-hideoverlay'); - this.map_.getOverlayContainerStopEvent().classList.add('olcs-hideoverlay'); } this.camera_.readFromView(); @@ -524,7 +538,6 @@ class OLCesium { this.map_.removeInteraction = interaction => this.map_.getInteractions().remove(interaction); this.map_.getOverlayContainer().classList.remove('olcs-hideoverlay'); - this.map_.getOverlayContainerStopEvent().classList.remove('olcs-hideoverlay'); if (this.hiddenRootGroup_) { this.hiddenRootGroup_.setVisible(true); this.hiddenRootGroup_ = null; @@ -653,64 +666,65 @@ class OLCesium { throw new Error(`The OpenLayers map is not properly initialized: ${center} / ${view.getResolution()}`); } } -} + /** + * @type {ol.Feature} + */ + get trackedFeature() { + return this.trackedFeature_; + } -Object.defineProperties(OLCesium.prototype, { - 'trackedFeature': { - 'get': /** @this {olcs.OLCesium} */ function() { - return this.trackedFeature_; - }, - 'set': /** @this {olcs.OLCesium} */ function(feature) { - if (this.trackedFeature_ !== feature) { - - const scene = this.scene_; - - //Stop tracking - if (!feature || !feature.getGeometry()) { - this.needTrackedEntityUpdate_ = false; - scene.screenSpaceCameraController.enableTilt = true; - - if (this.trackedEntity_) { - this.dataSourceDisplay_.defaultDataSource.entities.remove(this.trackedEntity_); - } - this.trackedEntity_ = null; - this.trackedFeature_ = null; - this.entityView_ = null; - scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); - return; - } + /** + * @param {ol.Feature} feature + */ + set trackedFeature(feature) { + if (this.trackedFeature_ !== feature) { + + const scene = this.scene_; - this.trackedFeature_ = feature; - - //We can't start tracking immediately, so we set a flag and start tracking - //when the bounding sphere is ready (most likely next frame). - this.needTrackedEntityUpdate_ = true; - - const to4326Transform = this.to4326Transform_; - const toCesiumPosition = function() { - const geometry = feature.getGeometry(); - console.assert(geometry instanceof olGeomPoint); - const coo = geometry.getCoordinates(); - const coo4326 = to4326Transform(coo, undefined, coo.length); - return olcsCore.ol4326CoordinateToCesiumCartesian(coo4326); - }; - - // Create an invisible point entity for tracking. - // It is independant from the primitive/geometry created by the vector synchronizer. - const options = { - 'position': new Cesium.CallbackProperty((time, result) => toCesiumPosition(), false), - 'point': { - 'pixelSize': 1, - 'color': Cesium.Color.TRANSPARENT - } - }; - - this.trackedEntity_ = this.dataSourceDisplay_.defaultDataSource.entities.add(options); + //Stop tracking + if (!feature || !feature.getGeometry()) { + this.needTrackedEntityUpdate_ = false; + scene.screenSpaceCameraController.enableTilt = true; + + if (this.trackedEntity_) { + this.dataSourceDisplay_.defaultDataSource.entities.remove(this.trackedEntity_); + } + this.trackedEntity_ = null; + this.trackedFeature_ = null; + this.entityView_ = null; + scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + return; } + + this.trackedFeature_ = feature; + + //We can't start tracking immediately, so we set a flag and start tracking + //when the bounding sphere is ready (most likely next frame). + this.needTrackedEntityUpdate_ = true; + + const to4326Transform = this.to4326Transform_; + const toCesiumPosition = function() { + const geometry = feature.getGeometry(); + console.assert(geometry instanceof olGeomPoint); + const coo = geometry.getCoordinates(); + const coo4326 = to4326Transform(coo, undefined, coo.length); + return olcsCore.ol4326CoordinateToCesiumCartesian(coo4326); + }; + + // Create an invisible point entity for tracking. + // It is independant from the primitive/geometry created by the vector synchronizer. + const options = { + 'position': new Cesium.CallbackProperty((time, result) => toCesiumPosition(), false), + 'point': { + 'pixelSize': 1, + 'color': Cesium.Color.TRANSPARENT + } + }; + + this.trackedEntity_ = this.dataSourceDisplay_.defaultDataSource.entities.add(options); } } -}); - +} export default OLCesium; diff --git a/src/olcs/RasterSynchronizer.js b/src/olcs/RasterSynchronizer.js index 5a0923bf1..d5fe3ab7f 100644 --- a/src/olcs/RasterSynchronizer.js +++ b/src/olcs/RasterSynchronizer.js @@ -148,7 +148,7 @@ class RasterSynchronizer extends olcsAbstractSynchronizer { while (queue.length > 0) { const olLayer = queue.splice(0, 1)[0]; layers.push(olLayer); - zIndices[getUid(olLayer)] = olLayer.getZIndex(); + zIndices[getUid(olLayer)] = olLayer.getZIndex() || 0; if (olLayer instanceof olLayerGroup) { const sublayers = olLayer.getLayers(); diff --git a/src/olcs/SynchronizedOverlay.js b/src/olcs/SynchronizedOverlay.js index 25893de52..aef216eb4 100644 --- a/src/olcs/SynchronizedOverlay.js +++ b/src/olcs/SynchronizedOverlay.js @@ -6,6 +6,16 @@ import {transform} from 'ol/proj.js'; import {removeNode, removeChildren} from './util.js'; import {unByKey as olObservableUnByKey} from 'ol/Observable.js'; + +/** + * Options for SynchronizedOverlay + * @typedef {Object} SynchronizedOverlayOptions + * @property {!Cesium.Scene} scene + * @property {olOverlay} parent + * @property {!import('olsc/OverlaySynchronizer.js').default} synchronizer + */ + + class SynchronizedOverlay extends olOverlay { /** * @param {olcsx.SynchronizedOverlayOptions} options SynchronizedOverlay Options. diff --git a/src/olcs/VectorSynchronizer.js b/src/olcs/VectorSynchronizer.js index 198a0a19c..bdc757e03 100644 --- a/src/olcs/VectorSynchronizer.js +++ b/src/olcs/VectorSynchronizer.js @@ -7,6 +7,7 @@ import olSourceCluster from 'ol/source/Cluster.js'; import olLayerImage from 'ol/layer/Image.js'; import {olcsListen, getUid} from './util.js'; import olLayerVector from 'ol/layer/Vector.js'; +import olLayerVectorTile from 'ol/layer/VectorTile.js'; import olcsAbstractSynchronizer from './AbstractSynchronizer.js'; import olcsFeatureConverter from './FeatureConverter.js'; @@ -78,7 +79,7 @@ class VectorSynchronizer extends olcsAbstractSynchronizer { /** * Synchronizes the layer visibility properties * to the given Cesium Primitive. - * @param {olcsx.LayerWithParents} olLayerWithParents + * @param {import('olsc/core.js').LayerWithParents} olLayerWithParents * @param {!Cesium.Primitive} csPrimitive */ updateLayerVisibility(olLayerWithParents, csPrimitive) { @@ -99,7 +100,7 @@ class VectorSynchronizer extends olcsAbstractSynchronizer { */ createSingleLayerCounterparts(olLayerWithParents) { const olLayer = olLayerWithParents.layer; - if (!(olLayer instanceof olLayerVector)) { + if (!(olLayer instanceof olLayerVector) || olLayer instanceof olLayerVectorTile) { return null; } console.assert(olLayer instanceof olLayerLayer); diff --git a/src/olcs/contrib/LazyLoader.js b/src/olcs/contrib/LazyLoader.js index d6eb9d721..3db39170b 100644 --- a/src/olcs/contrib/LazyLoader.js +++ b/src/olcs/contrib/LazyLoader.js @@ -1,10 +1,9 @@ /** * @module olcs.contrib.LazyLoader */ -const exports = class { +export default class LazyLoader { /** * @param {string} url - * @struct * @api */ constructor(url) { @@ -38,7 +37,4 @@ const exports = class { } return this.promise; } -}; - - -export default exports; +} diff --git a/src/olcs/contrib/Manager.js b/src/olcs/contrib/Manager.js index 779d54da4..6e2c7950f 100644 --- a/src/olcs/contrib/Manager.js +++ b/src/olcs/contrib/Manager.js @@ -7,6 +7,14 @@ import olcsCore from '../core.js'; import {toRadians} from '../math.js'; import olObservable from 'ol/Observable.js'; + +/** + * @typedef {Object} ManagerOptions + * @property {import('ol/Map.js').default} map + * @property {import('ol/extent.js').Extent} [cameraExtentInRadians] + */ + + const Manager = class extends olObservable { /** * @param {string} cesiumUrl diff --git a/src/olcs/core.js b/src/olcs/core.js index 60c28c126..294fc2982 100644 --- a/src/olcs/core.js +++ b/src/olcs/core.js @@ -1,18 +1,45 @@ /** * @module olcs.core */ -const exports = {}; import {linear as linearEasing} from 'ol/easing.js'; import olLayerTile from 'ol/layer/Tile.js'; import olLayerImage from 'ol/layer/Image.js'; import {get as getProjection, transformExtent} from 'ol/proj.js'; -import olSourceImageStatic from 'ol/source/ImageStatic'; +import olSourceImageStatic from 'ol/source/ImageStatic.js'; import olSourceImageWMS from 'ol/source/ImageWMS.js'; import olSourceTileImage from 'ol/source/TileImage.js'; import olSourceTileWMS from 'ol/source/TileWMS.js'; import {defaultImageLoadFunction} from 'ol/source/Image.js'; import olcsCoreOLImageryProvider from './core/OLImageryProvider.js'; import olcsUtil from './util.js'; +import {ENABLE_RASTER_REPROJECTION} from 'ol/reproj/common.js'; + + +const exports = {}; + + +/** + * @typedef {Object} CesiumUrlDefinition + * @property {string} url + * @property {string} subdomains + */ + + +/** + * Options for rotate around axis core function. + * @typedef {Object} RotateAroundAxisOption + * @property {number} [duration] + * @property {function(number): number} [easing] + * @property {function(): void} [callback] + */ + + + +/** + * @typedef {Object} LayerWithParents + * @property {import('ol/layer/Base.js').default} layer + * @property {Array} parents + */ /** @@ -103,7 +130,7 @@ exports.createMatrixAtCoordinates = function(coordinates, rotation = 0, translat * @param {number} angle * @param {!Cesium.Cartesian3} axis * @param {!Cesium.Matrix4} transform - * @param {olcsx.core.RotateAroundAxisOption=} opt_options + * @param {RotateAroundAxisOption=} opt_options * @api */ exports.rotateAroundAxis = function(camera, angle, axis, transform, @@ -149,7 +176,7 @@ exports.rotateAroundAxis = function(camera, angle, axis, transform, * @param {!Cesium.Scene} scene * @param {number} heading * @param {!Cesium.Cartesian3} bottomCenter - * @param {olcsx.core.RotateAroundAxisOption=} opt_options + * @param {RotateAroundAxisOption=} opt_options * @api */ exports.setHeadingUsingBottomCenter = function(scene, heading, @@ -395,7 +422,7 @@ exports.tileLayerToImageryLayer = function(olMap, olLayer, viewProj) { projection = viewProj; } - if (exports.isCesiumProjection(projection)) { + if (exports.isCesiumProjection(projection) || ENABLE_RASTER_REPROJECTION) { provider = new olcsCoreOLImageryProvider(olMap, source, viewProj); } // Projection not supported by Cesium @@ -561,7 +588,7 @@ exports.convertColorToCesium = function(olColor) { /** * Convert an OpenLayers url to Cesium. * @param {string} url - * @return {!olcsx.core.CesiumUrlDefinition} + * @return {!CesiumUrlDefinition} * @api */ exports.convertUrlToCesium = function(url) { diff --git a/src/olcs/core/OLImageryProvider.js b/src/olcs/core/OLImageryProvider.js index 06bfa01dd..ba8286684 100644 --- a/src/olcs/core/OLImageryProvider.js +++ b/src/olcs/core/OLImageryProvider.js @@ -3,6 +3,23 @@ */ import {get as getProjection} from 'ol/proj.js'; import olcsUtil from '../util.js'; +import {ENABLE_RASTER_REPROJECTION} from 'ol/reproj/common.js'; +import olTileState from 'ol/TileState.js'; +import {listen, unlistenByKey} from 'ol/events.js'; +import {Tile as TileSource} from 'ol/source.js'; + + +const olUseNewCoordinates = (function() { + const tileSource = new TileSource({ + projection: 'EPSG:3857', + wrapX: true + }); + const tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]); + return tileCoord && tileCoord[1] === 33 && tileCoord[2] === 22; + // See b/test/spec/ol/source/tile.test.js + // of e9a30c5cb7e3721d9370025fbe5472c322847b35 in OpenLayers repository +})(); + class OLImageryProvider /* should not extend Cesium.ImageryProvider */ { /** @@ -96,6 +113,9 @@ class OLImageryProvider /* should not extend Cesium.ImageryProvider */ { this.tilingScheme_ = new Cesium.GeographicTilingScheme(); } else if (this.projection_ == getProjection('EPSG:3857')) { this.tilingScheme_ = new Cesium.WebMercatorTilingScheme(); + } else if (ENABLE_RASTER_REPROJECTION) { + this.tilingScheme_ = new Cesium.GeographicTilingScheme(); + this.projection_ = getProjection('EPSG:4326'); } else { return; } @@ -138,24 +158,52 @@ class OLImageryProvider /* should not extend Cesium.ImageryProvider */ { * @override */ requestImage(x, y, level) { - const tileUrlFunction = this.source_.getTileUrlFunction(); - if (tileUrlFunction && this.projection_) { - - // Perform mapping of Cesium tile coordinates to OpenLayers tile coordinates: - // 1) Cesium zoom level 0 is OpenLayers zoom level 1 for EPSG:4326 - const z_ = this.tilingScheme_ instanceof Cesium.GeographicTilingScheme ? level + 1 : level; - // 2) OpenLayers tile coordinates increase from bottom to top - const y_ = -y - 1; - - let url = tileUrlFunction.call(this.source_, - [z_, x, y_], 1, this.projection_); - if (this.proxy_) { - url = this.proxy_.getURL(url); - } - return url ? Cesium.ImageryProvider.loadImage(this, url) : this.emptyCanvas_; + // Perform mapping of Cesium tile coordinates to ol3 tile coordinates: + // 1) Cesium zoom level 0 is OpenLayers zoom level 1 for EPSG:4326 + const z_ = this.tilingScheme_ instanceof Cesium.GeographicTilingScheme ? level + 1 : level; + // 2) OpenLayers tile coordinates increase from bottom to top + + let y_ = y; + if (!olUseNewCoordinates) { + // OpenLayers version 3 to 5 tile coordinates increase from bottom to top + y_ = -y - 1; + } + + const tilegrid = this.source_.getTileGridForProjection(this.projection_); + if (z_ < tilegrid.getMinZoom() || z_ > tilegrid.getMaxZoom()) { + return Promise.resolve(this.emptyCanvas_); // no data + } + + const tile = this.source_.getTile(z_, x, y_, 1, this.projection_); + + tile.load(); + + // not yet loaded! + // const image = tile.getImage(); + // if (!image || !image.src) { + // return this.emptyCanvas_; // no data + // } + + + const state = tile.getState(); + if (state === olTileState.LOADED || state === olTileState.EMPTY) { + return Promise.resolve(tile.getImage()) || undefined; + } else if (state === olTileState.ERROR) { + return undefined; // let Cesium continue retrieving later } else { - // return empty canvas to stop Cesium from retrying later - return this.emptyCanvas_; + const promise = new Promise((resolve, reject) => { + const unlisten = listen(tile, 'change', (evt) => { + const state = tile.getState(); + if (state === olTileState.LOADED || state === olTileState.EMPTY) { + resolve(tile.getImage() || undefined); + unlistenByKey(unlisten); + } else if (state === olTileState.ERROR) { + resolve(undefined); // let Cesium continue retrieving later + unlistenByKey(unlisten); + } + }); + }); + return promise; } } } @@ -165,54 +213,54 @@ class OLImageryProvider /* should not extend Cesium.ImageryProvider */ { Object.defineProperties(OLImageryProvider.prototype, { 'ready': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() {return this.ready_;} + function() {return this.ready_;} }, 'rectangle': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() {return this.rectangle_;} + function() {return this.rectangle_;} }, 'tileWidth': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() { - const tg = this.source_.getTileGrid(); - return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[0] : tg.getTileSize(0)) : 256; - } + function() { + const tg = this.source_.getTileGrid(); + return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[0] : tg.getTileSize(0)) : 256; + } }, 'tileHeight': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() { - const tg = this.source_.getTileGrid(); - return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[1] : tg.getTileSize(0)) : 256; - } + function() { + const tg = this.source_.getTileGrid(); + return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[1] : tg.getTileSize(0)) : 256; + } }, 'maximumLevel': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() { - const tg = this.source_.getTileGrid(); - return tg ? tg.getMaxZoom() : 18; - } + function() { + const tg = this.source_.getTileGrid(); + return tg ? tg.getMaxZoom() : 18; + } }, 'minimumLevel': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() { - // WARNING: Do not use the minimum level (at least until the extent is - // properly set). Cesium assumes the minimumLevel to contain only - // a few tiles and tries to load them all at once -- this can - // freeze and/or crash the browser ! - return 0; - //var tg = this.source_.getTileGrid(); - //return tg ? tg.getMinZoom() : 0; - } + function() { + // WARNING: Do not use the minimum level (at least until the extent is + // properly set). Cesium assumes the minimumLevel to contain only + // a few tiles and tries to load them all at once -- this can + // freeze and/or crash the browser ! + return 0; + //var tg = this.source_.getTileGrid(); + //return tg ? tg.getMinZoom() : 0; + } }, 'tilingScheme': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() {return this.tilingScheme_;} + function() {return this.tilingScheme_;} }, 'tileDiscardPolicy': { @@ -221,12 +269,12 @@ Object.defineProperties(OLImageryProvider.prototype, { 'errorEvent': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() {return this.errorEvent_;} + function() {return this.errorEvent_;} }, 'proxy': { 'get': /** @this {olcs.core.OLImageryProvider} */ - function() {return this.proxy_;} + function() {return this.proxy_;} }, 'hasAlphaChannel': { diff --git a/src/olcs/core/VectorLayerCounterpart.js b/src/olcs/core/VectorLayerCounterpart.js index 20cd4c7a8..4892f3d23 100644 --- a/src/olcs/core/VectorLayerCounterpart.js +++ b/src/olcs/core/VectorLayerCounterpart.js @@ -3,6 +3,17 @@ */ import {unByKey as olObservableUnByKey} from 'ol/Observable.js'; + +/** + * Context for feature conversion. + * @typedef {Object} OlFeatureToCesiumContext + * @property {!(import('ol/Projection.js').default|string)} projection + * @property {!Cesium.PrimitiveCollection} primitives + * @property {Object>} featureToCesiumMap + * @property {!Cesium.BillboardCollection} billboards + */ + + class VectorLayerCounterpart { /** * Result of the conversion of an OpenLayers layer to Cesium. @@ -20,7 +31,7 @@ class VectorLayerCounterpart { this.rootCollection_ = new Cesium.PrimitiveCollection(); /** - * @type {!olcsx.core.OlFeatureToCesiumContext} + * @type {!OlFeatureToCesiumContext} */ this.context = { projection: layerProjection, diff --git a/src/olcs/olcs.css b/src/olcs/olcs.css index 9720e3592..ee846d462 100644 --- a/src/olcs/olcs.css +++ b/src/olcs/olcs.css @@ -1,3 +1,3 @@ -.olcs-hideoverlay .ol-overlay-container { +.olcs-hideoverlay { visibility:hidden; } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..2898fa328 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "ES6", + "module": "system", + "lib": ["es2017", "dom"], + "allowJs": true, + // "checkJs": true, + "noEmit": true, + // "strict": true, + "baseUrl": "./", + "paths": { + "ol/*": ["node_modules/ol/*"], + } + }, + "include": [ + "src/**/*.js", + ] +}