Compare commits

..

3 Commits

Author SHA1 Message Date
Olivier Guyot
2ad39cf69e Added missing Type component 2019-09-24 10:50:52 +02:00
Olivier Guyot
6929cb3001 Store typedef on the helper and use it to show a parameter list 2019-09-24 10:47:06 +02:00
Tim Schaub
5ee3063d01 Gatsby setup for API docs 2019-05-20 10:30:44 -06:00
94 changed files with 21796 additions and 627 deletions

View File

@@ -50,3 +50,11 @@ jobs:
- store_artifacts:
path: build/apidoc
destination: apidoc
- run:
name: Build Website
command: npm run build-site
- store_artifacts:
path: public
destination: website

8
.github/FUNDING.yml vendored
View File

@@ -1,8 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: openlayers
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL

17
.github/stale.yml vendored
View File

@@ -1,17 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- blocker
- regression
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

2
.gitignore vendored
View File

@@ -2,3 +2,5 @@
/coverage/
/dist/
node_modules/
/.cache/
/public/

View File

@@ -0,0 +1,23 @@
{
"opts": {
"recurse": true,
"template": "node_modules/jsdoc-json"
},
"tags": {
"allowUnknownTags": true
},
"source": {
"includePattern": "\\.js$",
"include": [
"src/ol"
]
},
"plugins": [
"jsdoc-plugin-typescript",
"config/jsdoc/api-info/plugins/api",
"config/jsdoc/api-info/plugins/module"
],
"typescript": {
"moduleRoot": "src"
}
}

View File

@@ -0,0 +1,15 @@
/**
* Handle the api annotation.
* @param {Object} dictionary The tag dictionary.
*/
exports.defineTags = dictionary => {
dictionary.defineTag('api', {
onTagged: (doclet, tag) => {
doclet.api = true;
}
});
};

View File

@@ -0,0 +1,170 @@
/**
* This plugin adds an `exportMap` property to @module doclets. Each export map
* is an object with properties named like the local identifier and values named
* like the exported identifier.
*
* For example, the code below
*
* export {foo as bar};
*
* would be a map like `{foo: 'bar'}`.
*
* In the case of an export declaration with a source, the export identifier is
* prefixed by the source. For example, this code
*
* export {foo as bar} from 'ol/bam';
*
* would be a map like `{'ol/bam foo': 'bar'}`.
*
* If a default export is a literal or object expression, the local name will be
* an empty string. For example
*
* export default {foo: 'bar'};
*
* would be a map like `{'': 'default'}`.
*/
const assert = require('assert');
const path = require('path');
/**
* A lookup of export maps per source filepath.
*/
const exportMapLookup = {};
function loc(filepath, node) {
return `${filepath}:${node.loc.start.line}`;
}
function nameFromChildIdentifier(filepath, node) {
assert.ok(node.id, `expected identifer in ${loc(filepath, node)}`);
assert.strictEqual(node.id.type, 'Identifier', `expected identifer in ${loc(filepath, node)}`);
return node.id.name;
}
function handleExportNamedDeclaration(filepath, node) {
if (!(filepath in exportMapLookup)) {
exportMapLookup[filepath] = {};
}
const exportMap = exportMapLookup[filepath];
const declaration = node.declaration;
if (declaration) {
// `export class Foo{}` or `export function foo() {}`
if (declaration.type === 'ClassDeclaration' || declaration.type === 'FunctionDeclaration') {
const name = nameFromChildIdentifier(filepath, declaration);
exportMap[name] = name;
return;
}
// `export const foo = 'bar', bam = 42`
if (declaration.type === 'VariableDeclaration') {
const declarations = declaration.declarations;
assert.ok(declarations.length > 0, `expected variable declarations in ${loc(filepath, declaration)}`);
for (const declarator of declarations) {
assert.strictEqual(declarator.type, 'VariableDeclarator', `unexpected "${declarator.type}" in ${loc(filepath, declarator)}`);
const name = nameFromChildIdentifier(filepath, declarator);
exportMap[name] = name;
}
return;
}
throw new Error(`Unexpected named export "${declaration.type}" in ${loc(filepath, declaration)}`);
}
let prefix = '';
const source = node.source;
if (source) {
// `export foo from 'bar'`
assert.strictEqual(source.type, 'Literal', `unexpected export source "${source.type}" in ${loc(filepath, source)}`);
prefix = `${source.value} `;
}
const specifiers = node.specifiers;
assert.ok(specifiers.length > 0, `expected export specifiers in ${loc(filepath, node)}`);
// `export {foo, bar}` or `export {default as Foo} from 'bar'`
for (const specifier of specifiers) {
assert.strictEqual(specifier.type, 'ExportSpecifier', `unexpected export specifier in ${loc(filepath, specifier)}`);
const local = specifier.local;
assert.strictEqual(local.type, 'Identifier', `unexpected local specifier "${local.type} in ${loc(filepath, local)}`);
const exported = specifier.exported;
assert.strictEqual(local.type, 'Identifier', `unexpected exported specifier "${exported.type} in ${loc(filepath, exported)}`);
exportMap[prefix + local.name] = exported.name;
}
}
function handleDefaultDeclaration(filepath, node) {
if (!(filepath in exportMapLookup)) {
exportMapLookup[filepath] = {};
}
const exportMap = exportMapLookup[filepath];
const declaration = node.declaration;
if (declaration) {
// `export default class Foo{}` or `export default function foo () {}`
if (declaration.type === 'ClassDeclaration' || declaration.type === 'FunctionDeclaration') {
const name = nameFromChildIdentifier(filepath, declaration);
exportMap[name] = 'default';
return;
}
// `export default foo`
if (declaration.type === 'Identifier') {
exportMap[declaration.name] = 'default';
return;
}
// `export default {foo: 'bar'}` or `export default 42`
if (declaration.type === 'ObjectExpression' || declaration.type === 'Literal') {
exportMap[''] = 'default';
return;
}
}
throw new Error(`Unexpected default export "${declaration.type}" in ${loc(filepath, declaration)}`);
}
exports.astNodeVisitor = {
visitNode: (node, event, parser, filepath) => {
if (node.type === 'ExportNamedDeclaration') {
return handleExportNamedDeclaration(filepath, node);
}
if (node.type === 'ExportDefaultDeclaration') {
return handleDefaultDeclaration(filepath, node);
}
}
};
const moduleLookup = {};
exports.handlers = {
// create a lookup of @module doclets
newDoclet: event => {
const doclet = event.doclet;
if (doclet.kind === 'module') {
const filepath = path.join(doclet.meta.path, doclet.meta.filename);
assert.ok(!(filepath in moduleLookup), `duplicate @module doc in ${filepath}`);
moduleLookup[filepath] = doclet;
}
},
// assign the `exportMap` property to @module doclets
parseComplete: event => {
for (const filepath in moduleLookup) {
assert.ok(filepath in exportMapLookup, `missing ${filepath} in export map lookup`);
moduleLookup[filepath].exportMap = exportMapLookup[filepath];
}
// make sure there was a @module doclet for each export map
for (const filepath in exportMapLookup) {
assert.ok(filepath in moduleLookup, `missing @module doclet in ${filepath}`);
}
}
};

View File

