Compare commits

..

55 Commits

Author SHA1 Message Date
ahocevar
fbe815853d Publish with beta tag 2019-05-30 15:58:19 +02:00
ahocevar
a50ef05565 Set version to 6.0.0-beta.9 2019-05-30 15:55:09 +02:00
Tim Schaub
93a607d846 Merge pull request #9615 from tschaub/import-specifiers
Include full filename in import specifier
2019-05-29 09:35:34 -06:00
Tim Schaub
deb00f20fe Include full filename in import specifier 2019-05-29 08:51:10 -06:00
Frédéric Junod
c4e465dcf9 Merge pull request #9592 from fredj/f9587_layerIndex
Remove `layerState` param from `prepareFrame` and `renderFrame` function
2019-05-29 09:27:38 +02:00
Frederic Junod
bfea858306 Add missing extension in import 2019-05-29 09:19:17 +02:00
Frédéric Junod
c92bf29677 Fix spelling
Co-Authored-By: Tim Schaub <tschaub@users.noreply.github.com>
2019-05-29 09:07:05 +02:00
Andreas Hocevar
6675f9be57 Merge pull request #9289 from sbrunner/vector-source-geom
Vector source geom
2019-05-28 11:23:31 +02:00
Frédéric Junod
1a6d67776b Merge pull request #9608 from fredj/md_link
Use markdown link syntax in jsdoc
2019-05-27 14:17:18 +02:00
Stéphane Brunner
889b6a9f43 Removes unnecessary type cast 2019-05-27 11:34:33 +02:00
Stéphane Brunner
970c1bcb66 Make the vector source geometry generic 2019-05-27 11:34:31 +02:00
Frederic Junod
2db953ceb1 Use markdown link syntax in jsdoc 2019-05-27 11:06:12 +02:00
Olivier Guyot
051cc68f24 Merge pull request #9596 from jahow/fix-source-missing-event
Vector source / prevent adding features with duplicate id in the collection
2019-05-26 10:53:58 +02:00
Frederic Junod
40c49a9ce5 Remove layerState param from prepareFrame and renderFrame function 2019-05-25 07:19:10 +02:00
Olivier Guyot
442fa907ce Vector source / prevent adding features with duplicate id...
...in the collection.

Previously two features with the same id could be pushed manually in the
features collection and stay there.

This would cause an error when clearing the source.

Fixes #6183.
2019-05-24 23:29:48 +02:00
Bart van den Eijnden
7044e30529 Merge pull request #9604 from bartvde/window-global
Use window instead of global in addEventListener
2019-05-24 15:17:07 +02:00
Frédéric Junod
7cfe047feb Merge pull request #9599 from openlayers/github_funding
Create FUNDING.yml
2019-05-24 15:14:26 +02:00
Tim Schaub
796f20385d Merge pull request #9598 from openlayers/greenkeeper/puppeteer-1.17.0
Update puppeteer to the latest version 🚀
2019-05-24 06:58:00 -06:00
bartvde
c76aa76743 Use window instead of global in addEventListener 2019-05-24 14:51:32 +02:00
Bart van den Eijnden
2969c9e8fb Merge pull request #9601 from bartvde/fix-addeventlistener2
Use global addEventListener in PluggableMap
2019-05-24 14:11:26 +02:00
bartvde
119c24faa2 Use global addEventListener in PluggableMap 2019-05-24 13:45:19 +02:00
Frédéric Junod
93711ea806 Create FUNDING.yml 2019-05-24 11:19:37 +02:00
Andreas Hocevar
96331c5d95 Merge pull request #9584 from ahocevar/reuse-render-target
Reuse render target
2019-05-24 10:33:36 +02:00
ahocevar
d8f41a9d73 Only reuse target when className is the same 2019-05-24 10:16:20 +02:00
greenkeeper[bot]
311900e441 chore(package): update puppeteer to version 1.17.0 2019-05-24 00:18:21 +00:00
ahocevar
bdb87f06f9 Rework tile image render queue 2019-05-23 15:55:29 +02:00
Frédéric Junod
ddb7da3733 Merge pull request #6217 from fredj/dragpan_primary
Add primaryAction condition to DragPan
2019-05-23 09:50:55 +02:00
Tim Schaub
a358521b2b Merge pull request #9594 from openlayers/greenkeeper/webpack-4.32.2
Update webpack to the latest version 🚀
2019-05-22 21:12:52 -06:00
greenkeeper[bot]
4f833501d7 chore(package): update webpack to version 4.32.2 2019-05-22 23:39:55 +00:00
ahocevar
ace5c65ee5 Smarter opacity handling 2019-05-22 16:47:23 +02:00
ahocevar
ae47d3df58 Use opacity from layer state 2019-05-22 16:47:22 +02:00
ahocevar
4c8effe6fa No tile transition when layer opacity is set 2019-05-22 16:47:22 +02:00
ahocevar
c56ad4363d Canvas opacity instead of css 2019-05-22 16:47:22 +02:00
ahocevar
7895b16043 Reuse container for raster and vector image layers 2019-05-22 16:47:20 +02:00
ahocevar
a45e704be2 Smarter reuse detection 2019-05-22 16:46:46 +02:00
ahocevar
d1f1b468b1 Reuse target for image layers 2019-05-22 16:46:46 +02:00
ahocevar
a55505b36a Reuse containers for tile, vector and vector tile layers 2019-05-22 16:46:40 +02:00
ahocevar
930318ab7a Clip high res tiles out of low res tiles only once 2019-05-22 15:57:15 +02:00
ahocevar
5fe9e06535 Use clipping to not render high res tiles on top of low res 2019-05-22 15:57:15 +02:00
ahocevar
606443bc6d Pass render target of previous layer to next layer 2019-05-22 15:56:51 +02:00
Frederic Junod
ec811bfa1f Add primaryAction condition to DragPan interaction 2019-05-22 15:21:17 +02:00
Tim Schaub
5e8d7f666e Merge pull request #9589 from openlayers/greenkeeper/webpack-4.32.1
Update webpack to the latest version 🚀
2019-05-22 06:35:21 -06:00
greenkeeper[bot]
4f9057f066 chore(package): update webpack to version 4.32.1 2019-05-22 06:59:26 +00:00
Tim Schaub
4ed6413635 Merge pull request #9586 from openlayers/greenkeeper/rollup-plugin-terser-5.0.0
Update rollup-plugin-terser to the latest version 🚀
2019-05-21 18:34:20 -06:00
greenkeeper[bot]
bb5ebaa1ab chore(package): update rollup-plugin-terser to version 5.0.0 2019-05-21 22:32:01 +00:00
Tim Schaub
c9491ed023 Merge pull request #9569 from engsterhold/patch-1
Fix for change in Zoomify.js/CustomTile signature
2019-05-21 06:52:51 -06:00
Tim Schaub
3db13fa3bb Merge pull request #9582 from tschaub/stale
Add app to mark inactive issues as stale
2019-05-21 06:49:56 -06:00
robert
7e4e113ac9 lint fix
Signed-off-by: robert <24939343+engsterhold@users.noreply.github.com>
2019-05-21 12:32:30 +02:00
Tim Schaub
dc4ce62fab Merge pull request #9581 from tschaub/update-webpack
Update webpack and use mode in the loader
2019-05-20 19:43:37 -06:00
Tim Schaub
6288744d70 Configure Stale app
See https://github.com/organizations/openlayers/settings/installations/1008384
2019-05-20 17:56:30 -06:00
Tim Schaub
c0339f167b Use mode from the loader context
See https://github.com/webpack/webpack/pull/9140.
2019-05-20 10:33:59 -06:00
greenkeeper[bot]
60007d8e3c chore(package): update webpack to version 4.32.0 2019-05-20 10:33:20 -06:00
engsterhold
f77b0941b8 fixed styling 2019-05-17 13:52:10 +02:00
ahocevar
b0fae46aa6 Do not use css z-index 2019-05-16 22:29:32 +02:00
engsterhold
e69b15d33e Bandaid fix for change in Zoomify.js/CustomTile signature
The recent addition of tilePixelRatio to the Zoomify.js/CustomTile constructor broke parameter binding in IIIF.js/IIIF.
The fix mirrors the change in the  Zoomify.js/Zoomify constructor
2019-05-16 16:10:58 +02:00
94 changed files with 627 additions and 21796 deletions

View File

@@ -50,11 +50,3 @@ 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 Normal file
View File

@@ -0,0 +1,8 @@
# 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 Normal file
View File

@@ -0,0 +1,17 @@
# 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,5 +2,3 @@
/coverage/
/dist/
node_modules/
/.cache/
/public/

View File

@@ -1,23 +0,0 @@
{
"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

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

View File

@@ -1,170 +0,0 @@
/**
* 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,6 +5,7 @@ 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()
@@ -51,21 +52,21 @@ const zoomtoswitzerland =
document.getElementById('zoomtoswitzerland');
zoomtoswitzerland.addEventListener('click', function() {
const feature = source.getFeatures()[0];
const polygon = /** @type {import("../src/ol/geom/SimpleGeometry.js").default} */ (feature.getGeometry());
const polygon = 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 = /** @type {import("../src/ol/geom/SimpleGeometry.js").default} */ (feature.getGeometry());
const point = 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 = /** @type {import("../src/ol/geom/Point.js").default} */ (feature.getGeometry());
const point = 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';
import SourceState from '../src/ol/source/State.js';
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';
import ZoomSlider from '../src/ol/control/ZoomSlider.js';
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 = new Feature({
const geoMarker = /** @type Feature<import("../src/ol/geom/Point").default> */(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 = /** @type {import("../src/ol/geom/Point").default} */ (geoMarker.getGeometry());
const geometry = 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';
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';
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';
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';
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';
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';
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';
import {toLonLat, fromLonLat} from '../src/ol/proj';
import Layer from '../src/ol/layer/Layer.js';
import {toLonLat, fromLonLat} from '../src/ol/proj.js';
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,14 +2,7 @@ const build = require('../../tasks/serialize-workers').build;
function loader() {
const callback = this.async();
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';
}
const minify = this.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';
import {create as createVersionWorker} from '../src/ol/worker/version.js';
const map = new Map({

View File

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

View File

@@ -1,23 +0,0 @@
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

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ol",
"version": "6.0.0-beta.8",
"version": "6.0.0-beta.9",
"description": "OpenLayers mapping library",
"keywords": [
"map",
@@ -24,10 +24,7 @@
"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",
"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"
"apidoc": "jsdoc -R config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
},
"main": "index.js",
"repository": {
@@ -46,8 +43,6 @@
"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",
@@ -61,15 +56,10 @@
"copy-webpack-plugin": "^5.0.3",
"coveralls": "3.0.3",
"eslint": "^5.16.0",
"eslint-config-openlayers": "^11.0.0",
"eslint-config-tschaub": "^13.1.0",
"eslint-plugin-react": "^7.13.0",
"eslint-config-openlayers": "^12.0.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",
@@ -78,7 +68,6 @@
"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",
@@ -95,28 +84,20 @@
"pixelmatch": "^4.0.2",
"pngjs": "^3.4.0",
"proj4": "2.5.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",
"puppeteer": "~1.17.0",
"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": "^4.0.4",
"rollup-plugin-terser": "^5.0.0",
"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.31.0",
"webpack": "4.32.2",
"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';
import {Heatmap as HeatmapLayer} from '../../../src/ol/layer';
import VectorSource from '../../../src/ol/source/Vector';
import KML from '../../../src/ol/format/KML';
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';
const vector = new HeatmapLayer({
source: new VectorSource({

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -0,0 +1,30 @@
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';
} from '../../../src/ol/proj.js';
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';
import {fromLonLat} from '../../../src/ol/proj.js';
import {transformExtent} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ';
import XYZ from '../../../src/ol/source/XYZ.js';
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';
import XYZ from '../../../src/ol/source/XYZ.js';
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';
import XYZ from '../../../src/ol/source/XYZ';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
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';
import XYZ from '../../../src/ol/source/XYZ';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
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';
import XYZ from '../../../src/ol/source/XYZ';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
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';
import XYZ from '../../../src/ol/source/XYZ';
import {fromLonLat} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ.js';
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';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
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';
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';
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';
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';
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';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
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';
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';
import MVT from '../../../src/ol/format/MVT';
import {createXYZ} from '../../../src/ol/tilegrid';
import VectorTileLayer from '../../../src/ol/layer/VectorTile';
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';
new Map({
layers: [

View File

@@ -9,12 +9,6 @@ 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({
@@ -27,6 +21,12 @@ 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';
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';
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';
class CustomLayer extends VectorLayer {
createRenderer() {

View File

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

View File

@@ -1,35 +0,0 @@
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;

View File

@@ -1,26 +0,0 @@
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;

View File

@@ -1,35 +0,0 @@
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

@@ -1,26 +0,0 @@
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

@@ -1,20 +0,0 @@
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;

View File

@@ -1,27 +0,0 @@
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

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

View File

@@ -1,26 +0,0 @@
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;

View File

@@ -1,33 +0,0 @@
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;

View File

@@ -1,205 +0,0 @@
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;
}

View File

@@ -1,9 +0,0 @@
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,10 +57,11 @@ import BaseObject, {getChangeEventType} from './Object.js';
* ```
*
* @api
* @template {import("./geom/Geometry.js").default} Geometry
*/
class Feature extends BaseObject {
/**
* @param {import("./geom/Geometry.js").default|Object<string, *>=} opt_geometryOrProperties
* @param {Geometry|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.
@@ -106,7 +107,7 @@ class Feature extends BaseObject {
if (opt_geometryOrProperties) {
if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') {
const geometry = /** @type {import("./geom/Geometry.js").default} */ (opt_geometryOrProperties);
const geometry = /** @type {Geometry} */ (opt_geometryOrProperties);
this.setGeometry(geometry);
} else {
/** @type {Object<string, *>} */
@@ -140,13 +141,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 {import("./geom/Geometry.js").default|undefined} The default geometry for the feature.
* @return {Geometry|undefined} The default geometry for the feature.
* @api
* @observable
*/
getGeometry() {
return (
/** @type {import("./geom/Geometry.js").default|undefined} */ (this.get(this.geometryName_))
/** @type {Geometry|undefined} */ (this.get(this.geometryName_))
);
}
@@ -218,7 +219,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 {import("./geom/Geometry.js").default|undefined} geometry The new geometry.
* @param {Geometry|undefined} geometry The new geometry.
* @api
* @observable
*/

View File

@@ -39,10 +39,11 @@ 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
* @property {Array<DeclutterItems>} 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
@@ -54,6 +55,13 @@ 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
*/
@@ -1050,7 +1058,7 @@ class PluggableMap extends BaseObject {
if (!this.handleResize_) {
this.handleResize_ = this.updateSize.bind(this);
addEventListener(EventType.RESIZE, this.handleResize_, false);
window.addEventListener(EventType.RESIZE, this.handleResize_, false);
}
}
@@ -1224,13 +1232,14 @@ 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 = /** @type {FrameState} */ ({
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_,
@@ -1243,7 +1252,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';
import {easeOut} from './easing';
import {createMinMaxResolution} from './resolutionconstraint';
import {equals} from './coordinate.js';
import {easeOut} from './easing.js';
import {createMinMaxResolution} from './resolutionconstraint.js';
/**

View File

@@ -174,9 +174,8 @@ class Geometry extends BaseObject {
/**
* Create a simplified version of this geometry. For linestrings, this uses
* the the {@link
* https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
* Douglas Peucker} algorithm. For polygons, a quantization-based
* the [Douglas Peucker](https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm)
* 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} from '../events/condition.js';
import {noModifierKeys, primaryAction} 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}.
* Default is {@link module:ol/events/condition~noModifierKeys} and {@link module:ol/events/condition~primaryAction}.
* @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 : noModifierKeys;
this.condition_ = options.condition ? options.condition : defaultCondition;
/**
* @private
@@ -166,4 +166,12 @@ 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}
* @type {Feature<Point>}
* @private
*/
this.sketchPoint_ = null;
@@ -387,7 +387,7 @@ class Draw extends PointerInteraction {
/**
* Sketch line. Used when drawing polygon.
* @type {Feature}
* @type {Feature<LineString>}
* @private
*/
this.sketchLine_ = null;
@@ -669,7 +669,7 @@ class Draw extends PointerInteraction {
this.sketchPoint_ = new Feature(new Point(coordinates));
this.updateSketchFeatures_();
} else {
const sketchPointGeom = /** @type {Point} */ (this.sketchPoint_.getGeometry());
const sketchPointGeom = this.sketchPoint_.getGeometry();
sketchPointGeom.setCoordinates(coordinates);
}
}
@@ -711,7 +711,7 @@ class Draw extends PointerInteraction {
*/
modifyDrawing_(event) {
let coordinate = event.coordinate;
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
const geometry = 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 = /** @type {Point} */ (this.sketchPoint_.getGeometry());
const sketchPointGeom = 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 = /** @type {Polygon} */ (geometry).getLinearRing(0);
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
const ring = geometry.getLinearRing(0);
sketchLineGeom = 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 = /** @type {LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom = 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 = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
const geometry = 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 = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
const geometry = 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 = /** @type {LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom = 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 = /** @type {import("../geom/SimpleGeometry.js").default} */ (sketchFeature.getGeometry());
const geometry = 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} feature Feature to be extended.
* @param {!Feature<LineString>} feature Feature to be extended.
* @api
*/
extend(feature) {
const geometry = feature.getGeometry();
const lineString = /** @type {LineString} */ (geometry);
const 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}
* @type {Feature<Point>}
* @private
*/
this.vertexFeature_ = null;
@@ -265,7 +265,7 @@ class Extent extends PointerInteraction {
this.vertexFeature_ = vertexFeature;
this.vertexOverlay_.getSource().addFeature(vertexFeature);
} else {
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
const geometry = 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 = /** @type {Point} */ (vertexFeature.getGeometry());
const geometry = 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 = /** @type {Point} */ (vertexFeature.getGeometry());
const geometry = vertexFeature.getGeometry();
const vertex = geometry.getCoordinates();
const vertexExtent = boundingExtent([vertex]);
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);

View File

@@ -83,6 +83,9 @@ 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';
import Text from '../style/Text';
import Fill from '../style/Fill';
import Stroke from '../style/Stroke';
import {degreesToStringHDMS} from '../coordinate.js';
import Text from '../style/Text.js';
import Fill from '../style/Fill.js';
import Stroke from '../style/Stroke.js';
import LineString from '../geom/LineString.js';
import VectorSource from '../source/Vector';
import VectorSource from '../source/Vector.js';
import {
equivalent as equivalentProjection,
get as getProjection,
getTransform,
transformExtent
} 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';
} 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';
/**

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';
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer.js';
/**

View File

@@ -189,13 +189,15 @@ 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) {
render(frameState, target) {
const layerRenderer = this.getRenderer();
const layerState = this.getLayerState();
if (layerRenderer.prepareFrame(frameState, layerState)) {
return layerRenderer.renderFrame(frameState, layerState);
if (layerRenderer.prepareFrame(frameState)) {
return layerRenderer.renderFrame(frameState, target);
}
}

View File

@@ -122,9 +122,10 @@ export function renderDeclutterItems(frameState, declutterTree) {
}
const items = frameState.declutterItems;
for (let z = items.length - 1; z >= 0; --z) {
const zIndexItems = items[z];
const item = items[z];
const zIndexItems = item.items;
for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) {
declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], declutterTree);
declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], item.opacity, 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 (alpha) {
if (opacity != 1) {
context.globalAlpha = alpha;
}
if (transform) {

View File

@@ -362,10 +362,12 @@ 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 && fillStroke) {
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
if (declutterArgs) {
if (fillStroke) {
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
}
declutterGroup.push(declutterArgs);
}
declutterGroup.push(declutterArgs);
} else if (intersects) {
if (fillStroke) {
this.replayTextBackground_(context, p1, p2, p3, p4,
@@ -414,10 +416,11 @@ 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, declutterTree) {
renderDeclutter(declutterGroup, feature, opacity, declutterTree) {
if (declutterGroup && declutterGroup.length > 5) {
const groupCount = declutterGroup[4];
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
@@ -436,13 +439,19 @@ class Executor extends Disposable {
declutterTree.insert(box);
for (let j = 5, jj = declutterGroup.length; j < jj; ++j) {
const declutterData = /** @type {Array} */ (declutterGroup[j]);
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);
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;
}
}
}

View File

@@ -430,10 +430,11 @@ 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<Array<*>>} declutterItems Declutter items.
* @param {Array<import("../../PluggableMap.js").DeclutterItems>} declutterItems Declutter items.
*/
export function replayDeclutter(declutterReplays, context, rotation, snapToPixel, declutterItems) {
export function replayDeclutter(declutterReplays, context, rotation, opacity, snapToPixel, declutterItems) {
const zs = Object.keys(declutterReplays).map(Number).sort(numberSafeCompareFunction);
const skippedFeatureUids = {};
for (let z = 0, zz = zs.length; z < zz; ++z) {
@@ -443,7 +444,10 @@ export function replayDeclutter(declutterReplays, context, rotation, snapToPixel
const executor = executorData[i++];
if (executor !== currentExecutor) {
currentExecutor = executor;
declutterItems.push(executor.declutterItems);
declutterItems.push({
items: executor.declutterItems,
opacity: opacity
});
}
const transform = executorData[i++];
executor.execute(context, transform, rotation, skippedFeatureUids, snapToPixel);

View File

@@ -81,25 +81,26 @@ class CompositeMapRenderer extends MapRenderer {
this.calculateMatrices2D(frameState);
this.dispatchRenderEvent(RenderEventType.PRECOMPOSE, frameState);
const layerStatesArray = frameState.layerStatesArray;
const layerStatesArray = frameState.layerStatesArray.sort(function(a, b) {
return a.zIndex - b.zIndex;
});
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);
if (element) {
const zIndex = layerState.zIndex;
if (zIndex !== element.style.zIndex) {
element.style.zIndex = zIndex === Infinity ? Number.MAX_SAFE_INTEGER : zIndex;
}
const element = layer.render(frameState, previousElement);
if (element !== previousElement) {
this.children_.push(element);
previousElement = element;
}
}
super.renderFrame(frameState);

View File

@@ -29,10 +29,9 @@ 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, layerState) {
prepareFrame(frameState) {
return abstract();
}
@@ -40,10 +39,10 @@ class LayerRenderer extends Observable {
* Render the layer.
* @abstract
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
* @param {import("../layer/Layer.js").State} layerState Layer state.
* @param {HTMLElement} target Target that may be used to render content to.
* @return {HTMLElement} The rendered element.
*/
renderFrame(frameState, layerState) {
renderFrame(frameState, target) {
return abstract();
}

View File

@@ -38,7 +38,8 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState, layerState) {
prepareFrame(frameState) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
const pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const viewResolution = viewState.resolution;
@@ -72,11 +73,12 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState, layerState) {
renderFrame(frameState, target) {
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;
@@ -101,13 +103,15 @@ 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 {
} else if (!this.containerReused) {
context.clearRect(0, 0, width, height);
}
@@ -138,8 +142,17 @@ 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);
@@ -147,17 +160,12 @@ 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 canvas;
return this.container;
}

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} from '../../transform.js';
import {create as createTransform, apply as applyTransform, compose as composeTransform, toString as transformToString} from '../../transform.js';
/**
* @abstract
@@ -21,6 +21,12 @@ class CanvasLayerRenderer extends LayerRenderer {
super(layer);
/**
* @protected
* @type {HTMLElement}
*/
this.container = null;
/**
* @protected
* @type {number}
@@ -55,20 +61,57 @@ class CanvasLayerRenderer extends LayerRenderer {
* @protected
* @type {CanvasRenderingContext2D}
*/
this.context = createCanvasContext2D();
this.context = null;
/**
* @type {boolean}
*/
this.containerReused = false;
const canvas = this.context.canvas;
canvas.style.position = 'absolute';
canvas.style.transformOrigin = 'top left';
canvas.className = this.getLayer().getClassName();
}
/**
* @inheritDoc
* 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.
*/
disposeInternal() {
this.context.canvas.width = this.context.canvas.height = 0;
super.disposeInternal();
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;
}
}
/**

View File

@@ -125,7 +125,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState, layerState) {
prepareFrame(frameState) {
return true;
}
@@ -137,8 +137,8 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
* @inheritDoc
* @returns {HTMLElement} The rendered element.
*/
renderFrame(frameState, layerState) {
const context = this.context;
renderFrame(frameState, target) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
const viewState = frameState.viewState;
const projection = viewState.projection;
const viewResolution = viewState.resolution;
@@ -224,7 +224,6 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
}
const canvas = context.canvas;
const canvasScale = tileResolution / viewResolution;
// set forward and inverse pixel transforms
@@ -234,6 +233,11 @@ 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
@@ -247,7 +251,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
if (canvas.width != width || canvas.height != height) {
canvas.width = width;
canvas.height = height;
} else {
} else if (!this.containerReused) {
context.clearRect(0, 0, width, height);
}
@@ -259,7 +263,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
this.renderedTiles.length = 0;
/** @type {Array<number>} */
const zs = Object.keys(tilesToDrawByZ).map(Number);
let zs = Object.keys(tilesToDrawByZ).map(Number);
zs.sort(function(a, b) {
if (a === z) {
return 1;
@@ -270,7 +274,14 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
}
});
for (let i = 0, ii = zs.length; i < ii; ++i) {
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) {
const currentZ = zs[i];
const currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
const currentResolution = tileGrid.getResolution(currentZ);
@@ -298,8 +309,36 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const y = Math.round(floatY);
const w = nextX - x;
const h = nextY - y;
const transition = z === currentZ;
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, 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.renderedTiles.push(tile);
this.updateUsedTiles(frameState.usedTiles, tileSource, tile);
}
@@ -322,17 +361,12 @@ 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 canvas;
return this.container;
}
/**
@@ -344,19 +378,15 @@ 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) {
drawTileImage(tile, frameState, x, y, w, h, gutter, transition, opacity) {
const image = this.getTileImage(tile);
if (!image) {
return;
}
const uid = getUid(this);
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 alpha = opacity * (transition ? tile.getAlpha(uid, frameState.time) : 1);
const alphaChanged = alpha !== this.context.globalAlpha;
if (alphaChanged) {
this.context.save();

View File

@@ -63,7 +63,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState, layerState) {
prepareFrame(frameState) {
const pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const viewResolution = viewState.resolution;
@@ -78,6 +78,7 @@ 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: [],
@@ -91,10 +92,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, layerState) &&
if (vectorRenderer.prepareFrame(imageFrameState) &&
(vectorRenderer.replayGroupChanged ||
!equals(skippedFeatures, newSkippedFeatures))) {
vectorRenderer.renderFrame(imageFrameState, layerState);
vectorRenderer.renderFrame(imageFrameState, null);
renderDeclutterItems(imageFrameState, null);
skippedFeatures = newSkippedFeatures;
callback();

View File

@@ -70,24 +70,37 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState, layerState) {
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);
const context = this.context;
const canvas = context.canvas;
const replayGroup = this.replayGroup_;
if (!replayGroup || replayGroup.isEmpty()) {
if (canvas.width > 0) {
if (!this.containerReused && canvas.width > 0) {
canvas.width = 0;
}
return canvas;
return this.container;
}
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);
@@ -98,7 +111,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
if (canvas.style.transform !== canvasTransform) {
canvas.style.transform = canvasTransform;
}
} else {
} else if (!this.containerReused) {
context.clearRect(0, 0, width, height);
}
@@ -152,7 +165,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
if (declutterReplays) {
const viewHints = frameState.viewHints;
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems);
replayDeclutter(declutterReplays, context, rotation, 1, hifi, frameState.declutterItems);
}
if (clipped) {
@@ -162,11 +175,12 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
this.postRender(context, frameState);
const opacity = layerState.opacity;
if (opacity !== parseFloat(canvas.style.opacity)) {
canvas.style.opacity = opacity;
const container = this.container;
if (opacity !== parseFloat(container.style.opacity)) {
container.style.opacity = opacity === 1 ? '' : opacity;
}
return canvas;
return this.container;
}
/**
@@ -219,7 +233,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState, layerState) {
prepareFrame(frameState) {
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
const vectorSource = vectorLayer.getSource();

View File

@@ -24,7 +24,6 @@ import {
makeInverse
} from '../../transform.js';
import CanvasExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js';
import {clear, isEmpty} from '../../obj.js';
/**
@@ -59,32 +58,11 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
constructor(layer) {
super(layer);
const baseCanvas = this.context.canvas;
/**
* @private
* @type {CanvasRenderingContext2D}
*/
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;
this.overlayContext_ = null;
/**
* The transform for rendered pixels to viewport CSS pixels for the overlay canvas.
@@ -136,17 +114,43 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @inheritDoc
*/
disposeInternal() {
this.overlayContext_.canvas.width = this.overlayContext_.canvas.height = 0;
super.disposeInternal();
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);
}
}
/**
* @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) {
prepareTile(tile, pixelRatio, projection, queue) {
let render = false;
const tileUid = getUid(tile);
const state = tile.getState();
if (((state === TileState.LOADED && tile.hifi) ||
@@ -158,9 +162,13 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (state === TileState.LOADED || state === TileState.ERROR) {
this.updateExecutorGroup_(tile, pixelRatio, projection);
if (this.tileImageNeedsRender_(tile, pixelRatio, projection)) {
this.renderTileImageQueue_[tileUid] = tile;
render = true;
if (queue) {
this.renderTileImageQueue_[tileUid] = tile;
}
}
}
return render;
}
/**
@@ -176,7 +184,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));
const listenerKey = listen(tile, EventType.CHANGE, this.prepareTile.bind(this, tile, pixelRatio, projection, true));
this.tileListenerKeys_[tileUid] = listenerKey;
}
} else {
@@ -185,7 +193,10 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (hifi || !tile.wantedResolution) {
tile.wantedResolution = resolution;
}
this.prepareTile(tile, pixelRatio, projection);
const render = this.prepareTile(tile, pixelRatio, projection, false);
if (render) {
this.renderTileImage_(tile, frameState);
}
}
return tile;
}
@@ -207,13 +218,13 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @inheritDoc
*/
prepareFrame(frameState, layerState) {
prepareFrame(frameState) {
const layerRevision = this.getLayer().getRevision();
if (this.renderedLayerRevision_ != layerRevision) {
this.renderedTiles.length = 0;
}
this.renderedLayerRevision_ = layerRevision;
return super.prepareFrame(frameState, layerState);
return super.prepareFrame(frameState);
}
/**
@@ -379,26 +390,30 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState, layerState) {
super.renderFrame(frameState, layerState);
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
renderFrame(frameState, target) {
const viewHints = frameState.viewHints;
const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
this.renderQueuedTileImages_(hifi, frameState);
super.renderFrame(frameState, target);
const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer());
const renderMode = layer.getRenderMode();
if (renderMode === VectorTileRenderType.IMAGE) {
this.renderTileImages_(hifi, frameState);
return this.container_;
return this.container;
}
if (!isEmpty(this.renderTileImageQueue_) && !this.extentChanged) {
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];
}
}
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;
@@ -419,13 +434,14 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (canvas.style.transform !== canvasTransform) {
canvas.style.transform = canvasTransform;
}
} else {
} else if (!this.containerReused) {
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) {
@@ -436,6 +452,7 @@ 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)) {
@@ -443,9 +460,8 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
continue;
}
const currentZ = tile.tileCoord[0];
let zs, currentClip;
if (!declutterReplays) {
zs = [];
let currentClip;
if (!declutterReplays && !clipped) {
currentClip = executorGroup.getClipCoords(transform);
context.save();
@@ -453,7 +469,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 < zs[j]) {
if (currentZ < clipZs[j]) {
context.beginPath();
// counter-clockwise (outer ring) for current tile
context.moveTo(currentClip[0], currentClip[1]);
@@ -470,51 +486,38 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
}
}
executorGroup.execute(context, transform, rotation, {}, hifi, replayTypes, declutterReplays);
if (!declutterReplays) {
if (!declutterReplays && !clipped) {
context.restore();
clips.push(currentClip);
zs.push(currentZ);
clipZs.push(currentZ);
clipped = true;
}
}
}
if (declutterReplays) {
replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems);
const layerState = frameState.layerStatesArray[frameState.layerIndex];
replayDeclutter(declutterReplays, context, rotation, layerState.opacity, hifi, frameState.declutterItems);
}
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_;
return this.container;
}
/**
* @param {boolean} hifi We have time to render a high fidelity map image.
* @param {import('../../PluggableMap.js').FrameState} frameState Frame state.
*/
renderTileImages_(hifi, frameState) {
renderQueuedTileImages_(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];
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);
this.renderTileImage_(tile, frameState);
}
clear(this.renderTileImageQueue_);
}
/**
@@ -561,24 +564,29 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
/**
* @param {import("../../VectorRenderTile.js").default} tile Tile.
* @param {number} pixelRatio Pixel ratio.
* @param {number} renderPixelRatio Render pixel ratio.
* @param {import("../../proj/Projection.js").default} projection Projection.
* @param {import("../../PluggableMap").FrameState} frameState Frame state.
* @private
*/
renderTileImage_(tile, pixelRatio, renderPixelRatio, projection) {
renderTileImage_(tile, frameState) {
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';
import WebGLHelper from '../../webgl/Helper.js';
/**

View File

@@ -1,21 +1,21 @@
/**
* @module ol/renderer/webgl/PointsLayer
*/
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 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 {
create as createTransform,
makeInverse as makeInverseTransform,
multiply as multiplyTransform,
apply as applyTransform
} from '../../transform';
} from '../../transform.js';
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 = /** @type {import("../../geom/Point").default} */ (feature.getGeometry());
const geom = feature.getGeometry();
return geom.getCoordinates()[index];
};
this.opacityCallback_ = options.opacityCallback || function() {
@@ -284,7 +284,8 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
/**
* @inheritDoc
*/
renderFrame(frameState, layerState) {
renderFrame(frameState) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
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';
import {clamp} from './math';
import {getHeight, getWidth} from './extent.js';
import {clamp} from './math.js';
/**

View File

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

View File

@@ -75,6 +75,7 @@ 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 || [];
@@ -260,7 +261,7 @@ class IIIF extends TileImage {
return baseUrl + regionParam + '/' + sizeParam + '/0/' + quality + '.' + format;
};
const IiifTileClass = CustomTile.bind(null, tileGrid);
const IiifTileClass = CustomTile.bind(null, tilePixelRatio, 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';
import {Processor} from 'pixelworks/lib/index.js';
import {equals, getCenter, getHeight, getWidth} from '../extent.js';
import ImageLayer from '../layer/Image.js';
import TileLayer from '../layer/Tile.js';
@@ -214,6 +214,7 @@ class RasterSource extends ImageSource {
extent: null,
focus: null,
index: 0,
layerIndex: 0,
layerStatesArray: getLayerStatesArray(this.layers_),
pixelRatio: 1,
pixelToCoordinateTransform: createTransform(),
@@ -358,7 +359,8 @@ class RasterSource extends ImageSource {
const len = this.layers_.length;
const imageDatas = new Array(len);
for (let i = 0; i < len; ++i) {
const imageData = getImageData(this.layers_[i], frameState, frameState.layerStatesArray[i]);
frameState.layerIndex = i;
const imageData = getImageData(this.layers_[i], frameState);
if (imageData) {
imageDatas[i] = imageData;
} else {
@@ -430,21 +432,24 @@ 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, layerState) {
function getImageData(layer, frameState) {
const renderer = layer.getRenderer();
if (!renderer) {
throw new Error('Unsupported layer type: ' + layer);
}
if (!renderer.prepareFrame(frameState, layerState)) {
if (!renderer.prepareFrame(frameState)) {
return null;
}
const width = frameState.size[0];
const height = frameState.size[1];
const element = renderer.renderFrame(frameState, layerState);
const container = renderer.renderFrame(frameState, null);
let element;
if (container) {
element = container.firstElementChild;
}
if (!(element instanceof HTMLCanvasElement)) {
throw new Error('Unsupported rendered element: ' + element);
}

View File

@@ -35,12 +35,13 @@ 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=} opt_feature Feature.
* @param {import("../Feature.js").default<Geometry>=} opt_feature Feature.
*/
constructor(type, opt_feature) {
@@ -48,7 +49,7 @@ export class VectorSourceEvent extends Event {
/**
* The feature being added or removed.
* @type {import("../Feature.js").default|undefined}
* @type {import("../Feature.js").default<Geometry>|undefined}
* @api
*/
this.feature = opt_feature;
@@ -154,8 +155,9 @@ 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
* @fires VectorSourceEvent<Geometry>
* @api
* @template {import("../geom/Geometry.js").default} Geometry
*/
class VectorSource extends Source {
/**
@@ -215,7 +217,7 @@ class VectorSource extends Source {
/**
* @private
* @type {RBush<import("../Feature.js").default>}
* @type {RBush<import("../Feature.js").default<Geometry>>}
*/
this.featuresRtree_ = useSpatialIndex ? new RBush() : null;
@@ -227,21 +229,21 @@ class VectorSource extends Source {
/**
* @private
* @type {!Object<string, import("../Feature.js").default>}
* @type {!Object<string, import("../Feature.js").default<Geometry>>}
*/
this.nullGeometryFeatures_ = {};
/**
* A lookup of features by id (the return from feature.getId()).
* @private
* @type {!Object<string, import("../Feature.js").default>}
* @type {!Object<string, import("../Feature.js").default<Geometry>>}
*/
this.idIndex_ = {};
/**
* A lookup of features without id (keyed by getUid(feature)).
* @private
* @type {!Object<string, import("../Feature.js").default>}
* @type {!Object<string, import("../Feature.js").default<Geometry>>}
*/
this.undefIdIndex_ = {};
@@ -253,7 +255,7 @@ class VectorSource extends Source {
/**
* @private
* @type {Collection<import("../Feature.js").default>}
* @type {Collection<import("../Feature.js").default<Geometry>>}
*/
this.featuresCollection_ = null;
@@ -282,7 +284,10 @@ 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.
* @param {import("../Feature.js").default} feature Feature to add.
* 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.
* @api
*/
addFeature(feature) {
@@ -293,13 +298,16 @@ class VectorSource extends Source {
/**
* Add a feature without firing a `change` event.
* @param {import("../Feature.js").default} feature Feature.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @protected
*/
addFeatureInternal(feature) {
const featureKey = getUid(feature);
if (!this.addToIndex_(featureKey, feature)) {
if (this.featuresCollection_) {
this.featuresCollection_.remove(feature);
}
return;
}
@@ -322,7 +330,7 @@ class VectorSource extends Source {
/**
* @param {string} featureKey Unique identifier for the feature.
* @param {import("../Feature.js").default} feature The feature.
* @param {import("../Feature.js").default<Geometry>} feature The feature.
* @private
*/
setupChangeEvents_(featureKey, feature) {
@@ -337,7 +345,7 @@ class VectorSource extends Source {
/**
* @param {string} featureKey Unique identifier for the feature.
* @param {import("../Feature.js").default} feature The feature.
* @param {import("../Feature.js").default<Geometry>} feature The feature.
* @return {boolean} The feature is "valid", in the sense that it is also a
* candidate for insertion into the Rtree.
* @private
@@ -362,7 +370,7 @@ class VectorSource extends Source {
/**
* Add a batch of features to the source.
* @param {Array<import("../Feature.js").default>} features Features to add.
* @param {Array<import("../Feature.js").default<Geometry>>} features Features to add.
* @api
*/
addFeatures(features) {
@@ -373,7 +381,7 @@ class VectorSource extends Source {
/**
* Add features without firing a `change` event.
* @param {Array<import("../Feature.js").default>} features Features.
* @param {Array<import("../Feature.js").default<Geometry>>} features Features.
* @protected
*/
addFeaturesInternal(features) {
@@ -414,14 +422,14 @@ class VectorSource extends Source {
/**
* @param {!Collection<import("../Feature.js").default>} collection Collection.
* @param {!Collection<import("../Feature.js").default<Geometry>>} collection Collection.
* @private
*/
bindFeaturesCollection_(collection) {
let modifyingCollection = false;
listen(this, VectorEventType.ADDFEATURE,
/**
* @param {VectorSourceEvent} evt The vector source event
* @param {VectorSourceEvent<Geometry>} evt The vector source event
*/
function(evt) {
if (!modifyingCollection) {
@@ -432,7 +440,7 @@ class VectorSource extends Source {
});
listen(this, VectorEventType.REMOVEFEATURE,
/**
* @param {VectorSourceEvent} evt The vector source event
* @param {VectorSourceEvent<Geometry>} evt The vector source event
*/
function(evt) {
if (!modifyingCollection) {
@@ -448,7 +456,7 @@ class VectorSource extends Source {
function(evt) {
if (!modifyingCollection) {
modifyingCollection = true;
this.addFeature(/** @type {import("../Feature.js").default} */ (evt.element));
this.addFeature(/** @type {import("../Feature.js").default<Geometry>} */ (evt.element));
modifyingCollection = false;
}
}, this);
@@ -459,7 +467,7 @@ class VectorSource extends Source {
function(evt) {
if (!modifyingCollection) {
modifyingCollection = true;
this.removeFeature(/** @type {import("../Feature.js").default} */ (evt.element));
this.removeFeature(/** @type {import("../Feature.js").default<Geometry>} */ (evt.element));
modifyingCollection = false;
}
}, this);
@@ -512,7 +520,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): T} callback Called with each feature
* @param {function(import("../Feature.js").default<Geometry>): 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
@@ -534,7 +542,7 @@ class VectorSource extends Source {
* value.
*
* @param {import("../coordinate.js").Coordinate} coordinate Coordinate.
* @param {function(import("../Feature.js").default): T} callback Called with each feature
* @param {function(import("../Feature.js").default<Geometry>): 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
@@ -565,7 +573,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): T} callback Called with each feature
* @param {function(import("../Feature.js").default<Geometry>): 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
@@ -589,7 +597,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): T} callback Called with each feature
* @param {function(import("../Feature.js").default<Geometry>): 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
@@ -598,7 +606,7 @@ class VectorSource extends Source {
forEachFeatureIntersectingExtent(extent, callback) {
return this.forEachFeatureInExtent(extent,
/**
* @param {import("../Feature.js").default} feature Feature.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @return {T|undefined} The return value from the last call to the callback.
*/
function(feature) {
@@ -617,7 +625,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>} The collection of features.
* @return {Collection<import("../Feature.js").default<Geometry>>} The collection of features.
* @api
*/
getFeaturesCollection() {
@@ -627,7 +635,7 @@ class VectorSource extends Source {
/**
* Get all features on the source in random order.
* @return {Array<import("../Feature.js").default>} Features.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @api
*/
getFeatures() {
@@ -641,7 +649,7 @@ class VectorSource extends Source {
}
}
return (
/** @type {Array<import("../Feature.js").default>} */ (features)
/** @type {Array<import("../Feature.js").default<Geometry>>} */ (features)
);
}
@@ -649,7 +657,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>} Features.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @api
*/
getFeaturesAtCoordinate(coordinate) {
@@ -669,7 +677,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>} Features.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @api
*/
getFeaturesInExtent(extent) {
@@ -683,10 +691,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):boolean=} opt_filter Feature filter function.
* @param {function(import("../Feature.js").default<Geometry>):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} Closest feature.
* @return {import("../Feature.js").default<Geometry>} Closest feature.
* @api
*/
getClosestFeatureToCoordinate(coordinate, opt_filter) {
@@ -706,7 +714,7 @@ class VectorSource extends Source {
const filter = opt_filter ? opt_filter : TRUE;
this.featuresRtree_.forEachInExtent(extent,
/**
* @param {import("../Feature.js").default} feature Feature.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
*/
function(feature) {
if (filter(feature)) {
@@ -753,7 +761,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} The feature (or `null` if not found).
* @return {import("../Feature.js").default<Geometry>} The feature (or `null` if not found).
* @api
*/
getFeatureById(id) {
@@ -797,7 +805,7 @@ class VectorSource extends Source {
* @private
*/
handleFeatureChange_(event) {
const feature = /** @type {import("../Feature.js").default} */ (event.target);
const feature = /** @type {import("../Feature.js").default<Geometry>} */ (event.target);
const featureKey = getUid(feature);
const geometry = feature.getGeometry();
if (!geometry) {
@@ -845,7 +853,7 @@ class VectorSource extends Source {
/**
* Returns true if the feature is contained within the source.
* @param {import("../Feature.js").default} feature Feature.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @return {boolean} Has feature.
* @api
*/
@@ -927,7 +935,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} feature Feature to remove.
* @param {import("../Feature.js").default<Geometry>} feature Feature to remove.
* @api
*/
removeFeature(feature) {
@@ -946,7 +954,7 @@ class VectorSource extends Source {
/**
* Remove feature without firing a `change` event.
* @param {import("../Feature.js").default} feature Feature.
* @param {import("../Feature.js").default<Geometry>} feature Feature.
* @protected
*/
removeFeatureInternal(feature) {
@@ -967,7 +975,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} feature The feature.
* @param {import("../Feature.js").default<Geometry>} 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';
import {create, fromTransform} from '../vec/mat4';
import WebGLPostProcessingPass from './PostProcessingPass';
import {getContext} from '../webgl';
} from '../transform.js';
import {create, fromTransform} from '../vec/mat4.js';
import WebGLPostProcessingPass from './PostProcessingPass.js';
import {getContext} from '../webgl.js';
/**

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';
import {VERSION} from '../util.js';
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
npm publish --tag beta
}
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';
import Feature from '../../../src/ol/Feature.js';
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';
import {LineString, Point} from '../../../src/ol/geom.js';
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';
import LabelCache from '../../../../../src/ol/render/canvas/LabelCache.js';
describe('ol.render.canvas.LabelCache', function() {

View File

@@ -35,6 +35,8 @@ 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: [],
@@ -44,7 +46,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,13 +301,15 @@ 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, layer.getLayerState());
renderer.renderFrame(frameState, null);
}
expect(rendered).to.be(true);
});

View File

@@ -234,6 +234,8 @@ 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(),
@@ -247,13 +249,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, {});
renderer.renderFrame(frameState, null);
expect(replayState.renderedTileRevision).to.be(revision);
layer.changed();
renderer.renderFrame(frameState, {});
renderer.renderFrame(frameState, null);
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';
import WebGLArrayBuffer from '../../../../../src/ol/webgl/Buffer';
import Layer from '../../../../../src/ol/layer/Layer';
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';
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';
import {get as getProjection} from '../../../../../src/ol/proj';
import Polygon from '../../../../../src/ol/geom/Polygon';
import ViewHint from '../../../../../src/ol/ViewHint';
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';
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';
import {createMinMaxResolution} from '../../../src/ol/resolutionconstraint.js';
describe('ol.resolutionconstraint', function() {

View File

@@ -719,6 +719,19 @@ 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';
import WebGLArrayBuffer from '../../../../src/ol/webgl/Buffer.js';
describe('ol.webgl.Buffer', function() {

View File

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