@@ -5,7 +5,6 @@ import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
/** @type {VectorSource<import("../src/ol/geom/SimpleGeometry.js").default>} */
const source = new VectorSource({
url: 'data/geojson/switzerland.geojson',
format: new GeoJSON()
@@ -52,21 +51,21 @@ const zoomtoswitzerland =
document.getElementById('zoomtoswitzerland');
zoomtoswitzerland.addEventListener('click', function() {
const feature = source.getFeatures()[0];
const polygon = feature.getGeometry();
const polygon = /** @type {import("../src/ol/geom/SimpleGeometry.js").default} */ (feature.getGeometry());
view.fit(polygon, {padding: [170, 50, 30, 150]});
}, false);
const zoomtolausanne = document.getElementById('zoomtolausanne');
zoomtolausanne.addEventListener('click', function() {
const feature = source.getFeatures()[1];
const point = feature.getGeometry();
const point = /** @type {import("../src/ol/geom/SimpleGeometry.js").default} */ (feature.getGeometry());
view.fit(point, {padding: [170, 50, 30, 150], minResolution: 50});
}, false);
const centerlausanne = document.getElementById('centerlausanne');
centerlausanne.addEventListener('click', function() {
const feature = source.getFeatures()[1];
const point = feature.getGeometry();
const point = /** @type {import("../src/ol/geom/Point.js").default} */ (feature.getGeometry());
const size = map.getSize();
view.centerOn(point.getCoordinates(), size, [570, 500]);
}, false);

2
examples/d3.js vendored
View File

@@ -2,7 +2,7 @@ import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {getWidth, getCenter} from '../src/ol/extent.js';
import {Layer, Tile as TileLayer} from '../src/ol/layer.js';
import SourceState from '../src/ol/source/State.js';
import SourceState from '../src/ol/source/State';
import {fromLonLat, toLonLat} from '../src/ol/proj.js';
import Stamen from '../src/ol/source/Stamen.js';

View File

@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import ZoomSlider from '../src/ol/control/ZoomSlider.js';
import ZoomSlider from '../src/ol/control/ZoomSlider';
const view = new View({
center: [328627.563458, 5921296.662223],

View File

@@ -67,10 +67,10 @@ const routeFeature = new Feature({
type: 'route',
geometry: route
});
const geoMarker = /** @type Feature<import("../src/ol/geom/Point").default> */(new Feature({
const geoMarker = new Feature({
type: 'geoMarker',
geometry: new Point(routeCoords[0])
}));
});
const startMarker = new Feature({
type: 'icon',
geometry: new Point(routeCoords[0])
@@ -191,7 +191,7 @@ function stopAnimation(ended) {
// if animation cancelled set the marker at the beginning
const coord = ended ? routeCoords[routeLength - 1] : routeCoords[0];
const geometry = geoMarker.getGeometry();
const geometry = /** @type {import("../src/ol/geom/Point").default} */ (geoMarker.getGeometry());
geometry.setCoordinates(coord);
//remove listener
vectorLayer.un('postrender', moveFeature);

View File

@@ -1,14 +1,14 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import TileLayer from '../src/ol/layer/Tile.js';
import Feature from '../src/ol/Feature.js';
import Point from '../src/ol/geom/Point.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import {Vector} from '../src/ol/source.js';
import {fromLonLat} from '../src/ol/proj.js';
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer.js';
import {clamp, lerp} from '../src/ol/math.js';
import Stamen from '../src/ol/source/Stamen.js';
import Feature from '../src/ol/Feature';
import Point from '../src/ol/geom/Point';
import VectorLayer from '../src/ol/layer/Vector';
import {Vector} from '../src/ol/source';
import {fromLonLat} from '../src/ol/proj';
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer';
import {clamp, lerp} from '../src/ol/math';
import Stamen from '../src/ol/source/Stamen';
const vectorSource = new Vector({
attributions: 'NASA'

View File

@@ -1,14 +1,14 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import TileLayer from '../src/ol/layer/Tile.js';
import TileJSON from '../src/ol/source/TileJSON.js';
import Feature from '../src/ol/Feature.js';
import Point from '../src/ol/geom/Point.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import {Vector} from '../src/ol/source.js';
import {fromLonLat} from '../src/ol/proj.js';
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer.js';
import {lerp} from '../src/ol/math.js';
import TileJSON from '../src/ol/source/TileJSON';
import Feature from '../src/ol/Feature';
import Point from '../src/ol/geom/Point';
import VectorLayer from '../src/ol/layer/Vector';
import {Vector} from '../src/ol/source';
import {fromLonLat} from '../src/ol/proj';
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer';
import {lerp} from '../src/ol/math';
const vectorSource = new Vector({
features: [],

View File

@@ -1,7 +1,7 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import Layer from '../src/ol/layer/Layer.js';
import {toLonLat, fromLonLat} from '../src/ol/proj.js';
import Layer from '../src/ol/layer/Layer';
import {toLonLat, fromLonLat} from '../src/ol/proj';
import {Stroke, Style} from '../src/ol/style.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';

View File

@@ -2,7 +2,14 @@ const build = require('../../tasks/serialize-workers').build;
function loader() {
const callback = this.async();
const minify = this.mode === 'production';
let minify = false;
// TODO: remove when https://github.com/webpack/webpack/issues/6496 is addressed
const compilation = this._compilation;
if (compilation) {
minify = compilation.compiler.options.mode === 'production';
}
build(this.resource, {minify})
.then(chunk => {

View File

@@ -4,7 +4,7 @@ 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';
import {create as createVersionWorker} from '../src/ol/worker/version.js';
import {create as createVersionWorker} from '../src/ol/worker/version';
const map = new Map({

11
gatsby-config.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = {
plugins: [
'gatsby-plugin-emotion',
{
resolve: 'gatsby-plugin-typography',
options: {
pathToConfigModule: 'site/util/typography'
}
}
]
};

23
gatsby-node.js Normal file
View File

@@ -0,0 +1,23 @@
function getDocs() {
// TODO: build if not present
const info = require('./build/api-info.json');
return info.docs.filter(doc => !doc.ignore && (doc.api || doc.kind === 'module' || doc.kind === 'typedef'));
}
function createPages({actions: {createPage}}) {
createPage({
path: '/api',
component: require.resolve('./site/pages/API.js'),
context: {docs: getDocs()}
});
createPage({
path: '/info',
component: require.resolve('./site/pages/Info.js'),
context: {docs: getDocs()}
});
}
exports.createPages = createPages;

20668
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ol",
"version": "6.0.0-beta.9",
"version": "6.0.0-beta.8",
"description": "OpenLayers mapping library",
"keywords": [
"map",
@@ -24,7 +24,10 @@
"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",
"typecheck": "tsc --pretty",
"apidoc": "jsdoc -R config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
"apidoc": "jsdoc -R config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc",
"api-info": "jsdoc --configure config/jsdoc/api-info/conf.json --destination build/api-info.json",
"serve-site": "gatsby develop",
"build-site": "npm run api-info && gatsby build"
},
"main": "index.js",
"repository": {
@@ -43,6 +46,8 @@
"devDependencies": {
"@babel/core": "^7.4.0",
"@babel/preset-env": "^7.4.4",
"@emotion/core": "^10.0.10",
"@emotion/styled": "^10.0.11",
"@openlayers/eslint-plugin": "^4.0.0-beta.2",
"@types/arcgis-rest-api": "^10.4.4",
"@types/geojson": "^7946.0.7",
@@ -56,10 +61,15 @@
"copy-webpack-plugin": "^5.0.3",
"coveralls": "3.0.3",
"eslint": "^5.16.0",
"eslint-config-openlayers": "^12.0.0",
"eslint-config-openlayers": "^11.0.0",
"eslint-config-tschaub": "^13.1.0",
"eslint-plugin-react": "^7.13.0",
"expect.js": "0.3.1",
"front-matter": "^3.0.2",
"fs-extra": "^8.0.0",
"gatsby": "^2.4.3",
"gatsby-plugin-emotion": "^4.0.6",
"gatsby-plugin-typography": "^2.2.13",
"glob": "^7.1.4",
"globby": "^9.2.0",
"handlebars": "4.1.2",
@@ -68,6 +78,7 @@
"istanbul-instrumenter-loader": "^3.0.1",
"jquery": "3.4.1",
"jsdoc": "3.6.2",
"jsdoc-json": "^2.0.2",
"jsdoc-plugin-typescript": "^2.0.1",
"karma": "^4.1.0",
"karma-chrome-launcher": "2.2.0",
@@ -84,20 +95,28 @@
"pixelmatch": "^4.0.2",
"pngjs": "^3.4.0",
"proj4": "2.5.0",
"puppeteer": "~1.17.0",
"prop-types": "^15.7.2",
"puppeteer": "~1.16.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-markdown": "^4.0.8",
"react-syntax-highlighter": "^10.2.1",
"react-typography": "^0.16.19",
"rollup": "^1.12.0",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-commonjs": "^10.0.0",
"rollup-plugin-node-resolve": "^5.0.0",
"rollup-plugin-terser": "^5.0.0",
"rollup-plugin-terser": "^4.0.4",
"serve-static": "^1.14.0",
"shx": "^0.3.2",
"sinon": "^7.3.2",
"terser-webpack-plugin": "^1.2.3",
"typescript": "^3.4.5",
"typography": "^0.16.19",
"typography-theme-alton": "^0.16.19",
"url-polyfill": "^1.1.5",
"walk": "^2.3.9",
"webpack": "4.32.2",
"webpack": "4.31.0",
"webpack-cli": "^3.3.2",
"webpack-dev-middleware": "^3.6.2",
"webpack-dev-server": "^3.3.1",

View File

@@ -1,10 +1,10 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {Heatmap as HeatmapLayer} from '../../../src/ol/layer.js';
import VectorSource from '../../../src/ol/source/Vector.js';
import KML from '../../../src/ol/format/KML.js';
import XYZ from '../../../src/ol/source/XYZ';
import {Heatmap as HeatmapLayer} from '../../../src/ol/layer';
import VectorSource from '../../../src/ol/source/Vector';
import KML from '../../../src/ol/format/KML';
const vector = new HeatmapLayer({
source: new VectorSource({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -1,30 +0,0 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import {Group as LayerGroup, Tile as TileLayer} from '../../../src/ol/layer.js';
import XYZ from '../../../src/ol/source/XYZ.js';
new Map({
target: 'map',
view: new View({
center: [0, 0],
zoom: 3
}),
layers: new LayerGroup({
opacity: 0.75,
layers: [
new TileLayer({
opacity: 0.25,
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg'
})
}),
new TileLayer({
source: new XYZ({
url: '/data/tiles/stamen-labels/{z}/{x}/{y}.png'
})
})
]
})
});
render();

View File

@@ -5,7 +5,7 @@ import {
get as getProjection,
transform,
transformExtent
} from '../../../src/ol/proj.js';
} from '../../../src/ol/proj';
import ImageLayer from '../../../src/ol/layer/Image.js';
const center = transform([-122.416667, 37.783333], 'EPSG:4326', 'EPSG:3857');

View File

@@ -5,9 +5,9 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj.js';
import {fromLonLat} from '../../../src/ol/proj';
import {transformExtent} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import XYZ from '../../../src/ol/source/XYZ';
const center = fromLonLat([7, 50]);
const extent = transformExtent([2, 47, 10, 53], 'EPSG:4326', 'EPSG:3857');

View File

@@ -1,7 +1,7 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import XYZ from '../../../src/ol/source/XYZ';
import {createXYZ} from '../../../src/ol/tilegrid.js';
const center = [-10997148, 4569099];

View File

@@ -1,8 +1,8 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {fromLonLat} from '../../../src/ol/proj';
import XYZ from '../../../src/ol/source/XYZ';
const center = fromLonLat([8.6, 50.1]);

View File

@@ -1,8 +1,8 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {fromLonLat} from '../../../src/ol/proj';
import XYZ from '../../../src/ol/source/XYZ';
const center = fromLonLat([8.6, 50.1]);

View File

@@ -1,8 +1,8 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {fromLonLat} from '../../../src/ol/proj';
import XYZ from '../../../src/ol/source/XYZ';
const center = fromLonLat([8.6, 50.1]);

View File

@@ -1,8 +1,8 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {fromLonLat} from '../../../src/ol/proj';
import XYZ from '../../../src/ol/source/XYZ';
const center = fromLonLat([8.6, 50.1]);

View File

@@ -1,9 +1,9 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
import MVT from '../../../src/ol/format/MVT.js';
import {createXYZ} from '../../../src/ol/tilegrid.js';
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
import VectorTileSource from '../../../src/ol/source/VectorTile';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
const map = new Map({
pixelRatio: 2,

View File

@@ -1,16 +1,16 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
import MVT from '../../../src/ol/format/MVT.js';
import {createXYZ} from '../../../src/ol/tilegrid.js';
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
import VectorSource from '../../../src/ol/source/Vector.js';
import Feature from '../../../src/ol/Feature.js';
import Point from '../../../src/ol/geom/Point.js';
import VectorLayer from '../../../src/ol/layer/Vector.js';
import Style from '../../../src/ol/style/Style.js';
import CircleStyle from '../../../src/ol/style/Circle.js';
import Fill from '../../../src/ol/style/Fill.js';
import VectorTileSource from '../../../src/ol/source/VectorTile';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
import VectorSource from '../../../src/ol/source/Vector';
import Feature from '../../../src/ol/Feature';
import Point from '../../../src/ol/geom/Point';
import VectorLayer from '../../../src/ol/layer/Vector';
import Style from '../../../src/ol/style/Style';
import CircleStyle from '../../../src/ol/style/Circle';
import Fill from '../../../src/ol/style/Fill';
const vectorSource = new VectorSource({
features: [

View File

@@ -1,9 +1,9 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
import MVT from '../../../src/ol/format/MVT.js';
import {createXYZ} from '../../../src/ol/tilegrid.js';
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
import VectorTileSource from '../../../src/ol/source/VectorTile';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
const map = new Map({
layers: [

View File

@@ -1,9 +1,9 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import VectorTileSource from '../../../src/ol/source/VectorTile.js';
import MVT from '../../../src/ol/format/MVT.js';
import {createXYZ} from '../../../src/ol/tilegrid.js';
import VectorTileLayer from '../../../src/ol/layer/VectorTile.js';
import VectorTileSource from '../../../src/ol/source/VectorTile';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
new Map({
layers: [

View File

@@ -9,6 +9,12 @@ import Point from '../../../src/ol/geom/Point.js';
const map = new Map({
layers: [
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
maxZoom: 3
})
}),
new VectorLayer({
zIndex: 1,
style: new Style({
@@ -21,12 +27,6 @@ const map = new Map({
url: '/data/countries.json',
format: new GeoJSON()
})
}),
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
maxZoom: 3
})
})
],
target: 'map',

View File

@@ -1,11 +1,11 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import XYZ from '../../../src/ol/source/XYZ.js';
import {Vector as VectorLayer} from '../../../src/ol/layer.js';
import VectorSource from '../../../src/ol/source/Vector.js';
import KML from '../../../src/ol/format/KML.js';
import WebGLPointsLayerRenderer from '../../../src/ol/renderer/webgl/PointsLayer.js';
import XYZ from '../../../src/ol/source/XYZ';
import {Vector as VectorLayer} from '../../../src/ol/layer';
import VectorSource from '../../../src/ol/source/Vector';
import KML from '../../../src/ol/format/KML';
import WebGLPointsLayerRenderer from '../../../src/ol/renderer/webgl/PointsLayer';
class CustomLayer extends VectorLayer {
createRenderer() {

3
site/.eslintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "tschaub/react"
}

35
site/components/Class.jsx Normal file
View File

@@ -0,0 +1,35 @@
import {object} from 'prop-types';
import React from 'react';
import Markdown from 'react-markdown';
import Code from './Code';
import Parameter from './Parameter';
function Class({cls, module, helper}) {
const exportedName = module.getExportedName(cls.name);
let importCode;
if (exportedName === 'default') {
importCode = `import ${cls.name} from '${module.id}';`;
} else {
importCode = `import {${exportedName}} from '${module.id}';`;
}
return (
<div>
<h3>{cls.name}</h3>
<Code value={importCode} />
<Markdown source={cls.doc.classdesc} renderers={{code: Code}} />
<h6>Parameters</h6>
<ul>
{cls.doc.params && cls.doc.params.map(param => <Parameter param={param} module={module} helper={helper} />)}
</ul>
</div>
);
}
Class.propTypes = {
cls: object.isRequired,
module: object.isRequired,
helper: object.isRequired
};
export default Class;

26
site/components/Code.jsx Normal file
View File

@@ -0,0 +1,26 @@
import React, {PureComponent} from 'react';
import {string} from 'prop-types';
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter';
import {coy} from 'react-syntax-highlighter/dist/styles/prism';
class Code extends PureComponent {
render() {
let language = this.props.language;
if (!language) {
language = 'js';
}
return (
<SyntaxHighlighter language={language} style={coy}>
{this.props.value}
</SyntaxHighlighter>
);
}
}
Code.propTypes = {
value: string.isRequired,
language: string
};
export default Code;

35
site/components/Func.jsx Normal file
View File

@@ -0,0 +1,35 @@
import {object} from 'prop-types';
import React from 'react';
import Markdown from 'react-markdown';
import Code from './Code';
import Parameter from './Parameter';
function Func({func, module, helper}) {
const exportedName = module.getExportedName(func.name);
let importCode;
if (exportedName === 'default') {
importCode = `import ${func.name} from '${module.id}';`;
} else {
importCode = `import {${exportedName}} from '${module.id}';`;
}
return (
<div>
<h3>{func.name}</h3>
<Code value={importCode} />
<Markdown source={func.doc.description} renderers={{code: Code}} />
<h6>Parameters</h6>
<ul>
{func.doc.params && func.doc.params.map(param => <Parameter param={param} module={module} helper={helper} />)}
</ul>
</div>
);
}
Func.propTypes = {
func: object.isRequired,
module: object.isRequired,
helper: object.isRequired
};
export default Func;

View File

@@ -0,0 +1,26 @@
import {object} from 'prop-types';
import React from 'react';
import Class from './Class';
import Func from './Func';
function Module({module, helper}) {
return (
<div>
<hr />
<h2>{module.id}</h2>
{module.classes.map(cls => (
<Class key={cls.name} cls={cls} module={module} helper={helper} />
))}
{module.functions.map(func => (
<Func key={func.name} func={func} module={module} helper={helper} />
))}
</div>
);
}
Module.propTypes = {
module: object.isRequired,
helper: object.isRequired
};
export default Module;

View File

@@ -0,0 +1,20 @@
import {object} from 'prop-types';
import React from 'react';
import Type from './Type';
function Parameter({param, module, helper}) {
return (
<li>
<code>{param.name}</code> - {param.description} {param.optional && <span>(optional)</span>}<br/>
{param.type.names.map(longName => <Type longName={longName} module={module} helper={helper} />)}
</li>
);
}
Parameter.propTypes = {
param: object.isRequired,
module: object.isRequired,
helper: object.isRequired
};
export default Parameter;

27
site/components/Type.jsx Normal file
View File

@@ -0,0 +1,27 @@
import {object} from 'prop-types';
import React from 'react';
import Parameter from './Parameter';
function Type({longName, module, helper}) {
const type = helper.getTypeDef(longName);
if (!type) {
return <code>{longName}</code>;
}
return (
<div>
<code>{type.doc.type.names}</code>
<ul>
{type.doc.properties && type.doc.properties.map(prop => <Parameter param={prop} module={module} helper={helper} />)}
</ul>
</div>
);
}
Type.propTypes = {
longName: object.isRequired,
module: object.isRequired,
helper: object.isRequired
};
export default Type;

View File

@@ -0,0 +1,8 @@
import styled from '@emotion/styled';
import {baseSpacingPx} from '../util/typography';
export const Page = styled.div({
display: 'flex',
flexDirection: 'column',
margin: 2 * baseSpacingPx
});

26
site/pages/API.js Normal file
View File

@@ -0,0 +1,26 @@
import {object} from 'prop-types';
import React from 'react';
import {Page} from '../components/layout';
import Module from '../components/Module';
import {getHelper} from '../util/api';
function API({pageContext: {docs}}) {
const helper = getHelper(docs);
return (
<Page>
<h1>API</h1>
{helper.modules
.filter(module => module.visible)
.map(module => (
<Module key={module.id} module={module} helper={helper} />
))}
</Page>
);
}
API.propTypes = {
pageContext: object.isRequired
};
export default API;

33
site/pages/Info.js Normal file
View File

@@ -0,0 +1,33 @@
import {object} from 'prop-types';
import React from 'react';
import {Page} from '../components/layout';
function Info({pageContext: {docs}}) {
return (
<Page>
<h1>API</h1>
<table>
<tbody>
<tr>
<th>kind</th>
<th>longname</th>
<th>memberof</th>
</tr>
{docs.map(doc => (
<tr key={doc.longname}>
<td>{doc.kind}</td>
<td>{doc.longname}</td>
<td>{doc.memberof}</td>
</tr>
))}
</tbody>
</table>
</Page>
);
}
Info.propTypes = {
pageContext: object.isRequired
};
export default Info;

205
site/util/api.js Normal file
View File

@@ -0,0 +1,205 @@
class FunctionDoc {
constructor(doc) {
this.name = doc.name;
this.doc = doc;
}
}
class TypedefDoc {
constructor(doc) {
this.name = doc.name;
this.doc = doc;
}
}
class ClassDoc {
constructor(name) {
this.name = name;
}
processDoc(doc) {
if (doc.kind === 'class') {
this.doc = doc;
}
}
}
class ModuleDoc {
constructor(id) {
this.id = id;
this.classLookup = {};
this.classes = [];
this.functionLookup = {};
this.functions = [];
}
processDoc(doc) {
if (doc.kind === 'module') {
this.doc = doc;
//console.log('processing module: ' + doc.longname)
return;
}
if (doc.kind === 'class') {
const name = nameFromLongname(doc.longname);
if (!(name in this.classLookup)) {
const cls = new ClassDoc(name);
this.classLookup[name] = cls;
this.classes.push(cls);
}
this.classLookup[name].processDoc(doc);
return;
}
if (doc.kind === 'function') {
if (nameFromLongname(doc.memberof)) {
// belongs to a class or other
return;
}
if (doc.name in this.functionLookup) {
throw new Error(`Duplicate function ${doc.name} in ${this.id}`);
}
const func = new FunctionDoc(doc);
this.functionLookup[doc.name] = func;
this.functions.push(func);
return;
}
}
finalize() {
this.classes.sort(byName);
this.functions.sort(byName);
this.visible = this.classes.length > 0 || this.functions.length > 0;
}
getExportedName(localName) {
if (!this.doc || !this.doc.exportMap) {
throw new Error(`Expected to find export map in module doc: ${this.id}`);
}
if (!(localName in this.doc.exportMap)) {
throw new Error(
`No local name "${localName}" in export map for module: ${this.id}`
);
}
return this.doc.exportMap[localName];
}
}
const longnameRE = /^module:(?<module>.*?)([~\.](?<name>\w+)(#(?<member>\w+))?(:(?<type>\w+))?)?$/;
function moduleIDFromLongname(longname) {
const match = longname.match(longnameRE);
if (!match) {
throw new Error(`could not match module id in longname: ${longname}`);
}
return match.groups.module;
}
export function nameFromLongname(longname) {
const match = longname.match(longnameRE);
if (!match) {
throw new Error(`could not match name in longname: ${longname}`);
}
return match.groups.name;
}
function memberFromLongname(longname) {
const match = longname.match(longnameRE);
if (!match) {
throw new Error(`could not match member in longname: ${longname}`);
}
return match.groups.member;
}
function byName(a, b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
}
function byModuleId(a, b) {
const aParts = a.id.split('/');
const bParts = b.id.split('/');
const len = Math.max(aParts.length, bParts.length);
for (let i = 0; i < len; ++i) {
if (aParts[i] && bParts[i]) {
if (aParts[i] < bParts[i]) {
return -1;
}
if (aParts[i] > bParts[i]) {
return 1;
}
} else if (!aParts[i]) {
return -1;
} else {
return 1;
}
}
return 0;
}
class DocHelper {
constructor(docs) {
this.moduleLookup = {};
this.modules = [];
this.typedefLookup = {};
docs.forEach(doc => {
// typedef are indexed by long name
if (doc.kind === 'typedef') {
if (doc.name in this.typedefLookup) {
throw new Error(`Duplicate type definition ${doc.name} in ${this.id}`);
}
const type = new TypedefDoc(doc);
this.typedefLookup[doc.longname] = type;
return;
}
const moduleID = moduleIDFromLongname(doc.longname);
if (!(moduleID in this.moduleLookup)) {
const module = new ModuleDoc(moduleID);
this.moduleLookup[moduleID] = module;
this.modules.push(module);
}
const module = this.moduleLookup[moduleID];
module.processDoc(doc);
});
this.modules.sort(byModuleId);
this.modules.forEach(module => module.finalize());
}
getTypeDef(longName) {
this.typedefLookup[longName] && console.log(this.typedefLookup[longName]);
return this.typedefLookup[longName];
}
}
let cachedDocs;
let cachedHelper;
export function getHelper(docs) {
if (docs !== cachedDocs) {
if (cachedDocs) {
console.warn('creating new doc helper'); // eslint-disable-line
}
cachedHelper = new DocHelper(docs);
cachedDocs = docs;
}
return cachedHelper;
}

9
site/util/typography.js Normal file
View File

@@ -0,0 +1,9 @@
import Typography from 'typography';
import theme from 'typography-theme-alton';
const typography = new Typography(theme);
export const baseSpacingPx = parseInt(theme.baseFontSize, 10);
export {theme};
export default typography;

View File

@@ -57,11 +57,10 @@ import BaseObject, {getChangeEventType} from './Object.js';
* ```
*
* @api
* @template {import("./geom/Geometry.js").default} Geometry
*/
class Feature extends BaseObject {
/**
* @param {Geometry|Object<string, *>=} opt_geometryOrProperties
* @param {import("./geom/Geometry.js").default|Object<string, *>=} opt_geometryOrProperties
* You may pass a Geometry object directly, or an object literal containing
* properties. If you pass an object literal, you may include a Geometry
* associated with a `geometry` key.
@@ -107,7 +106,7 @@ class Feature extends BaseObject {
if (opt_geometryOrProperties) {
if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') {
const geometry = /** @type {Geometry} */ (opt_geometryOrProperties);
const geometry = /** @type {import("./geom/Geometry.js").default} */ (opt_geometryOrProperties);
this.setGeometry(geometry);
} else {
/** @type {Object<string, *>} */
@@ -141,13 +140,13 @@ class Feature extends BaseObject {
* Get the feature's default geometry. A feature may have any number of named
* geometries. The "default" geometry (the one that is rendered by default) is
* set when calling {@link module:ol/Feature~Feature#setGeometry}.
* @return {Geometry|undefined} The default geometry for the feature.
* @return {import("./geom/Geometry.js").default|undefined} The default geometry for the feature.
* @api
* @observable
*/
getGeometry() {
return (
/** @type {Geometry|undefined} */ (this.get(this.geometryName_))
/** @type {import("./geom/Geometry.js").default|undefined} */ (this.get(this.geometryName_))
);
}
@@ -219,7 +218,7 @@ class Feature extends BaseObject {
/**
* Set the default geometry for the feature. This will update the property
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
* @param {Geometry|undefined} geometry The new geometry.
* @param {import("./geom/Geometry.js").default|undefined} geometry The new geometry.
* @api
* @observable
*/

View File

@@ -39,11 +39,10 @@ import {create as createTransform, apply as applyTransform} from './transform.js
* @property {boolean} animate
* @property {import("./transform.js").Transform} coordinateToPixelTransform
* @property {null|import("./extent.js").Extent} extent
* @property {Array<DeclutterItems>} declutterItems
* @property {Array<*>} declutterItems
* @property {import("./coordinate.js").Coordinate} focus
* @property {number} index
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray
* @property {number} layerIndex
* @property {import("./transform.js").Transform} pixelToCoordinateTransform
* @property {Array<PostRenderFunction>} postRenderFunctions
* @property {import("./size.js").Size} size
@@ -55,13 +54,6 @@ import {create as createTransform, apply as applyTransform} from './transform.js
*/
/**
* @typedef {Object} DeclutterItems
* @property {Array<*>} items Declutter items of an executor.
* @property {number} opacity Layer opacity.
*/
/**
* @typedef {function(PluggableMap, ?FrameState): any} PostRenderFunction
*/
@@ -1058,7 +1050,7 @@ class PluggableMap extends BaseObject {
if (!this.handleResize_) {
this.handleResize_ = this.updateSize.bind(this);
window.addEventListener(EventType.RESIZE, this.handleResize_, false);
addEventListener(EventType.RESIZE, this.handleResize_, false);
}
}
@@ -1232,14 +1224,13 @@ class PluggableMap extends BaseObject {
if (size !== undefined && hasArea(size) && view && view.isDef()) {
const viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined);
viewState = view.getState(this.pixelRatio_);
frameState = {
frameState = /** @type {FrameState} */ ({
animate: false,
coordinateToPixelTransform: this.coordinateToPixelTransform_,
declutterItems: previousFrameState ? previousFrameState.declutterItems : [],
extent: extent,
focus: this.focus_ ? this.focus_ : viewState.center,
index: this.frameIndex_++,
layerIndex: 0,
layerStatesArray: this.getLayerGroup().getLayerStatesArray(),
pixelRatio: this.pixelRatio_,
pixelToCoordinateTransform: this.pixelToCoordinateTransform_,
@@ -1252,7 +1243,7 @@ class PluggableMap extends BaseObject {
viewState: viewState,
viewHints: viewHints,
wantedTiles: {}
};
});
}
if (frameState) {

View File

@@ -21,9 +21,9 @@ import {clamp, modulo} from './math.js';
import {assign} from './obj.js';
import {createProjection, METERS_PER_UNIT} from './proj.js';
import Units from './proj/Units.js';
import {equals} from './coordinate.js';
import {easeOut} from './easing.js';
import {createMinMaxResolution} from './resolutionconstraint.js';
import {equals} from './coordinate';
import {easeOut} from './easing';
import {createMinMaxResolution} from './resolutionconstraint';
/**

View File

@@ -174,8 +174,9 @@ class Geometry extends BaseObject {
/**
* Create a simplified version of this geometry. For linestrings, this uses
* the [Douglas Peucker](https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm)
* algorithm. For polygons, a quantization-based
* the the {@link
* https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
* Douglas Peucker} algorithm. For polygons, a quantization-based
* simplification is used to preserve topology.
* @param {number} tolerance The tolerance distance for simplification.
* @return {Geometry} A new, simplified version of the original geometry.

View File

@@ -3,7 +3,7 @@
*/
import {scale as scaleCoordinate, rotate as rotateCoordinate} from '../coordinate.js';
import {easeOut} from '../easing.js';
import {noModifierKeys, primaryAction} from '../events/condition.js';
import {noModifierKeys} from '../events/condition.js';
import {FALSE} from '../functions.js';
import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js';
@@ -12,7 +12,7 @@ import PointerInteraction, {centroid as centroidFromPointers} from './Pointer.js
* @typedef {Object} Options
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
* to indicate whether that event should be handled.
* Default is {@link module:ol/events/condition~noModifierKeys} and {@link module:ol/events/condition~primaryAction}.
* Default is {@link module:ol/events/condition~noModifierKeys}.
* @property {import("../Kinetic.js").default} [kinetic] Kinetic inertia to apply to the pan.
*/
@@ -59,7 +59,7 @@ class DragPan extends PointerInteraction {
* @private
* @type {import("../events/condition.js").Condition}
*/
this.condition_ = options.condition ? options.condition : defaultCondition;
this.condition_ = options.condition ? options.condition : noModifierKeys;
/**
* @private
@@ -166,12 +166,4 @@ class DragPan extends PointerInteraction {
}
}
/**
* @param {ol.MapBrowserEvent} mapBrowserEvent Browser event.
* @return {boolean} Combined condition result.
*/
function defaultCondition(mapBrowserEvent) {
return noModifierKeys(mapBrowserEvent) && primaryAction(mapBrowserEvent);
}
export default DragPan;

View File

@@ -373,7 +373,7 @@ class Draw extends PointerInteraction {
/**
* Sketch point.
* @type {Feature<Point>}
* @type {Feature}
* @private
*/
this.sketchPoint_ = null;
@@ -387,7 +387,7 @@ class Draw extends PointerInteraction {
/**
* Sketch line. Used when drawing polygon.
* @type {Feature<LineString>}
* @type {Feature}
* @private
*/
this.sketchLine_ = null;
@@ -669,7 +669,7 @@ class Draw extends PointerInteraction {
this.sketchPoint_ = new Feature(new Point(coordinates));
this.updateSketchFeatures_();
} else {
const sketchPointGeom = this.sketchPoint_.getGeometry();
const sketchPointGeom = /** @type {Point} */ (this.sketchPoint_.getGeometry());
sketchPointGeom.setCoordinates(coordinates);
}
}
@@ -711,7 +711,7 @@ class Draw extends PointerInteraction {
*/
modifyDrawing_(event) {
let coordinate = event.coordinate;
const geometry = this.sketchFeature_.getGeometry();
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
let coordinates, last;
if (this.mode_ === Mode.POINT) {
last = this.sketchCoords_;
@@ -730,7 +730,7 @@ class Draw extends PointerInteraction {
last[1] = coordinate[1];
this.geometryFunction_(/** @type {!LineCoordType} */ (this.sketchCoords_), geometry);
if (this.sketchPoint_) {
const sketchPointGeom = this.sketchPoint_.getGeometry();
const sketchPointGeom = /** @type {Point} */ (this.sketchPoint_.getGeometry());
sketchPointGeom.setCoordinates(coordinate);
}
/** @type {LineString} */
@@ -740,8 +740,8 @@ class Draw extends PointerInteraction {
if (!this.sketchLine_) {
this.sketchLine_ = new Feature();
}
const ring = geometry.getLinearRing(0);
sketchLineGeom = this.sketchLine_.getGeometry();
const ring = /** @type {Polygon} */ (geometry).getLinearRing(0);
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
if (!sketchLineGeom) {
sketchLineGeom = new LineString(ring.getFlatCoordinates(), ring.getLayout());
this.sketchLine_.setGeometry(sketchLineGeom);
@@ -751,7 +751,7 @@ class Draw extends PointerInteraction {
sketchLineGeom.changed();
}
} else if (this.sketchLineCoords_) {
sketchLineGeom = this.sketchLine_.getGeometry();
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom.setCoordinates(this.sketchLineCoords_);
}
this.updateSketchFeatures_();
@@ -764,7 +764,7 @@ class Draw extends PointerInteraction {
*/
addToDrawing_(event) {
const coordinate = event.coordinate;
const geometry = this.sketchFeature_.getGeometry();
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
let done;
let coordinates;
if (this.mode_ === Mode.LINE_STRING) {
@@ -808,7 +808,7 @@ class Draw extends PointerInteraction {
if (!this.sketchFeature_) {
return;
}
const geometry = this.sketchFeature_.getGeometry();
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
let coordinates;
/** @type {LineString} */
let sketchLineGeom;
@@ -822,7 +822,7 @@ class Draw extends PointerInteraction {
} else if (this.mode_ === Mode.POLYGON) {
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
coordinates.splice(-2, 1);
sketchLineGeom = this.sketchLine_.getGeometry();
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom.setCoordinates(coordinates);
this.geometryFunction_(this.sketchCoords_, geometry);
}
@@ -846,7 +846,7 @@ class Draw extends PointerInteraction {
return;
}
let coordinates = this.sketchCoords_;
const geometry = sketchFeature.getGeometry();
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (sketchFeature.getGeometry());
if (this.mode_ === Mode.LINE_STRING) {
// remove the redundant last point
coordinates.pop();
@@ -900,12 +900,12 @@ class Draw extends PointerInteraction {
* Extend an existing geometry by adding additional points. This only works
* on features with `LineString` geometries, where the interaction will
* extend lines by adding points to the end of the coordinates array.
* @param {!Feature<LineString>} feature Feature to be extended.
* @param {!Feature} feature Feature to be extended.
* @api
*/
extend(feature) {
const geometry = feature.getGeometry();
const lineString = geometry;
const lineString = /** @type {LineString} */ (geometry);
this.sketchFeature_ = feature;
this.sketchCoords_ = lineString.getCoordinates();
const last = this.sketchCoords_[this.sketchCoords_.length - 1];

View File

@@ -126,7 +126,7 @@ class Extent extends PointerInteraction {
/**
* Feature for displaying the visible pointer
* @type {Feature<Point>}
* @type {Feature}
* @private
*/
this.vertexFeature_ = null;
@@ -265,7 +265,7 @@ class Extent extends PointerInteraction {
this.vertexFeature_ = vertexFeature;
this.vertexOverlay_.getSource().addFeature(vertexFeature);
} else {
const geometry = vertexFeature.getGeometry();
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
geometry.setCoordinates(vertex);
}
return vertexFeature;

View File

@@ -660,7 +660,7 @@ class Modify extends PointerInteraction {
this.vertexFeature_ = vertexFeature;
this.overlay_.getSource().addFeature(vertexFeature);
} else {
const geometry = vertexFeature.getGeometry();
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
geometry.setCoordinates(coordinates);
}
return vertexFeature;
@@ -785,7 +785,7 @@ class Modify extends PointerInteraction {
const vertexFeature = this.vertexFeature_;
if (vertexFeature) {
const insertVertices = [];
const geometry = vertexFeature.getGeometry();
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
const vertex = geometry.getCoordinates();
const vertexExtent = boundingExtent([vertex]);
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);

View File

@@ -83,9 +83,6 @@ class BaseLayer extends BaseObject {
}
/**
* This method is not meant to be called by layers or layer renderers because the state
* is incorrect if the layer is included in a layer group.
*
* @param {boolean=} opt_managed Layer is managed.
* @return {import("./Layer.js").State} Layer state.
*/

View File

@@ -3,27 +3,27 @@
*/
import VectorLayer from './Vector.js';
import {assign} from '../obj.js';
import {degreesToStringHDMS} from '../coordinate.js';
import Text from '../style/Text.js';
import Fill from '../style/Fill.js';
import Stroke from '../style/Stroke.js';
import {degreesToStringHDMS} from '../coordinate';
import Text from '../style/Text';
import Fill from '../style/Fill';
import Stroke from '../style/Stroke';
import LineString from '../geom/LineString.js';
import VectorSource from '../source/Vector.js';
import VectorSource from '../source/Vector';
import {
equivalent as equivalentProjection,
get as getProjection,
getTransform,
transformExtent
} from '../proj.js';
import {getCenter, intersects, equals, getIntersection, isEmpty} from '../extent.js';
import {clamp} from '../math.js';
import Style from '../style/Style.js';
import Feature from '../Feature.js';
import {bbox} from '../loadingstrategy.js';
import {meridian, parallel} from '../geom/flat/geodesic.js';
import GeometryLayout from '../geom/GeometryLayout.js';
import Point from '../geom/Point.js';
import Collection from '../Collection.js';
} from '../proj';
import {getCenter, intersects, equals, getIntersection, isEmpty} from '../extent';
import {clamp} from '../math';
import Style from '../style/Style';
import Feature from '../Feature';
import {bbox} from '../loadingstrategy';
import {meridian, parallel} from '../geom/flat/geodesic';
import GeometryLayout from '../geom/GeometryLayout';
import Point from '../geom/Point';
import Collection from '../Collection';
/**

View File

@@ -6,7 +6,7 @@ import {getChangeEventType} from '../Object.js';
import {createCanvasContext2D} from '../dom.js';
import VectorLayer from './Vector.js';
import {assign} from '../obj.js';
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer.js';
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer';
/**

View File

@@ -189,15 +189,13 @@ class Layer extends BaseLayer {
* In charge to manage the rendering of the layer. One layer type is
* bounded with one layer renderer.
* @param {?import("../PluggableMap.js").FrameState} frameState Frame state.
* @param {HTMLElement} target Target which the renderer may (but need not) use
* for rendering its content.
* @return {HTMLElement} The rendered element.
*/
render(frameState, target) {
render(frameState) {
const layerRenderer = this.getRenderer();
if (layerRenderer.prepareFrame(frameState)) {
return layerRenderer.renderFrame(frameState, target);
const layerState = this.getLayerState();
if (layerRenderer.prepareFrame(frameState, layerState)) {
return layerRenderer.renderFrame(frameState, layerState);
}
}

View File

@@ -122,10 +122,9 @@ export function renderDeclutterItems(frameState, declutterTree) {
}
const items = frameState.declutterItems;
for (let z = items.length - 1; z >= 0; --z) {
const item = items[z];
const zIndexItems = item.items;
const zIndexItems = items[z];
for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) {
declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], item.opacity, declutterTree);
declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], declutterTree);
}
}
items.length = 0;

View File

@@ -403,7 +403,7 @@ export function drawImage(context,
context.drawImage(image, originX, originY, w, h, x, y, w * scale, h * scale);
if (opacity != 1) {
if (alpha) {
context.globalAlpha = alpha;
}
if (transform) {

View File

@@ -362,12 +362,10 @@ class Executor extends Disposable {
const declutterArgs = intersects ?
[context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
null;
if (declutterArgs) {
if (fillStroke) {
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
}
declutterGroup.push(declutterArgs);
if (declutterArgs && fillStroke) {
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
}
declutterGroup.push(declutterArgs);
} else if (intersects) {
if (fillStroke) {
this.replayTextBackground_(context, p1, p2, p3, p4,
@@ -416,11 +414,10 @@ class Executor extends Disposable {
/**
* @param {import("../canvas.js").DeclutterGroup} declutterGroup Declutter group.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} opacity Layer opacity.
* @param {?} declutterTree Declutter tree.
* @return {?} Declutter tree.
*/
renderDeclutter(declutterGroup, feature, opacity, declutterTree) {
renderDeclutter(declutterGroup, feature, declutterTree) {
if (declutterGroup && declutterGroup.length > 5) {
const groupCount = declutterGroup[4];
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
@@ -439,19 +436,13 @@ class Executor extends Disposable {
declutterTree.insert(box);
for (let j = 5, jj = declutterGroup.length; j < jj; ++j) {
const declutterData = /** @type {Array} */ (declutterGroup[j]);
const context = declutterData[0];
const currentAlpha = context.globalAlpha;
if (currentAlpha !== opacity) {
context.globalAlpha = opacity;
}
if (declutterData.length > 11) {
this.replayTextBackground_(declutterData[0],
declutterData[13], declutterData[14], declutterData[15], declutterData[16],
declutterData[11], declutterData[12]);
}
drawImage.apply(undefined, declutterData);
if (currentAlpha !== opacity) {
context.globalAlpha = currentAlpha;
if (declutterData) {
if (declutterData.length > 11) {
this.replayTextBackground_(declutterData[0],
declutterData[13], declutterData[14], declutterData[15], declutterData[16],
declutterData[11], declutterData[12]);
}
drawImage.apply(undefined, declutterData);
}
}
}

View File

@@ -430,11 +430,10 @@ export function getCircleArray(radius) {
* @param {!Object<string, Array<*>>} declutterReplays Declutter replays.
* @param {CanvasRenderingContext2D} context Context.
* @param {number} rotation Rotation.
* @param {number} opacity Opacity.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
* @param {Array<import("../../PluggableMap.js").DeclutterItems>} declutterItems Declutter items.
* @param {Array<Array<*>>} declutterItems Declutter items.
*/
export function replayDeclutter(declutterReplays, context, rotation, opacity, snapToPixel, declutterItems) {
export function replayDeclutter(declutterReplays, context, rotation, snapToPixel, declutterItems) {
const zs = Object.keys(declutterReplays).map(Number).sort(numberSafeCompareFunction);
const skippedFeatureUids = {};
for (let z = 0, zz = zs.length; z < zz; ++z) {
@@ -444,10 +443,7 @@ export function replayDeclutter(declutterReplays, context, rotation, opacity, sn
const executor = executorData[i++];
if (executor !== currentExecutor) {
currentExecutor = executor;
declutterItems.push({
items: executor.declutterItems,
opacity: opacity
});
declutterItems.push(executor.declutterItems);
}
const transform = executorData[i++];
executor.execute(context, transform, rotation, skippedFeatureUids, snapToPixel);

View File

@@ -81,26 +81,25 @@ class CompositeMapRenderer extends MapRenderer {
this.calculateMatrices2D(frameState);
this.dispatchRenderEvent(RenderEventType.PRECOMPOSE, frameState);
const layerStatesArray = frameState.layerStatesArray.sort(function(a, b) {
return a.zIndex - b.zIndex;
});
const layerStatesArray = frameState.layerStatesArray;
const viewResolution = frameState.viewState.resolution;
this.children_.length = 0;
let previousElement = null;
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
const layerState = layerStatesArray[i];
frameState.layerIndex = i;
if (!visibleAtResolution(layerState, viewResolution) ||
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
continue;
}
const layer = layerState.layer;
const element = layer.render(frameState, previousElement);
if (element !== previousElement) {
const element = layer.render(frameState);
if (element) {
const zIndex = layerState.zIndex;
if (zIndex !== element.style.zIndex) {
element.style.zIndex = zIndex === Infinity ? Number.MAX_SAFE_INTEGER : zIndex;
}
this.children_.push(element);
previousElement = element;
}
}
super.renderFrame(frameState);

View File

@@ -29,9 +29,10 @@ class LayerRenderer extends Observable {
* Determine whether render should be called.
* @abstract
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
* @param {import("../layer/Layer.js").State} layerState Layer state.
* @return {boolean} Layer is ready to be rendered.
*/
prepareFrame(frameState) {
prepareFrame(frameState, layerState) {
return abstract();
}
@@ -39,10 +40,10 @@ class LayerRenderer extends Observable {
* Render the layer.
* @abstract
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
* @param {HTMLElement} target Target that may be used to render content to.
* @param {import("../layer/Layer.js").State} layerState Layer state.
* @return {HTMLElement} The rendered element.
*/
renderFrame(frameState, target) {
renderFrame(frameState, layerState) {
return abstract();
}

View File

@@ -38,8 +38,7 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
prepareFrame(frameState, layerState) {
const pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const viewResolution = viewState.resolution;
@@ -73,12 +72,11 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState, target) {
renderFrame(frameState, layerState) {
const image = this.image_;
const imageExtent = image.getExtent();
const imageResolution = image.getResolution();
const imagePixelRatio = image.getPixelRatio();
const layerState = frameState.layerStatesArray[frameState.layerIndex];
const pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const viewCenter = viewState.center;
@@ -103,15 +101,13 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
);
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
this.useContainer(target, this.pixelTransform_, layerState.opacity);
const context = this.context;
const canvas = context.canvas;
if (canvas.width != width || canvas.height != height) {
canvas.width = width;
canvas.height = height;
} else if (!this.containerReused) {
} else {
context.clearRect(0, 0, width, height);
}
@@ -142,17 +138,8 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
this.preRender(context, frameState);
if (dw >= 0.5 && dh >= 0.5) {
const opacity = layerState.opacity;
let previousAlpha;
if (opacity !== 1) {
previousAlpha = this.context.globalAlpha;
this.context.globalAlpha = opacity;
}
this.context.drawImage(img, 0, 0, +img.width, +img.height,
Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
if (opacity !== 1) {
this.context.globalAlpha = previousAlpha;
}
}
this.postRender(context, frameState);
@@ -160,12 +147,17 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
context.restore();
}
const opacity = layerState.opacity;
if (opacity !== parseFloat(canvas.style.opacity)) {
canvas.style.opacity = opacity;
}
const canvasTransform = transformToString(this.pixelTransform_);
if (canvasTransform !== canvas.style.transform) {
canvas.style.transform = canvasTransform;
}
return this.container;
return canvas;
}

View File

@@ -7,7 +7,7 @@ import RenderEvent from '../../render/Event.js';
import RenderEventType from '../../render/EventType.js';
import {rotateAtOffset} from '../../render/canvas.js';
import LayerRenderer from '../Layer.js';
import {create as createTransform, apply as applyTransform, compose as composeTransform, toString as transformToString} from '../../transform.js';
import {create as createTransform, apply as applyTransform, compose as composeTransform} from '../../transform.js';
/**
* @abstract
@@ -21,12 +21,6 @@ class CanvasLayerRenderer extends LayerRenderer {
super(layer);
/**
* @protected
* @type {HTMLElement}
*/
this.container = null;
/**
* @protected
* @type {number}
@@ -61,57 +55,20 @@ class CanvasLayerRenderer extends LayerRenderer {
* @protected
* @type {CanvasRenderingContext2D}
*/
this.context = null;
/**
* @type {boolean}
*/
this.containerReused = false;
this.context = createCanvasContext2D();
const canvas = this.context.canvas;
canvas.style.position = 'absolute';
canvas.style.transformOrigin = 'top left';
canvas.className = this.getLayer().getClassName();
}
/**
* Get a rendering container from an existing target, if compatible.
* @param {HTMLElement} target Potential render target.
* @param {import("../../transform").Transform} transform Transform.
* @param {number} opacity Opacity.
* @inheritDoc
*/
useContainer(target, transform, opacity) {
const layerClassName = this.getLayer().getClassName();
let container, context;
if (target && target.style.opacity === '' && target.className === layerClassName) {
const canvas = target.firstElementChild;
if (canvas instanceof HTMLCanvasElement) {
context = canvas.getContext('2d');
}
}
if (context && context.canvas.style.transform === transformToString(transform)) {
// Container of the previous layer renderer can be used.
this.container = target;
this.context = context;
this.containerReused = true;
} else if (this.containerReused) {
// Previously reused container cannot be used any more.
this.container = null;
this.context = null;
this.containerReused = false;
}
if (!this.container) {
container = document.createElement('div');
container.className = layerClassName;
let style = container.style;
style.position = 'absolute';
style.width = '100%';
style.height = '100%';
context = createCanvasContext2D();
const canvas = context.canvas;
container.appendChild(canvas);
style = canvas.style;
style.position = 'absolute';
style.transformOrigin = 'top left';
this.container = container;
this.context = context;
}
disposeInternal() {
this.context.canvas.width = this.context.canvas.height = 0;
super.disposeInternal();
}
/**

View File

@@ -125,7 +125,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState) {
prepareFrame(frameState, layerState) {
return true;
}
@@ -137,8 +137,8 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
* @inheritDoc
* @returns {HTMLElement} The rendered element.
*/
renderFrame(frameState, target) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
renderFrame(frameState, layerState) {
const context = this.context;
const viewState = frameState.viewState;
const projection = viewState.projection;
const viewResolution = viewState.resolution;
@@ -224,6 +224,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
}
const canvas = context.canvas;
const canvasScale = tileResolution / viewResolution;
// set forward and inverse pixel transforms
@@ -233,11 +234,6 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
rotation,
-width / 2, -height / 2
);
this.useContainer(target, this.pixelTransform_, layerState.opacity);
const context = this.context;
const canvas = context.canvas;
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
// set scale transform for calculating tile positions on the canvas
@@ -251,7 +247,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
if (canvas.width != width || canvas.height != height) {
canvas.width = width;
canvas.height = height;
} else if (!this.containerReused) {
} else {
context.clearRect(0, 0, width, height);
}
@@ -263,7 +259,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
this.renderedTiles.length = 0;
/** @type {Array<number>} */
let zs = Object.keys(tilesToDrawByZ).map(Number);
const zs = Object.keys(tilesToDrawByZ).map(Number);
zs.sort(function(a, b) {
if (a === z) {
return 1;
@@ -274,14 +270,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
}
});
let clips, clipZs, currentClip;
if (layerState.opacity === 1 && (!this.containerReused || tileSource.getOpaque(frameState.viewState.projection))) {
zs = zs.reverse();
} else {
clips = [];
clipZs = [];
}
for (let i = zs.length - 1; i >= 0; --i) {
for (let i = 0, ii = zs.length; i < ii; ++i) {
const currentZ = zs[i];
const currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
const currentResolution = tileGrid.getResolution(currentZ);
@@ -309,36 +298,8 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const y = Math.round(floatY);
const w = nextX - x;
const h = nextY - y;
const transition = z === currentZ;
if (clips && (!transition || tile.getAlpha(getUid(this), frameState.time) === 1)) {
// Clip mask for regions in this tile that already filled by a higher z tile
context.save();
currentClip = [x, y, x + w, y, x + w, y + h, x, y + h];
for (let i = 0, ii = clips.length; i < ii; ++i) {
if (z !== currentZ && currentZ < clipZs[i]) {
const clip = clips[i];
context.beginPath();
// counter-clockwise (outer ring) for current tile
context.moveTo(currentClip[0], currentClip[1]);
context.lineTo(currentClip[2], currentClip[3]);
context.lineTo(currentClip[4], currentClip[5]);
context.lineTo(currentClip[6], currentClip[7]);
// clockwise (inner ring) for higher z tile
context.moveTo(clip[6], clip[7]);
context.lineTo(clip[4], clip[5]);
context.lineTo(clip[2], clip[3]);
context.lineTo(clip[0], clip[1]);
context.clip();
}
}
clips.push(currentClip);
clipZs.push(currentZ);
}
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, transition, layerState.opacity);
if (clips) {
context.restore();
}
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, z === currentZ);
this.renderedTiles.push(tile);
this.updateUsedTiles(frameState.usedTiles, tileSource, tile);
}
@@ -361,12 +322,17 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
context.restore();
}
const opacity = layerState.opacity;
if (opacity !== parseFloat(canvas.style.opacity)) {
canvas.style.opacity = opacity;
}
const canvasTransform = transformToString(this.pixelTransform_);
if (canvasTransform !== canvas.style.transform) {
canvas.style.transform = canvasTransform;
}
return this.container;
return canvas;
}
/**
@@ -378,15 +344,19 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
* @param {number} h Height of the tile.
* @param {number} gutter Tile gutter.
* @param {boolean} transition Apply an alpha transition.
* @param {number} opacity Opacity.
*/
drawTileImage(tile, frameState, x, y, w, h, gutter, transition, opacity) {
drawTileImage(tile, frameState, x, y, w, h, gutter, transition) {
const image = this.getTileImage(tile);
if (!image) {
return;
}
const uid = getUid(this);
const alpha = opacity * (transition ? tile.getAlpha(uid, frameState.time) : 1);
const alpha = transition ? tile.getAlpha(uid, frameState.time) : 1;
const tileLayer = /** @type {import("../../layer/Tile.js").default} */ (this.getLayer());
const tileSource = tileLayer.getSource();
if (alpha === 1 && !tileSource.getOpaque(frameState.viewState.projection)) {
this.context.clearRect(x, y, w, h);
}
const alphaChanged = alpha !== this.context.globalAlpha;
if (alphaChanged) {
this.context.save();

View File

@@ -63,7 +63,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState) {
prepareFrame(frameState, layerState) {
const pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const viewResolution = viewState.resolution;
@@ -78,7 +78,6 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] && !isEmpty(renderedExtent)) {
let skippedFeatures = this.skippedFeatures_;
vectorRenderer.useContainer(null, null, 1);
const context = vectorRenderer.context;
const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, {
declutterItems: [],
@@ -92,10 +91,10 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
}));
const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
const image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
if (vectorRenderer.prepareFrame(imageFrameState) &&
if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
(vectorRenderer.replayGroupChanged ||
!equals(skippedFeatures, newSkippedFeatures))) {
vectorRenderer.renderFrame(imageFrameState, null);
vectorRenderer.renderFrame(imageFrameState, layerState);
renderDeclutterItems(imageFrameState, null);
skippedFeatures = newSkippedFeatures;
callback();

View File

@@ -70,37 +70,24 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
useContainer(target, transform, opacity) {
if (opacity < 1) {
target = null;
}
super.useContainer(target, transform, opacity);
}
/**
* @inheritDoc
*/
renderFrame(frameState, target) {
const pixelRatio = frameState.pixelRatio;
const layerState = frameState.layerStatesArray[frameState.layerIndex];
// set forward and inverse pixel transforms
makeScale(this.pixelTransform_, 1 / pixelRatio, 1 / pixelRatio);
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
this.useContainer(target, this.pixelTransform_, layerState.opacity);
renderFrame(frameState, layerState) {
const context = this.context;
const canvas = context.canvas;
const replayGroup = this.replayGroup_;
if (!replayGroup || replayGroup.isEmpty()) {
if (!this.containerReused && canvas.width > 0) {
if (canvas.width > 0) {
canvas.width = 0;
}
return this.container;
return canvas;
}
const pixelRatio = frameState.pixelRatio;
// set forward and inverse pixel transforms
makeScale(this.pixelTransform_, 1 / pixelRatio, 1 / pixelRatio);
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
// resize and clear
const width = Math.round(frameState.size[0] * pixelRatio);
const height = Math.round(frameState.size[1] * pixelRatio);
@@ -111,7 +98,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
if (canvas.style.transform !== canvasTransform) {
canvas.style.transform = canvasTransform;
}
} else if (!this.containerReused) {
} else {
context.clearRect(0, 0, width, height);
}
@@ -165,7 +152,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
if (declutterReplays) {
const viewHints = frameState.viewHints;
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
replayDeclutter(declutterReplays, context, rotation, 1, hifi, frameState.declutterItems);
replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems);
}
if (clipped) {
@@ -175,12 +162,11 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
this.postRender(context, frameState);
const opacity = layerState.opacity;
const container = this.container;
if (opacity !== parseFloat(container.style.opacity)) {
container.style.opacity = opacity === 1 ? '' : opacity;
if (opacity !== parseFloat(canvas.style.opacity)) {
canvas.style.opacity = opacity;
}
return this.container;
return canvas;
}
/**
@@ -233,7 +219,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState) {
prepareFrame(frameState, layerState) {
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
const vectorSource = vectorLayer.getSource();

View File

@@ -24,6 +24,7 @@ import {
makeInverse
} from '../../transform.js';
import CanvasExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js';
import {clear, isEmpty} from '../../obj.js';
/**
@@ -58,11 +59,32 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
constructor(layer) {
super(layer);
const baseCanvas = this.context.canvas;
/**
* @private
* @type {CanvasRenderingContext2D}
*/
this.overlayContext_ = null;
this.overlayContext_ = createCanvasContext2D();
const overlayCanvas = this.overlayContext_.canvas;
overlayCanvas.style.position = 'absolute';
overlayCanvas.style.transformOrigin = 'top left';
const container = document.createElement('div');
const style = container.style;
style.position = 'absolute';
style.width = '100%';
style.height = '100%';
container.appendChild(baseCanvas);
container.appendChild(overlayCanvas);
/**
* @private
* @type {HTMLElement}
*/
this.container_ = container;
/**
* The transform for rendered pixels to viewport CSS pixels for the overlay canvas.
@@ -114,43 +136,17 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @inheritDoc
*/
useContainer(target, transform, opacity) {
let overlayContext;
if (target && target.childElementCount === 2) {
overlayContext = target.lastElementChild.getContext('2d');
if (!overlayContext) {
target = null;
}
}
const containerReused = this.containerReused;
super.useContainer(target, transform, opacity);
if (containerReused && !this.containerReused && !overlayContext) {
this.overlayContext_ = null;
}
if (this.containerReused && overlayContext) {
this.overlayContext_ = overlayContext;
}
if (!this.overlayContext_) {
const overlayContext = createCanvasContext2D();
const style = overlayContext.canvas.style;
style.position = 'absolute';
style.transformOrigin = 'top left';
this.overlayContext_ = overlayContext;
}
if (this.container.childElementCount === 1) {
this.container.appendChild(this.overlayContext_.canvas);
}
disposeInternal() {
this.overlayContext_.canvas.width = this.overlayContext_.canvas.height = 0;
super.disposeInternal();
}
/**
* @param {import("../../VectorRenderTile.js").default} tile Tile.
* @param {number} pixelRatio Pixel ratio.
* @param {import("../../proj/Projection").default} projection Projection.
* @param {boolean} queue Queue tile for rendering.
* @return {boolean} Tile needs to be rendered.
*/
prepareTile(tile, pixelRatio, projection, queue) {
let render = false;
prepareTile(tile, pixelRatio, projection) {
const tileUid = getUid(tile);
const state = tile.getState();
if (((state === TileState.LOADED && tile.hifi) ||
@@ -162,13 +158,9 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (state === TileState.LOADED || state === TileState.ERROR) {
this.updateExecutorGroup_(tile, pixelRatio, projection);
if (this.tileImageNeedsRender_(tile, pixelRatio, projection)) {
render = true;
if (queue) {
this.renderTileImageQueue_[tileUid] = tile;
}
this.renderTileImageQueue_[tileUid] = tile;
}
}
return render;
}
/**
@@ -184,7 +176,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
tile.wantedResolution = resolution;
const tileUid = getUid(tile);
if (!(tileUid in this.tileListenerKeys_)) {
const listenerKey = listen(tile, EventType.CHANGE, this.prepareTile.bind(this, tile, pixelRatio, projection, true));
const listenerKey = listen(tile, EventType.CHANGE, this.prepareTile.bind(this, tile, pixelRatio, projection));
this.tileListenerKeys_[tileUid] = listenerKey;
}
} else {
@@ -193,10 +185,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (hifi || !tile.wantedResolution) {
tile.wantedResolution = resolution;
}
const render = this.prepareTile(tile, pixelRatio, projection, false);
if (render) {
this.renderTileImage_(tile, frameState);
}
this.prepareTile(tile, pixelRatio, projection);
}
return tile;
}
@@ -218,13 +207,13 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState) {
prepareFrame(frameState, layerState) {
const layerRevision = this.getLayer().getRevision();
if (this.renderedLayerRevision_ != layerRevision) {
this.renderedTiles.length = 0;
}
this.renderedLayerRevision_ = layerRevision;
return super.prepareFrame(frameState);
return super.prepareFrame(frameState, layerState);
}
/**
@@ -390,30 +379,26 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState, target) {
const viewHints = frameState.viewHints;
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
this.renderQueuedTileImages_(hifi, frameState);
super.renderFrame(frameState, target);
renderFrame(frameState, layerState) {
super.renderFrame(frameState, layerState);
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
const viewHints = frameState.viewHints;
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
const renderMode = layer.getRenderMode();
if (renderMode === VectorTileRenderType.IMAGE) {
return this.container;
this.renderTileImages_(hifi, frameState);
return this.container_;
}
const source = layer.getSource();
// Unqueue tiles from the image queue when we don't need any more
const usedTiles = frameState.usedTiles[getUid(source)];
for (const tileUid in this.renderTileImageQueue_) {
if (!(tileUid in usedTiles)) {
delete this.renderTileImageQueue_[tileUid];
}
if (!isEmpty(this.renderTileImageQueue_) && !this.extentChanged) {
this.renderTileImages_(hifi, frameState);
return this.container_;
}
const context = this.overlayContext_;
const declutterReplays = layer.getDeclutter() ? {} : null;
const source = layer.getSource();
const replayTypes = VECTOR_REPLAYS[renderMode];
const pixelRatio = frameState.pixelRatio;
const rotation = frameState.viewState.rotation;
@@ -434,14 +419,13 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (canvas.style.transform !== canvasTransform) {
canvas.style.transform = canvasTransform;
}
} else if (!this.containerReused) {
} else {
context.clearRect(0, 0, width, height);
}
const tiles = this.renderedTiles;
const tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
const clips = [];
const clipZs = [];
for (let i = tiles.length - 1; i >= 0; --i) {
const tile = /** @type {import("../../VectorRenderTile.js").default} */ (tiles[i]);
if (tile.getState() == TileState.ABORT) {
@@ -452,7 +436,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
const worldOffset = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent)[0] - tileExtent[0];
const transform = this.getRenderTransform(frameState, width, height, worldOffset);
const executorGroups = tile.executorGroups[getUid(layer)];
let clipped = false;
for (let t = 0, tt = executorGroups.length; t < tt; ++t) {
const executorGroup = executorGroups[t];
if (!executorGroup.hasExecutors(replayTypes)) {
@@ -460,8 +443,9 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
continue;
}
const currentZ = tile.tileCoord[0];
let currentClip;
if (!declutterReplays && !clipped) {
let zs, currentClip;
if (!declutterReplays) {
zs = [];
currentClip = executorGroup.getClipCoords(transform);
context.save();
@@ -469,7 +453,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
// already filled by a higher resolution tile
for (let j = 0, jj = clips.length; j < jj; ++j) {
const clip = clips[j];
if (currentZ < clipZs[j]) {
if (currentZ < zs[j]) {
context.beginPath();
// counter-clockwise (outer ring) for current tile
context.moveTo(currentClip[0], currentClip[1]);
@@ -486,38 +470,51 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
}
}
executorGroup.execute(context, transform, rotation, {}, hifi, replayTypes, declutterReplays);
if (!declutterReplays && !clipped) {
if (!declutterReplays) {
context.restore();
clips.push(currentClip);
clipZs.push(currentZ);
clipped = true;
zs.push(currentZ);
}
}
}
if (declutterReplays) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
replayDeclutter(declutterReplays, context, rotation, layerState.opacity, hifi, frameState.declutterItems);
replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems);
}
return this.container;
const opacity = layerState.opacity;
if (opacity !== parseFloat(canvas.style.opacity)) {
canvas.style.opacity = opacity;
}
// Now that we have rendered the tiles we have already, let's prepare new tile images
// for the next frame
this.renderTileImages_(hifi, frameState);
return this.container_;
}
/**
* @param {boolean} hifi We have time to render a high fidelity map image.
* @param {import('../../PluggableMap.js').FrameState} frameState Frame state.
*/
renderQueuedTileImages_(hifi, frameState) {
renderTileImages_(hifi, frameState) {
// When we don't have time to render hifi, only render tiles until we have used up
// half of the frame budget of 16 ms
for (const uid in this.renderTileImageQueue_) {
if (!hifi && Date.now() - frameState.time > 8) {
frameState.animate = true;
break;
}
const tile = this.renderTileImageQueue_[uid];
frameState.animate = true;
delete this.renderTileImageQueue_[uid];
this.renderTileImage_(tile, frameState);
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
const viewState = frameState.viewState;
const tileGrid = layer.getSource().getTileGridForProjection(viewState.projection);
const tileResolution = tileGrid.getResolution(tile.tileCoord[0]);
const renderPixelRatio = frameState.pixelRatio / tile.wantedResolution * tileResolution;
this.renderTileImage_(tile, frameState.pixelRatio, renderPixelRatio, viewState.projection);
}
clear(this.renderTileImageQueue_);
}
/**
@@ -564,29 +561,24 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @param {import("../../VectorRenderTile.js").default} tile Tile.
* @param {import("../../PluggableMap").FrameState} frameState Frame state.
* @param {number} pixelRatio Pixel ratio.
* @param {number} renderPixelRatio Render pixel ratio.
* @param {import("../../proj/Projection.js").default} projection Projection.
* @private
*/
renderTileImage_(tile, frameState) {
renderTileImage_(tile, pixelRatio, renderPixelRatio, projection) {
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
const replayState = tile.getReplayState(layer);
const revision = layer.getRevision();
const executorGroups = tile.executorGroups[getUid(layer)];
replayState.renderedTileRevision = revision;
replayState.renderedTileZ = tile.sourceZ;
const tileCoord = tile.wrappedTileCoord;
const z = tileCoord[0];
const source = layer.getSource();
let pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const projection = viewState.projection;
const tileGrid = source.getTileGridForProjection(projection);
const tileResolution = tileGrid.getResolution(tile.tileCoord[0]);
const renderPixelRatio = frameState.pixelRatio / tile.wantedResolution * tileResolution;
const resolution = tileGrid.getResolution(z);
const context = tile.getContext(layer);
// Increase tile size when overzooming for low pixel ratio, to avoid blurry tiles
pixelRatio = Math.max(pixelRatio, renderPixelRatio / pixelRatio);
const size = source.getTilePixelSize(z, pixelRatio, projection);

View File

@@ -2,7 +2,7 @@
* @module ol/renderer/webgl/Layer
*/
import LayerRenderer from '../Layer.js';
import WebGLHelper from '../../webgl/Helper.js';
import WebGLHelper from '../../webgl/Helper';
/**

View File

@@ -1,21 +1,21 @@
/**
* @module ol/renderer/webgl/PointsLayer
*/
import WebGLArrayBuffer from '../../webgl/Buffer.js';
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl.js';
import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper.js';
import GeometryType from '../../geom/GeometryType.js';
import WebGLLayerRenderer, {getBlankTexture, pushFeatureToBuffer} from './Layer.js';
import GeoJSON from '../../format/GeoJSON.js';
import {getUid} from '../../util.js';
import ViewHint from '../../ViewHint.js';
import {createEmpty, equals} from '../../extent.js';
import WebGLArrayBuffer from '../../webgl/Buffer';
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl';
import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper';
import GeometryType from '../../geom/GeometryType';
import WebGLLayerRenderer, {getBlankTexture, pushFeatureToBuffer} from './Layer';
import GeoJSON from '../../format/GeoJSON';
import {getUid} from '../../util';
import ViewHint from '../../ViewHint';
import {createEmpty, equals} from '../../extent';
import {
create as createTransform,
makeInverse as makeInverseTransform,
multiply as multiplyTransform,
apply as applyTransform
} from '../../transform.js';
} from '../../transform';
const VERTEX_SHADER = `
precision mediump float;
@@ -25,15 +25,15 @@ const VERTEX_SHADER = `
attribute vec2 a_offsets;
attribute float a_opacity;
attribute vec4 a_color;
uniform mat4 u_projectionMatrix;
uniform mat4 u_offsetScaleMatrix;
uniform mat4 u_offsetRotateMatrix;
varying vec2 v_texCoord;
varying float v_opacity;
varying vec4 v_color;
void main(void) {
mat4 offsetMatrix = u_offsetScaleMatrix;
if (a_rotateWithView == 1.0) {
@@ -48,13 +48,13 @@ const VERTEX_SHADER = `
const FRAGMENT_SHADER = `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 v_texCoord;
varying float v_opacity;
varying vec4 v_color;
void main(void) {
if (v_opacity == 0.0) {
discard;
@@ -222,7 +222,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
return 1;
};
this.coordCallback_ = options.coordCallback || function(feature, index) {
const geom = feature.getGeometry();
const geom = /** @type {import("../../geom/Point").default} */ (feature.getGeometry());
return geom.getCoordinates()[index];
};
this.opacityCallback_ = options.opacityCallback || function() {
@@ -284,8 +284,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
renderFrame(frameState, layerState) {
this.helper_.drawElements(0, this.indicesBuffer_.getArray().length);
this.helper_.finalizeDraw(frameState);
const canvas = this.helper_.getCanvas();

View File

@@ -2,8 +2,8 @@
* @module ol/resolutionconstraint
*/
import {linearFindNearest} from './array.js';
import {getHeight, getWidth} from './extent.js';
import {clamp} from './math.js';
import {getHeight, getWidth} from './extent';
import {clamp} from './math';
/**

View File

@@ -76,7 +76,7 @@ class Cluster extends VectorSource {
* @protected
*/
this.geometryFunction = options.geometryFunction || function(feature) {
const geometry = feature.getGeometry();
const geometry = /** @type {Point} */ (feature.getGeometry());
assert(geometry.getType() == GeometryType.POINT,
10); // The default `geometryFunction` can only handle `Point` geometries
return geometry;

View File

@@ -75,7 +75,6 @@ class IIIF extends TileImage {
const width = size[0];
const height = size[1];
const tileSize = options.tileSize;
const tilePixelRatio = options.tilePixelRatio || 1;
const format = options.format || 'jpg';
const quality = options.quality || (options.version == Versions.VERSION1 ? 'native' : 'default');
let resolutions = options.resolutions || [];
@@ -261,7 +260,7 @@ class IIIF extends TileImage {
return baseUrl + regionParam + '/' + sizeParam + '/0/' + quality + '.' + format;
};
const IiifTileClass = CustomTile.bind(null, tilePixelRatio, tileGrid);
const IiifTileClass = CustomTile.bind(null, tileGrid);
super({
attributions: options.attributions,

View File

@@ -7,7 +7,7 @@ import {createCanvasContext2D} from '../dom.js';
import {listen} from '../events.js';
import Event from '../events/Event.js';
import EventType from '../events/EventType.js';
import {Processor} from 'pixelworks/lib/index.js';
import {Processor} from 'pixelworks/lib/index';
import {equals, getCenter, getHeight, getWidth} from '../extent.js';
import ImageLayer from '../layer/Image.js';
import TileLayer from '../layer/Tile.js';
@@ -214,7 +214,6 @@ class RasterSource extends ImageSource {
extent: null,
focus: null,
index: 0,
layerIndex: 0,
layerStatesArray: getLayerStatesArray(this.layers_),
pixelRatio: 1,
pixelToCoordinateTransform: createTransform(),
@@ -359,8 +358,7 @@ class RasterSource extends ImageSource {
const len = this.layers_.length;
const imageDatas = new Array(len);
for (let i = 0; i < len; ++i) {
frameState.layerIndex = i;
const imageData = getImageData(this.layers_[i], frameState);
const imageData = getImageData(this.layers_[i], frameState, frameState.layerStatesArray[i]);
if (imageData) {
imageDatas[i] = imageData;
} else {
@@ -432,24 +430,21 @@ let sharedContext = null;
* Get image data from a layer.
* @param {import("../layer/Layer.js").default} layer Layer to render.
* @param {import("../PluggableMap.js").FrameState} frameState The frame state.
* @param {import("../layer/Layer.js").State} layerState The layer state.
* @return {ImageData} The image data.
*/
function getImageData(layer, frameState) {
function getImageData(layer, frameState, layerState) {
const renderer = layer.getRenderer();
if (!renderer) {
throw new Error('Unsupported layer type: ' + layer);
}
if (!renderer.prepareFrame(frameState)) {
if (!renderer.prepareFrame(frameState, layerState)) {
return null;
}
const width = frameState.size[0];
const height = frameState.size[1];
const container = renderer.renderFrame(frameState, null);
let element;
if (container) {
element = container.firstElementChild;
}
const element = renderer.renderFrame(frameState, layerState);
if (!(element instanceof HTMLCanvasElement)) {
throw new Error('Unsupported rendered element: ' + element);
}

View File

@@ -35,13 +35,12 @@ import RBush from '../structs/RBush.js';
* @classdesc
* Events emitted by {@link module:ol/source/Vector} instances are instances of this
* type.
* @template {import("../geom/Geometry.js").default} Geometry
*/
export class VectorSourceEvent extends Event {
/**
* @param {string} type Type.
* @param {import("../Feature.js").default<Geometry>=} opt_feature Feature.
* @param {import("../Feature.js").default=} opt_feature Feature.
*/
constructor(type, opt_feature) {
@@ -49,7 +48,7 @@ export class VectorSourceEvent extends Event {
/**
* The feature being added or removed.
* @type {import("../Feature.js").default<Geometry>|undefined}
* @type {import("../Feature.js").default|undefined}
* @api
*/
this.feature = opt_feature;
@@ -155,9 +154,8 @@ export class VectorSourceEvent extends Event {
* by this source are suitable for editing. See {@link module:ol/source/VectorTile~VectorTile} for
* vector data that is optimized for rendering.
*
* @fires VectorSourceEvent<Geometry>
* @fires VectorSourceEvent
* @api
* @template {import("../geom/Geometry.js").default} Geometry
*/
class VectorSource extends Source {
/**
@@ -217,7 +215,7 @@ class VectorSource extends Source {
/**
* @private
* @type {RBush<import("../Feature.js").default<Geometry>>}
* @type {RBush<import("../Feature.js").default>}
*/
this.featuresRtree_ = useSpatialIndex ? new RBush() : null;
@@ -229,21 +227,21 @@ class VectorSource extends Source {
/**
* @private
* @type {!Object<string, import("../Feature.js").default<Geometry>>}
* @type {!Object<string, import("../Feature.js").default>}
*/
this.nullGeometryFeatures_ = {};
/**
* A lookup of features by id (the return from feature.getId()).
* @private
* @type {!Object<string, import("../Feature.js").default<Geometry>>}
* @type {!Object<string, import("../Feature.js").default>}
*/
this.idIndex_ = {};
/**
* A lookup of features without id (keyed by getUid(feature)).
* @private
* @type {!Object<string, import("../Feature.js").default<Geometry>>}
* @type {!Object<string, import("../Feature.js").default>}
*/
this.undefIdIndex_ = {};
@@ -255,7 +253,7 @@ class VectorSource extends Source {
/**
* @private
* @type {Collection<import("../Feature.js").default<Geometry>>}
* @type {Collection<import("../Feature.js").default>}
*/
this.featuresCollection_ = null;
@@ -284,10 +282,7 @@ class VectorSource extends Source {
* instead. A feature will not be added to the source if feature with
* the same id is already there. The reason for this behavior is to avoid
* feature duplication when using bbox or tile loading strategies.
* Note: this also applies if an {@link module:ol/Collection} is used for features,
* meaning that if a feature with a duplicate id is added in the collection, it will
* be removed from it right away.
* @param {import("../Feature.js").default<Geometry>} feature Feature to add.
* @param {import("../Feature.js").default} feature Feature to add.
* @api
*/
addFeature(feature) {
@@ -298,16 +293,13 @@ class VectorSource extends Source {
/**
* Add a feature without firing a `change` event.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @param {import("../Feature.js").default} feature Feature.
* @protected
*/
addFeatureInternal(feature) {
const featureKey = getUid(feature);
if (!this.addToIndex_(featureKey, feature)) {
if (this.featuresCollection_) {
this.featuresCollection_.remove(feature);
}
return;
}
@@ -330,7 +322,7 @@ class VectorSource extends Source {
/**
* @param {string} featureKey Unique identifier for the feature.
* @param {import("../Feature.js").default<Geometry>} feature The feature.
* @param {import("../Feature.js").default} feature The feature.
* @private
*/
setupChangeEvents_(featureKey, feature) {
@@ -345,7 +337,7 @@ class VectorSource extends Source {
/**
* @param {string} featureKey Unique identifier for the feature.
* @param {import("../Feature.js").default<Geometry>} feature The feature.
* @param {import("../Feature.js").default} feature The feature.
* @return {boolean} The feature is "valid", in the sense that it is also a
* candidate for insertion into the Rtree.
* @private
@@ -370,7 +362,7 @@ class VectorSource extends Source {
/**
* Add a batch of features to the source.
* @param {Array<import("../Feature.js").default<Geometry>>} features Features to add.
* @param {Array<import("../Feature.js").default>} features Features to add.
* @api
*/
addFeatures(features) {
@@ -381,7 +373,7 @@ class VectorSource extends Source {
/**
* Add features without firing a `change` event.
* @param {Array<import("../Feature.js").default<Geometry>>} features Features.
* @param {Array<import("../Feature.js").default>} features Features.
* @protected
*/
addFeaturesInternal(features) {
@@ -422,14 +414,14 @@ class VectorSource extends Source {
/**
* @param {!Collection<import("../Feature.js").default<Geometry>>} collection Collection.
* @param {!Collection<import("../Feature.js").default>} collection Collection.
* @private
*/
bindFeaturesCollection_(collection) {
let modifyingCollection = false;
listen(this, VectorEventType.ADDFEATURE,
/**
* @param {VectorSourceEvent<Geometry>} evt The vector source event
* @param {VectorSourceEvent} evt The vector source event
*/
function(evt) {
if (!modifyingCollection) {
@@ -440,7 +432,7 @@ class VectorSource extends Source {
});
listen(this, VectorEventType.REMOVEFEATURE,
/**
* @param {VectorSourceEvent<Geometry>} evt The vector source event
* @param {VectorSourceEvent} evt The vector source event
*/
function(evt) {
if (!modifyingCollection) {
@@ -456,7 +448,7 @@ class VectorSource extends Source {
function(evt) {
if (!modifyingCollection) {
modifyingCollection = true;
this.addFeature(/** @type {import("../Feature.js").default<Geometry>} */ (evt.element));
this.addFeature(/** @type {import("../Feature.js").default} */ (evt.element));
modifyingCollection = false;
}
}, this);
@@ -467,7 +459,7 @@ class VectorSource extends Source {
function(evt) {
if (!modifyingCollection) {
modifyingCollection = true;
this.removeFeature(/** @type {import("../Feature.js").default<Geometry>} */ (evt.element));
this.removeFeature(/** @type {import("../Feature.js").default} */ (evt.element));
modifyingCollection = false;
}
}, this);
@@ -520,7 +512,7 @@ class VectorSource extends Source {
* stop and the function will return the same value.
* Note: this function only iterate through the feature that have a defined geometry.
*
* @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature
* @param {function(import("../Feature.js").default): T} callback Called with each feature
* on the source. Return a truthy value to stop iteration.
* @return {T|undefined} The return value from the last call to the callback.
* @template T
@@ -542,7 +534,7 @@ class VectorSource extends Source {
* value.
*
* @param {import("../coordinate.js").Coordinate} coordinate Coordinate.
* @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature
* @param {function(import("../Feature.js").default): T} callback Called with each feature
* whose goemetry contains the provided coordinate.
* @return {T|undefined} The return value from the last call to the callback.
* @template T
@@ -573,7 +565,7 @@ class VectorSource extends Source {
* features, equivalent to {@link module:ol/source/Vector~VectorSource#forEachFeature #forEachFeature()}.
*
* @param {import("../extent.js").Extent} extent Extent.
* @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature
* @param {function(import("../Feature.js").default): T} callback Called with each feature
* whose bounding box intersects the provided extent.
* @return {T|undefined} The return value from the last call to the callback.
* @template T
@@ -597,7 +589,7 @@ class VectorSource extends Source {
* {@link module:ol/source/Vector~VectorSource#forEachFeatureInExtent #forEachFeatureInExtent()} method instead.
*
* @param {import("../extent.js").Extent} extent Extent.
* @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature
* @param {function(import("../Feature.js").default): T} callback Called with each feature
* whose geometry intersects the provided extent.
* @return {T|undefined} The return value from the last call to the callback.
* @template T
@@ -606,7 +598,7 @@ class VectorSource extends Source {
forEachFeatureIntersectingExtent(extent, callback) {
return this.forEachFeatureInExtent(extent,
/**
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @param {import("../Feature.js").default} feature Feature.
* @return {T|undefined} The return value from the last call to the callback.
*/
function(feature) {
@@ -625,7 +617,7 @@ class VectorSource extends Source {
* Get the features collection associated with this source. Will be `null`
* unless the source was configured with `useSpatialIndex` set to `false`, or
* with an {@link module:ol/Collection} as `features`.
* @return {Collection<import("../Feature.js").default<Geometry>>} The collection of features.
* @return {Collection<import("../Feature.js").default>} The collection of features.
* @api
*/
getFeaturesCollection() {
@@ -635,7 +627,7 @@ class VectorSource extends Source {
/**
* Get all features on the source in random order.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @return {Array<import("../Feature.js").default>} Features.
* @api
*/
getFeatures() {
@@ -649,7 +641,7 @@ class VectorSource extends Source {
}
}
return (
/** @type {Array<import("../Feature.js").default<Geometry>>} */ (features)
/** @type {Array<import("../Feature.js").default>} */ (features)
);
}
@@ -657,7 +649,7 @@ class VectorSource extends Source {
/**
* Get all features whose geometry intersects the provided coordinate.
* @param {import("../coordinate.js").Coordinate} coordinate Coordinate.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @return {Array<import("../Feature.js").default>} Features.
* @api
*/
getFeaturesAtCoordinate(coordinate) {
@@ -677,7 +669,7 @@ class VectorSource extends Source {
* This method is not available when the source is configured with
* `useSpatialIndex` set to `false`.
* @param {import("../extent.js").Extent} extent Extent.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @return {Array<import("../Feature.js").default>} Features.
* @api
*/
getFeaturesInExtent(extent) {
@@ -691,10 +683,10 @@ class VectorSource extends Source {
* This method is not available when the source is configured with
* `useSpatialIndex` set to `false`.
* @param {import("../coordinate.js").Coordinate} coordinate Coordinate.
* @param {function(import("../Feature.js").default<Geometry>):boolean=} opt_filter Feature filter function.
* @param {function(import("../Feature.js").default):boolean=} opt_filter Feature filter function.
* The filter function will receive one argument, the {@link module:ol/Feature feature}
* and it should return a boolean value. By default, no filtering is made.
* @return {import("../Feature.js").default<Geometry>} Closest feature.
* @return {import("../Feature.js").default} Closest feature.
* @api
*/
getClosestFeatureToCoordinate(coordinate, opt_filter) {
@@ -714,7 +706,7 @@ class VectorSource extends Source {
const filter = opt_filter ? opt_filter : TRUE;
this.featuresRtree_.forEachInExtent(extent,
/**
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @param {import("../Feature.js").default} feature Feature.
*/
function(feature) {
if (filter(feature)) {
@@ -761,7 +753,7 @@ class VectorSource extends Source {
* `source.getFeatureById(2)` will return a feature with id `'2'` or `2`.
*
* @param {string|number} id Feature identifier.
* @return {import("../Feature.js").default<Geometry>} The feature (or `null` if not found).
* @return {import("../Feature.js").default} The feature (or `null` if not found).
* @api
*/
getFeatureById(id) {
@@ -805,7 +797,7 @@ class VectorSource extends Source {
* @private
*/
handleFeatureChange_(event) {
const feature = /** @type {import("../Feature.js").default<Geometry>} */ (event.target);
const feature = /** @type {import("../Feature.js").default} */ (event.target);
const featureKey = getUid(feature);
const geometry = feature.getGeometry();
if (!geometry) {
@@ -853,7 +845,7 @@ class VectorSource extends Source {
/**
* Returns true if the feature is contained within the source.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @param {import("../Feature.js").default} feature Feature.
* @return {boolean} Has feature.
* @api
*/
@@ -935,7 +927,7 @@ class VectorSource extends Source {
* Remove a single feature from the source. If you want to remove all features
* at once, use the {@link module:ol/source/Vector~VectorSource#clear #clear()} method
* instead.
* @param {import("../Feature.js").default<Geometry>} feature Feature to remove.
* @param {import("../Feature.js").default} feature Feature to remove.
* @api
*/
removeFeature(feature) {
@@ -954,7 +946,7 @@ class VectorSource extends Source {
/**
* Remove feature without firing a `change` event.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @param {import("../Feature.js").default} feature Feature.
* @protected
*/
removeFeatureInternal(feature) {
@@ -975,7 +967,7 @@ class VectorSource extends Source {
/**
* Remove a feature from the id index. Called internally when the feature id
* may have changed.
* @param {import("../Feature.js").default<Geometry>} feature The feature.
* @param {import("../Feature.js").default} feature The feature.
* @return {boolean} Removed the feature from the index.
* @private
*/

View File

@@ -15,10 +15,10 @@ import {
rotate as rotateTransform,
scale as scaleTransform,
translate as translateTransform
} from '../transform.js';
import {create, fromTransform} from '../vec/mat4.js';
import WebGLPostProcessingPass from './PostProcessingPass.js';
import {getContext} from '../webgl.js';
} from '../transform';
import {create, fromTransform} from '../vec/mat4';
import WebGLPostProcessingPass from './PostProcessingPass';
import {getContext} from '../webgl';
/**

View File

@@ -2,7 +2,7 @@
* A worker that responds to messages by posting a message with the version identifer.
* @module ol/worker/version
*/
import {VERSION} from '../util.js';
import {VERSION} from '../util';
onmessage = event => {
console.log('version worker received message:', event.data); // eslint-disable-line

View File

@@ -76,7 +76,7 @@ main() {
npm install
npm run build-package
cd ${BUILT_PACKAGE}
npm publish --tag beta
npm publish
}
if test ${#} -ne 1; then

View File

@@ -3,7 +3,7 @@ import Map from '../../../src/ol/Map.js';
import {get as getProjection} from '../../../src/ol/proj.js';
import Stroke from '../../../src/ol/style/Stroke.js';
import Text from '../../../src/ol/style/Text.js';
import Feature from '../../../src/ol/Feature.js';
import Feature from '../../../src/ol/Feature';
describe('ol.layer.Graticule', function() {
let graticule;

View File

@@ -4,7 +4,7 @@ import Map from '../../../src/ol/Map.js';
import MapEvent from '../../../src/ol/MapEvent.js';
import Overlay from '../../../src/ol/Overlay.js';
import View from '../../../src/ol/View.js';
import {LineString, Point} from '../../../src/ol/geom.js';
import {LineString, Point} from '../../../src/ol/geom';
import {TOUCH} from '../../../src/ol/has.js';
import {focus} from '../../../src/ol/events/condition.js';
import {defaults as defaultInteractions} from '../../../src/ol/interaction.js';

View File

@@ -1,4 +1,4 @@
import LabelCache from '../../../../../src/ol/render/canvas/LabelCache.js';
import LabelCache from '../../../../../src/ol/render/canvas/LabelCache';
describe('ol.render.canvas.LabelCache', function() {

View File

@@ -35,8 +35,6 @@ describe('ol/renderer/canvas/VectorImageLayer', function() {
projExtent[0] - 10000, -10000, projExtent[0] + 10000, 10000
];
const frameState = {
layerStatesArray: [layer.getLayerState()],
layerIndex: 0,
extent: extent,
skippedFeatureUids: {},
viewHints: [],
@@ -46,7 +44,7 @@ describe('ol/renderer/canvas/VectorImageLayer', function() {
rotation: 0
}
};
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
const expected = renderer.image_.getExtent();
scaleFromCenter(extent, 2);

View File

@@ -243,7 +243,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
frameState.extent =
[projExtent[0] - 10000, -10000, projExtent[0] + 10000, 10000];
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
projExtent[0] - worldWidth + buffer,
-10000, projExtent[2] + worldWidth - buffer, 10000
@@ -255,7 +255,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
frameState.extent =
[projExtent[0] - 10000, -10000, projExtent[1] - 10000, 10000];
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
projExtent[0] - worldWidth + buffer,
-10000, projExtent[2] + worldWidth - buffer, 10000
@@ -266,7 +266,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
frameState.extent =
[2 * projExtent[0] - 10000, -10000, 2 * projExtent[1] + 10000, 10000];
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
projExtent[0] - worldWidth + buffer,
-10000, projExtent[2] + worldWidth - buffer, 10000
@@ -279,7 +279,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
projExtent[0] - 2 * worldWidth - 10000,
-10000, projExtent[1] + 2 * worldWidth + 10000, 10000
];
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
projExtent[0] - 2 * worldWidth - 10000,
-10000, projExtent[2] + 2 * worldWidth + 10000, 10000
@@ -288,9 +288,9 @@ describe('ol.renderer.canvas.VectorLayer', function() {
it('sets replayGroupChanged correctly', function() {
frameState.extent = [-10000, -10000, 10000, 10000];
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
expect(renderer.replayGroupChanged).to.be(true);
renderer.prepareFrame(frameState);
renderer.prepareFrame(frameState, {});
expect(renderer.replayGroupChanged).to.be(false);
});
@@ -301,15 +301,13 @@ describe('ol.renderer.canvas.VectorLayer', function() {
expect(true);
done();
});
frameState.layerStatesArray = [layer.getLayerState()];
frameState.layerIndex = 0;
frameState.extent = [-10000, -10000, 10000, 10000];
frameState.size = [100, 100];
frameState.viewState.center = [0, 0];
let rendered = false;
if (renderer.prepareFrame(frameState)) {
if (renderer.prepareFrame(frameState, {})) {
rendered = true;
renderer.renderFrame(frameState, null);
renderer.renderFrame(frameState, layer.getLayerState());
}
expect(rendered).to.be(true);
});

View File

@@ -234,8 +234,6 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
};
const proj = getProjection('EPSG:3857');
const frameState = {
layerStatesArray: [layer.getLayerState()],
layerIndex: 0,
extent: proj.getExtent(),
pixelRatio: 1,
time: Date.now(),
@@ -249,13 +247,13 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
usedTiles: {},
wantedTiles: {}
};
renderer.renderFrame(frameState);
renderer.renderFrame(frameState, {});
const replayState = renderer.renderedTiles[0].getReplayState(layer);
const revision = replayState.renderedTileRevision;
renderer.renderFrame(frameState, null);
renderer.renderFrame(frameState, {});
expect(replayState.renderedTileRevision).to.be(revision);
layer.changed();
renderer.renderFrame(frameState, null);
renderer.renderFrame(frameState, {});
expect(replayState.renderedTileRevision).to.be(revision + 1);
expect(Object.keys(renderer.tileListenerKeys_).length).to.be(0);
});

View File

@@ -1,6 +1,6 @@
import WebGLLayerRenderer, {getBlankTexture, pushFeatureToBuffer} from '../../../../../src/ol/renderer/webgl/Layer.js';
import WebGLArrayBuffer from '../../../../../src/ol/webgl/Buffer.js';
import Layer from '../../../../../src/ol/layer/Layer.js';
import WebGLLayerRenderer, {getBlankTexture, pushFeatureToBuffer} from '../../../../../src/ol/renderer/webgl/Layer';
import WebGLArrayBuffer from '../../../../../src/ol/webgl/Buffer';
import Layer from '../../../../../src/ol/layer/Layer';
describe('ol.renderer.webgl.Layer', function() {

View File

@@ -3,10 +3,10 @@ import Point from '../../../../../src/ol/geom/Point.js';
import LineString from '../../../../../src/ol/geom/LineString.js';
import VectorLayer from '../../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../../src/ol/source/Vector.js';
import WebGLPointsLayerRenderer from '../../../../../src/ol/renderer/webgl/PointsLayer.js';
import {get as getProjection} from '../../../../../src/ol/proj.js';
import Polygon from '../../../../../src/ol/geom/Polygon.js';
import ViewHint from '../../../../../src/ol/ViewHint.js';
import WebGLPointsLayerRenderer from '../../../../../src/ol/renderer/webgl/PointsLayer';
import {get as getProjection} from '../../../../../src/ol/proj';
import Polygon from '../../../../../src/ol/geom/Polygon';
import ViewHint from '../../../../../src/ol/ViewHint';
describe('ol.renderer.webgl.PointsLayer', function() {

View File

@@ -1,5 +1,5 @@
import {createSnapToResolutions, createSnapToPower} from '../../../src/ol/resolutionconstraint.js';
import {createMinMaxResolution} from '../../../src/ol/resolutionconstraint.js';
import {createMinMaxResolution} from '../../../src/ol/resolutionconstraint';
describe('ol.resolutionconstraint', function() {

View File

@@ -719,19 +719,6 @@ describe('ol.source.Vector', function() {
expect(source.getFeatures().length).to.be(0);
});
it('prevents adding two features with a duplicate id in the collection', function() {
source = new VectorSource({
features: new Collection()
});
const feature1 = new Feature();
feature1.setId('1');
const feature2 = new Feature();
feature2.setId('1');
const collection = source.getFeaturesCollection();
collection.push(feature1);
collection.push(feature2);
expect(collection.getLength()).to.be(1);
});
});
describe('with a collection of features plus spatial index', function() {

View File

@@ -1,4 +1,4 @@
import WebGLArrayBuffer from '../../../../src/ol/webgl/Buffer.js';
import WebGLArrayBuffer from '../../../../src/ol/webgl/Buffer';
describe('ol.webgl.Buffer', function() {

View File

@@ -1,9 +1,9 @@
import WebGLHelper from '../../../../src/ol/webgl/Helper.js';
import WebGLHelper from '../../../../src/ol/webgl/Helper';
import {
create as createTransform,
rotate as rotateTransform,
scale as scaleTransform, translate as translateTransform
} from '../../../../src/ol/transform.js';
} from '../../../../src/ol/transform';
const VERTEX_SHADER = `