Compare commits
1 Commits
site
...
v5.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
980ea4a977 |
9
.babelrc
Normal file
9
.babelrc
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"plugins": ["jsdoc-closure"],
|
||||
"parserOpts": {
|
||||
"parser": "recast"
|
||||
},
|
||||
"generatorOpts": {
|
||||
"generator": "recast"
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ Use one of the following methods to use OpenLayers in your project:
|
||||
|
||||
* If you just want to add a `<script>` tag to test things out, you can link directly to one of the full builds from [cdnjs](https://cdnjs.com/libraries/openlayers) (not recommended for production)
|
||||
|
||||
* For use with Closure Library (rare), install the [`openlayers` package](https://npmjs.com/package/openlayers) and read the [tutorial](http://openlayers.org/en/latest/doc/tutorials/closure.html).
|
||||
|
||||
## Supported Browsers
|
||||
|
||||
OpenLayers runs on all modern browsers that support [HTML5](https://html.spec.whatwg.org/multipage/) and [ECMAScript 5](http://www.ecma-international.org/ecma-262/5.1/). This includes Chrome, Firefox, Safari and Edge. For older browsers and platforms like Internet Explorer (down to version 9) and Android 4.x, [polyfills](http://polyfill.io) for `requestAnimationFrame` and `Element.prototype.classList` are required, and using the KML format requires a polyfill for `URL`.
|
||||
|
||||
@@ -2,14 +2,6 @@
|
||||
|
||||
### Next release
|
||||
|
||||
#### `transition` option of `ol/source/VectorTile` is ignored
|
||||
|
||||
The `transition` option to get an opacity transition to fade in tiles has been disabled for `ol/source/VectorTile`. Vector tiles are now always rendered without an opacity transition.
|
||||
|
||||
#### `ol/style/Fill` with `CanvasGradient` or `CanvasPattern`
|
||||
|
||||
The origin for gradients and patterns has changed from the top-left corner of the extent of the geometry being filled to 512 css pixel increments from map coordinate `[0, 0]`. This allows repeat patterns to be aligned properly with vector tiles. For seamless repeat patterns, width and height of the pattern image must be a factor of two (2, 4, 8, ..., 512).
|
||||
|
||||
#### Removal of the renderer option for maps
|
||||
|
||||
The `renderer` option has been removed from the `Map` constructor. The purpose of this change is to avoid bundling code in your application that you do not need. Previously, code for both the Canvas and WebGL renderers was included in all applications - even though most people only use one renderer. The `Map` constructor now gives you a Canvas (2D) based renderer. If you want to try the WebGL renderer, you can import the constructor from `ol/WebGLMap`.
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
{
|
||||
"opts": {
|
||||
"recurse": true,
|
||||
"template": "config/jsdoc/api/template"
|
||||
},
|
||||
"tags": {
|
||||
"allowUnknownTags": true
|
||||
},
|
||||
"source": {
|
||||
"includePattern": ".+\\.js(doc)?$",
|
||||
"excludePattern": "(^|\\/|\\\\)_",
|
||||
"include": [
|
||||
"src/ol"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"plugins/markdown",
|
||||
"config/jsdoc/api/plugins/normalize-exports",
|
||||
"config/jsdoc/api/plugins/inline-options",
|
||||
"config/jsdoc/api/plugins/events",
|
||||
"config/jsdoc/api/plugins/observable",
|
||||
"config/jsdoc/api/plugins/api"
|
||||
],
|
||||
"markdown": {
|
||||
"parser": "gfm"
|
||||
},
|
||||
"templates": {
|
||||
"cleverLinks": true,
|
||||
"monospaceLinks": true,
|
||||
"default": {
|
||||
"outputSourceFiles": false
|
||||
"opts": {
|
||||
"recurse": true,
|
||||
"template": "config/jsdoc/api/template"
|
||||
},
|
||||
"applicationName": "OpenLayers"
|
||||
},
|
||||
"jsVersion": 180
|
||||
"tags": {
|
||||
"allowUnknownTags": true
|
||||
},
|
||||
"source": {
|
||||
"includePattern": ".+\\.js(doc)?$",
|
||||
"excludePattern": "(^|\\/|\\\\)_",
|
||||
"include": [
|
||||
"src",
|
||||
"externs/oli.js"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"plugins/markdown",
|
||||
"config/jsdoc/api/plugins/inheritdoc",
|
||||
"config/jsdoc/api/plugins/typedefs",
|
||||
"config/jsdoc/api/plugins/events",
|
||||
"config/jsdoc/api/plugins/observable",
|
||||
"config/jsdoc/api/plugins/api"
|
||||
],
|
||||
"markdown": {
|
||||
"parser": "gfm"
|
||||
},
|
||||
"templates": {
|
||||
"cleverLinks": true,
|
||||
"monospaceLinks": true,
|
||||
"default": {
|
||||
"outputSourceFiles": false
|
||||
},
|
||||
"applicationName": "OpenLayers"
|
||||
},
|
||||
"jsVersion": 180
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
<table><tr>
|
||||
<th width="33.3%">Map</th><th width="33.3%">View</th><th width="33.3%">Layers</th>
|
||||
</tr><tr>
|
||||
<td><p>A [map](module-ol_Map-Map.html) is made of [layers](module-ol_layer_Base-BaseLayer.html), a [view](module-ol_View-View.html) to visualize them, [interactions](module-ol_interaction_Interaction-Interaction.html) to modify map content and [controls](module-ol_control_Control-Control.html) with UI components.</p>
|
||||
[Overview](module-ol_Map-Map.html)<br>
|
||||
[Creation](module-ol_Map-Map.html#Map)<br>
|
||||
[Events](module-ol_MapBrowserEvent-MapBrowserEvent.html)</td>
|
||||
<td><p>A [map](ol.Map.html) is made of [layers](ol.layer.html), a [view](ol.View.html) to visualize them, [interactions](ol.interaction.html) to modify map content and [controls](ol.control.html) with UI components.</p>
|
||||
[Overview](ol.Map.html)<br>
|
||||
[Creation](ol.Map.html#Map)<br>
|
||||
[Events](ol.MapBrowserEvent.html)</td>
|
||||
<td><p>The view manages the visual parameters of the map view, like resolution or rotation.</p>
|
||||
[View](module-ol_View-View.html) with center, projection, resolution and rotation</td>
|
||||
<td><p>Layers are lightweight containers that get their data from [sources](module-ol_source_Source-Source.html).</p>
|
||||
[layer/Tile](module-ol_layer_Tile-TileLayer.html)<br>
|
||||
[layer/Image](module-ol_layer_Image-ImageLayer.html)<br>
|
||||
[layer/Vector](module-ol_layer_Vector-VectorLayer.html)<br>
|
||||
[layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)</td>
|
||||
[ol.View](ol.View.html) with center, projection, resolution and rotation</td>
|
||||
<td><p>Layers are lightweight containers that get their data from [sources](ol.source.html).</p>
|
||||
[ol.layer.Tile](ol.layer.Tile.html)<br>
|
||||
[ol.layer.Image](ol.layer.Image.html)<br>
|
||||
[ol.layer.Vector](ol.layer.Vector.html)<br>
|
||||
[ol.layer.VectorTile](ol.layer.VectorTile.html)</td>
|
||||
</tr><tr>
|
||||
<th>Controls</th><th>Interactions</th><th>Sources and formats</th>
|
||||
</tr><tr>
|
||||
<td>[Map default controls](module-ol_control_util.html#.defaults)<br>
|
||||
[All controls](module-ol_control_Control-Control.html)
|
||||
<td>[Map default controls](ol.control.html#.defaults)<br>
|
||||
[All controls](ol.control.html)
|
||||
</td>
|
||||
<td>
|
||||
[Map default interactions](module-ol_interaction.html#~defaults)<br>
|
||||
Interactions for [vector features](module-ol_Feature-Feature.html)
|
||||
<ul><li>[interaction/Select](module-ol_interaction_Select-Select.html)</li>
|
||||
<li>[interaction/Draw](module-ol_interaction_Draw-Draw.html)</li>
|
||||
<li>[interaction/Modify](module-ol_interaction_Modify-Modify.html)</li></ul>
|
||||
[All interactions](module-ol_interaction_Interaction-Interaction.html)</td>
|
||||
<td>[Tile sources](module-ol_source_Tile-TileSource.html) for [layer/Tile](module-ol_layer_Tile-TileLayer.html)
|
||||
<br>[Image sources](module-ol_source_Image-ImageSource.html) for [layer/Image](module-ol_layer_Image-ImageLayer.html)
|
||||
<br>[Vector sources](module-ol_source_Vector-VectorSource.html) for [layer/Vector](module-ol_layer_Vector-VectorLayer.html)
|
||||
<br>[Vector tile sources](module-ol_source_VectorTile-VectorTile.html) for [layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)
|
||||
<br>[Formats](module-ol_format_Feature-FeatureFormat.html) for reading/writing vector data
|
||||
<br>[format/WMSCapabilities](module-ol_format_WMSCapabilities-WMSCapabilities.html)</td></tr>
|
||||
[Map default interactions](ol.interaction.html#.defaults)<br>
|
||||
Interactions for [vector features](ol.Feature.html)
|
||||
<ul><li>[ol.interaction.Select](ol.interaction.Select.html)</li>
|
||||
<li>[ol.interaction.Draw](ol.interaction.Draw.html)</li>
|
||||
<li>[ol.interaction.Modify](ol.interaction.Modify.html)</li></ul>
|
||||
[All interactions](ol.interaction.html)</td>
|
||||
<td>[Tile sources](ol.source.Tile.html) for [ol.layer.Tile](ol.layer.Tile.html)
|
||||
<br>[Image sources](ol.source.Image.html) for [ol.layer.Image](ol.layer.Image.html)
|
||||
<br>[Vector sources](ol.source.Vector.html) for [ol.layer.Vector](ol.layer.Vector.html)
|
||||
<br>[Vector tile sources](ol.source.VectorTile.html) for [ol.layer.VectorTile](ol.layer.VectorTile.html)
|
||||
<br>[Formats](ol.format.Feature.html) for reading/writing vector data
|
||||
<br>[ol.format.WMSCapabilities](ol.format.WMSCapabilities.html)</td></tr>
|
||||
<tr><th>Projections</th><th>Observable objects</th><th>Other components</th></tr>
|
||||
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [proj.transform()](module-ol_proj.html#.transform) and [proj.transformExtent()](module-ol_proj.html#.transformExtent).</p>
|
||||
[ol/proj](module-ol_proj.html)</td>
|
||||
<td><p>Changes to all [ol/Object](module-ol_Object-BaseObject.html)s can be observed by calling the [object.on('propertychange')](module-ol_Object-BaseObject.html#on) method. Listeners receive an [ol/Object~ObjectEvent](module-ol_Object-ObjectEvent.html) with information on the changed property and old value.</p>
|
||||
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [ol.proj.transform()](ol.proj.html#.transform) and [ol.proj.transformExtent()](ol.proj.html#.transformExtent).</p>
|
||||
[ol.proj](ol.proj.html)</td>
|
||||
<td><p>Changes to all [ol.Objects](ol.Object.html) can be observed by calling the [object.on('propertychange')](ol.Object.html#on) method. Listeners receive an [ol.Object.Event](ol.Object.Event.html) with information on the changed property and old value.</p>
|
||||
<td>
|
||||
[ol/Geolocation](module-ol_Geolocation.html)<br>
|
||||
[ol/Overlay](module-ol_Overlay-Overlay.html)<br></td>
|
||||
[ol.Geolocation](ol.Geolocation.html)<br>
|
||||
[ol.Overlay](ol.Overlay.html)<br></td>
|
||||
</tr></table>
|
||||
|
||||
|
||||
@@ -52,4 +52,11 @@ The OpenLayers API consists of
|
||||
|
||||
Within a major release series, the API will not be changed. Any changes to the API will be accompanied by a new major release.
|
||||
|
||||
*Note*: The API change policy does not cover CSS class names that are used to style the OpenLayers UI. It also does not cover any typedefs and enums.
|
||||
*Note*: The API change policy does not cover CSS class names that are used to style the
|
||||
OpenLayers UI.
|
||||
|
||||
*Note for Closure Compiler users compiling their application code together with OpenLayers*:
|
||||
The names of types other than those in the list above (e.g. `ol.Coordinate`) are subject to change. It
|
||||
is therefore recommended to either use the resolved type as listed in the API docs (e.g.
|
||||
`Array.<number>` instead of `ol.Coordinate`), or pay attention to the upgrade notes, which will list
|
||||
the changes for those types.
|
||||
|
||||
@@ -24,7 +24,6 @@ exports.defineTags = function(dictionary) {
|
||||
const api = [];
|
||||
const classes = {};
|
||||
const types = {};
|
||||
const modules = {};
|
||||
|
||||
function hasApiMembers(doclet) {
|
||||
return doclet.longname.split('#')[0] == this.longname;
|
||||
@@ -58,8 +57,10 @@ function includeAugments(doclet) {
|
||||
}
|
||||
});
|
||||
}
|
||||
cls._hideConstructor = true;
|
||||
delete cls.undocumented;
|
||||
if (cls.longname.indexOf('oli.') !== 0) {
|
||||
cls._hideConstructor = true;
|
||||
delete cls.undocumented;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,21 +70,20 @@ function extractTypes(item) {
|
||||
item.type.names.forEach(function(type) {
|
||||
const match = type.match(/^(.*<)?([^>]*)>?$/);
|
||||
if (match) {
|
||||
modules[match[2]] = true;
|
||||
types[match[2]] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function includeTypes(doclet) {
|
||||
if (doclet.params) {
|
||||
if (doclet.params && doclet.kind != 'class') {
|
||||
doclet.params.forEach(extractTypes);
|
||||
}
|
||||
if (doclet.returns) {
|
||||
doclet.returns.forEach(extractTypes);
|
||||
}
|
||||
if (doclet.properties) {
|
||||
doclet.properties.forEach(extractTypes);
|
||||
if (doclet.isEnum) {
|
||||
types[doclet.meta.code.name] = true;
|
||||
}
|
||||
if (doclet.type && doclet.meta.code.type == 'MemberExpression') {
|
||||
extractTypes(doclet);
|
||||
@@ -95,7 +95,6 @@ exports.handlers = {
|
||||
newDoclet: function(e) {
|
||||
const doclet = e.doclet;
|
||||
if (doclet.stability) {
|
||||
modules[doclet.longname.split('~').shift()] = true;
|
||||
api.push(doclet);
|
||||
}
|
||||
// Mark explicity defined namespaces - needed in parseComplete to keep
|
||||
@@ -104,7 +103,6 @@ exports.handlers = {
|
||||
doclet.namespace_ = true;
|
||||
}
|
||||
if (doclet.kind == 'class') {
|
||||
modules[doclet.longname.split('~').shift()] = true;
|
||||
classes[doclet.longname] = doclet;
|
||||
}
|
||||
},
|
||||
@@ -130,13 +128,6 @@ exports.handlers = {
|
||||
// Always document namespaces and items with stability annotation
|
||||
continue;
|
||||
}
|
||||
if (doclet.kind == 'module' && doclet.longname in modules) {
|
||||
// Document all modules that are referenced by the API
|
||||
continue;
|
||||
}
|
||||
if (doclet.isEnum || doclet.kind == 'typedef') {
|
||||
continue;
|
||||
}
|
||||
if (doclet.kind == 'class' && api.some(hasApiMembers, doclet)) {
|
||||
// Mark undocumented classes with documented members as unexported.
|
||||
// This is used in ../template/tmpl/container.tmpl to hide the
|
||||
|
||||
109
config/jsdoc/api/plugins/inheritdoc.js
Normal file
109
config/jsdoc/api/plugins/inheritdoc.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This is a hack to prevent inheritDoc tags from entirely removing
|
||||
* documentation of the method that inherits the documentation.
|
||||
*
|
||||
* TODO: Remove this hack when https://github.com/jsdoc3/jsdoc/issues/53
|
||||
* is addressed.
|
||||
*/
|
||||
|
||||
|
||||
exports.defineTags = function(dictionary) {
|
||||
dictionary.defineTag('inheritDoc', {
|
||||
mustHaveValue: false,
|
||||
canHaveType: false,
|
||||
canHaveName: false,
|
||||
onTagged: function(doclet, tag) {
|
||||
doclet.inheritdoc = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const lookup = {};
|
||||
const incompleteByClass = {};
|
||||
const keepKeys = ['comment', 'meta', 'name', 'memberof', 'longname', 'augment',
|
||||
'stability'];
|
||||
|
||||
exports.handlers = {
|
||||
|
||||
newDoclet: function(e) {
|
||||
const doclet = e.doclet;
|
||||
let incompletes;
|
||||
if (!(doclet.longname in lookup)) {
|
||||
lookup[doclet.longname] = [];
|
||||
}
|
||||
lookup[doclet.longname].push(doclet);
|
||||
if (doclet.inheritdoc) {
|
||||
if (!(doclet.memberof in incompleteByClass)) {
|
||||
incompleteByClass[doclet.memberof] = [];
|
||||
}
|
||||
incompletes = incompleteByClass[doclet.memberof];
|
||||
if (incompletes.indexOf(doclet.name) == -1) {
|
||||
incompletes.push(doclet.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
parseComplete: function(e) {
|
||||
let ancestors, candidate, candidates, doclet, i, j, k, l, key;
|
||||
let incompleteDoclet, stability, incomplete, incompletes;
|
||||
const doclets = e.doclets;
|
||||
for (i = doclets.length - 1; i >= 0; --i) {
|
||||
doclet = doclets[i];
|
||||
if (doclet.augments) {
|
||||
ancestors = [].concat(doclet.augments);
|
||||
}
|
||||
incompletes = incompleteByClass[doclet.longname];
|
||||
if (ancestors && incompletes) {
|
||||
// collect ancestors from the whole hierarchy
|
||||
for (j = 0; j < ancestors.length; ++j) {
|
||||
candidates = lookup[ancestors[j]];
|
||||
if (candidates) {
|
||||
for (k = candidates.length - 1; k >= 0; --k) {
|
||||
candidate = candidates[k];
|
||||
if (candidate.augments) {
|
||||
ancestors = ancestors.concat(candidate.augments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// walk through all inheritDoc members
|
||||
for (j = incompletes.length - 1; j >= 0; --j) {
|
||||
incomplete = incompletes[j];
|
||||
candidates = lookup[doclet.longname + '#' + incomplete];
|
||||
if (candidates) {
|
||||
// get the incomplete doclet that needs to be augmented
|
||||
for (k = candidates.length - 1; k >= 0; --k) {
|
||||
incompleteDoclet = candidates[k];
|
||||
if (incompleteDoclet.inheritdoc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// find the documented ancestor
|
||||
for (k = ancestors.length - 1; k >= 0; --k) {
|
||||
candidates = lookup[ancestors[k] + '#' + incomplete];
|
||||
if (candidates) {
|
||||
for (l = candidates.length - 1; l >= 0; --l) {
|
||||
candidate = candidates[l];
|
||||
if (candidate && !candidate.inheritdoc) {
|
||||
stability = candidate.stability || incompleteDoclet.stability;
|
||||
if (stability) {
|
||||
incompleteDoclet.stability = stability;
|
||||
for (key in candidate) {
|
||||
if (candidate.hasOwnProperty(key) &&
|
||||
keepKeys.indexOf(key) == -1) {
|
||||
incompleteDoclet[key] = candidate[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
/**
|
||||
* @filedesc
|
||||
* Inlines option params from typedefs
|
||||
*/
|
||||
|
||||
const properties = {};
|
||||
|
||||
exports.handlers = {
|
||||
|
||||
/**
|
||||
* Collects all typedefs, keyed by longname
|
||||
* @param {Object} e Event object.
|
||||
*/
|
||||
newDoclet: function(e) {
|
||||
if (e.doclet.kind == 'typedef' && e.doclet.properties) {
|
||||
properties[e.doclet.longname] = e.doclet.properties;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds `options.*` params for options that match the longname of one of the
|
||||
* collected typedefs.
|
||||
* @param {Object} e Event object.
|
||||
*/
|
||||
parseComplete: function(e) {
|
||||
const doclets = e.doclets;
|
||||
for (let i = 0, ii = doclets.length; i < ii; ++i) {
|
||||
const doclet = doclets[i];
|
||||
if (doclet.params) {
|
||||
const params = doclet.params;
|
||||
for (let j = 0, jj = params.length; j < jj; ++j) {
|
||||
const param = params[j];
|
||||
if (param.type && param.type.names) {
|
||||
const type = param.type.names[0];
|
||||
if (type in properties) {
|
||||
param.type.names[0] = type;
|
||||
params.push.apply(params, properties[type].map(p => {
|
||||
const property = Object.assign({}, p);
|
||||
property.name = `${param.name}.${property.name}`;
|
||||
return property;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,106 +0,0 @@
|
||||
/**
|
||||
* @filedesc
|
||||
* Expands module path type to point to default export when no name is given
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let moduleRoot;
|
||||
|
||||
function addDefaultExportPath(obj) {
|
||||
if (!Array.isArray(obj)) {
|
||||
obj = obj.names;
|
||||
}
|
||||
obj.forEach((name, index) => {
|
||||
const matches = name.match(/module\:([^>|),\.<]|)+/g);
|
||||
if (matches) {
|
||||
matches.forEach(module => {
|
||||
if (!/[~\.]/.test(module)) {
|
||||
const checkFile = path.resolve(moduleRoot, module.replace(/^module\:/, ''));
|
||||
const file = fs.readFileSync(require.resolve(checkFile), 'utf-8');
|
||||
const lines = file.split('\n');
|
||||
let hasDefaultExport = false;
|
||||
for (let i = 0, ii = lines.length; i < ii; ++i) {
|
||||
hasDefaultExport = hasDefaultExport || /^export default [^\{]/.test(lines[i]);
|
||||
const match = lines[i].match(/^export default ([A-Za-z_$][A-Za-z0-9_$]+);$/);
|
||||
if (match) {
|
||||
// Use variable name if default export is assigned to a variable.
|
||||
obj[index] = name = name.replace(module, `${module}~${match[1]}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (hasDefaultExport) {
|
||||
// Duplicate last part if default export is not assigned to a variable.
|
||||
obj[index] = name = name.replace(module, `${module}~${module.split('/').pop()}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function replaceLinks(comment) {
|
||||
const matches = comment.match(/\{@link [^\} #]+}/g);
|
||||
if (matches) {
|
||||
const modules = matches.map(m => {
|
||||
const mm = m.match(/(module:[^\}]+)}$/);
|
||||
if (mm) {
|
||||
return mm[1];
|
||||
}
|
||||
}).filter(m => !!m);
|
||||
const newModules = modules.concat();
|
||||
addDefaultExportPath(newModules);
|
||||
modules.forEach((module, i) => {
|
||||
comment = comment.replace(module, newModules[i]);
|
||||
});
|
||||
}
|
||||
return comment;
|
||||
}
|
||||
|
||||
exports.handlers = {
|
||||
|
||||
/**
|
||||
* Adds default export to module path types without name
|
||||
* @param {Object} e Event object.
|
||||
*/
|
||||
newDoclet: function(e) {
|
||||
const doclet = e.doclet;
|
||||
if (doclet.kind == 'module') {
|
||||
const levelsUp = doclet.longname.replace(/^module\:/, '').split('/');
|
||||
if (doclet.meta.filename != 'index.js') {
|
||||
levelsUp.pop();
|
||||
}
|
||||
const pathArgs = [doclet.meta.path].concat(levelsUp.map(() => '../'));
|
||||
moduleRoot = path.resolve.apply(null, pathArgs);
|
||||
} else {
|
||||
if (doclet.description) {
|
||||
doclet.description = replaceLinks(doclet.description);
|
||||
}
|
||||
if (doclet.classdesc) {
|
||||
doclet.classdesc = replaceLinks(doclet.classdesc);
|
||||
}
|
||||
|
||||
const module = doclet.longname.split('#').shift();
|
||||
if (module.indexOf('module:') == 0 && module.indexOf('.') !== -1) {
|
||||
doclet.longname = doclet.longname.replace(module, module.replace('.', '~'));
|
||||
}
|
||||
if (doclet.augments) {
|
||||
addDefaultExportPath(doclet.augments);
|
||||
}
|
||||
if (doclet.params) {
|
||||
doclet.params.forEach(p => addDefaultExportPath(p.type));
|
||||
}
|
||||
if (doclet.returns) {
|
||||
doclet.returns.forEach(r => addDefaultExportPath(r.type));
|
||||
}
|
||||
if (doclet.properties) {
|
||||
doclet.properties.forEach(p => addDefaultExportPath(p.type));
|
||||
}
|
||||
if (doclet.type) {
|
||||
addDefaultExportPath(doclet.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -47,7 +47,7 @@ exports.handlers = {
|
||||
if (!cls.fires) {
|
||||
cls.fires = [];
|
||||
}
|
||||
event = 'module:ol/Object~ObjectEvent#event:change:' + name;
|
||||
event = 'ol.Object.Event#event:change:' + name;
|
||||
if (cls.fires.indexOf(event) == -1) {
|
||||
cls.fires.push(event);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,21 @@ ol.MapBrowserEventType = {
|
||||
```
|
||||
Note the value of the `@event` annotation. The text before the hash refers to the event class that the event belongs to, and the text after the hash is the type of the event.
|
||||
|
||||
To export event properties, they need to be defined in `externs/oli.js` (also see `readme.md` in `externs/`) and marked with an @api annotation:
|
||||
```js
|
||||
/** @interface */
|
||||
oli.MapBrowserEvent;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
* @api
|
||||
*/
|
||||
oli.MapBrowserEvent.prototype.coordinate;
|
||||
|
||||
// ...
|
||||
|
||||
};
|
||||
```
|
||||
To document which events are fired by a class or method, the `@fires` annotation is used:
|
||||
```js
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
/*global env: true */
|
||||
|
||||
const hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
|
||||
// Work around an issue with hasOwnProperty in JSDoc's templateHelper.js.
|
||||
//TODO Fix in JSDoc.
|
||||
Object.prototype.hasOwnProperty = function(property) {
|
||||
return property in this;
|
||||
};
|
||||
|
||||
const template = require('jsdoc/lib/jsdoc/template');
|
||||
const fs = require('jsdoc/lib/jsdoc/fs');
|
||||
const path = require('jsdoc/lib/jsdoc/path');
|
||||
@@ -18,12 +9,9 @@ const _ = require('underscore');
|
||||
const htmlsafe = helper.htmlsafe;
|
||||
const linkto = helper.linkto;
|
||||
const resolveAuthorLinks = helper.resolveAuthorLinks;
|
||||
const hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
const outdir = env.opts.destination;
|
||||
|
||||
// Work around an issue with hasOwnProperty in JSDoc's templateHelper.js.
|
||||
//TODO Fix in JSDoc.
|
||||
Object.prototype.hasOwnProperty = hasOwnProp;
|
||||
|
||||
let view;
|
||||
let data;
|
||||
|
||||
@@ -204,7 +192,7 @@ function attachModuleSymbols(doclets, modules) {
|
||||
function buildNav(members) {
|
||||
const nav = [];
|
||||
// merge namespaces and classes, then sort
|
||||
const merged = members.modules.concat(members.classes);
|
||||
const merged = members.namespaces.concat(members.classes);
|
||||
merged.sort(function(a, b) {
|
||||
if (a.longname > b.longname) {
|
||||
return 1;
|
||||
@@ -217,9 +205,9 @@ function buildNav(members) {
|
||||
_.each(merged, function(v) {
|
||||
// exclude interfaces from sidebar
|
||||
if (v.interface !== true) {
|
||||
if (v.kind == 'module') {
|
||||
if (v.kind == 'namespace') {
|
||||
nav.push({
|
||||
type: 'module',
|
||||
type: 'namespace',
|
||||
longname: v.longname,
|
||||
name: v.name,
|
||||
members: find({
|
||||
|
||||
@@ -85,7 +85,7 @@ $(function () {
|
||||
var srcLinks = $('div.tag-source');
|
||||
srcLinks.each(function(i, el) {
|
||||
var textParts = el.innerHTML.trim().split(', ');
|
||||
var link = 'https://github.com/openlayers/openlayers/blob/v' + currentVersion + '/src/ol/' +
|
||||
var link = 'https://github.com/openlayers/openlayers/blob/v' + currentVersion + '/' +
|
||||
textParts[0];
|
||||
el.innerHTML = '<a href="' + link + '">' + textParts[0] + '</a>, ' +
|
||||
'<a href="' + link + textParts[1].replace('line ', '#L') + '">' +
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
<br>
|
||||
<?js if (doc.stability || doc.kind == 'namespace') {
|
||||
var ancestors = doc.ancestors.map(a => a.replace(/>\./g, '>').replace(/\.</g, '<')).join('/');
|
||||
var name = doc.name.toLowerCase();
|
||||
var parts = [];
|
||||
if (ancestors) {
|
||||
parts.push(ancestors.split('~').shift());
|
||||
parts.push(ancestors);
|
||||
}
|
||||
parts.push(name);
|
||||
var importPath = parts.join('/');
|
||||
?>
|
||||
<pre class="prettyprint source"><code>import <?js= doc.name ?> from '<?js= importPath ?>';</code></pre>
|
||||
|
||||
@@ -11,7 +11,7 @@ var self = this;
|
||||
?>
|
||||
<li class="item" data-name="<?js= item.longname ?>">
|
||||
<span class="title">
|
||||
<?js= self.linkto(item.longname, item.longname.replace('module:', '')) ?>
|
||||
<?js= self.linkto(item.longname, item.longname) ?>
|
||||
<?js if (item.type === 'namespace' &&
|
||||
(item.members.length + item.typedefs.length + item.methods.length +
|
||||
item.events.length > 0)) { ?>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Settable</th>
|
||||
<th><a href="module-ol_Object-ObjectEvent.html">ol/Object~ObjectEvent</a> type</th>
|
||||
<th><a href="ol.Object.Event.html">ol.Object.Event</a> type</th>
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
},
|
||||
"plugins": [
|
||||
"config/jsdoc/info/api-plugin",
|
||||
"config/jsdoc/info/module-plugin"
|
||||
"config/jsdoc/info/define-plugin",
|
||||
"config/jsdoc/info/virtual-plugin"
|
||||
]
|
||||
}
|
||||
|
||||
35
config/jsdoc/info/define-plugin.js
Normal file
35
config/jsdoc/info/define-plugin.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @fileoverview This plugin extracts info from boolean defines. This only
|
||||
* handles boolean defines with the default value in the description. Default
|
||||
* is assumed to be provided with something like "default is `true`" (case
|
||||
* insensitive, with or without ticks).
|
||||
*/
|
||||
|
||||
|
||||
const DEFAULT_VALUE = /default\s+is\s+`?(true|false)`?/i;
|
||||
|
||||
|
||||
/**
|
||||
* Hook to define new tags.
|
||||
* @param {Object} dictionary The tag dictionary.
|
||||
*/
|
||||
exports.defineTags = function(dictionary) {
|
||||
|
||||
dictionary.defineTag('define', {
|
||||
canHaveType: true,
|
||||
mustHaveValue: true,
|
||||
onTagged: function(doclet, tag) {
|
||||
const types = tag.value.type.names;
|
||||
if (types.length === 1 && types[0] === 'boolean') {
|
||||
const match = tag.value.description.match(DEFAULT_VALUE);
|
||||
if (match) {
|
||||
doclet.define = {
|
||||
default: match[1] === 'true'
|
||||
};
|
||||
doclet.description = tag.value.description;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
@@ -1,135 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
const exportLookup = {};
|
||||
const moduleLookup = {};
|
||||
|
||||
const MODULE_PATH = /^module:(.*)~(\w+)$/;
|
||||
|
||||
/**
|
||||
* Add exports to modules.
|
||||
*/
|
||||
exports.handlers = {
|
||||
|
||||
symbolFound(event) {
|
||||
const filename = event.filename;
|
||||
const node = event.astnode;
|
||||
let local, exported;
|
||||
switch (node.type) {
|
||||
|
||||
case 'ExportDefaultDeclaration': {
|
||||
exported = 'default';
|
||||
|
||||
switch (node.declaration.type) {
|
||||
|
||||
case 'Identifier': {
|
||||
// export default foo;
|
||||
local = node.declaration.name;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'FunctionDeclaration': {
|
||||
if (!node.declaration.id) {
|
||||
// export default function() {}
|
||||
local = '';
|
||||
} else {
|
||||
// export default function foo() {}
|
||||
local = node.declaration.id.name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
local = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'ExportNamedDeclaration': {
|
||||
if (!node.declaration) {
|
||||
// export {foo}
|
||||
// export {foo as bar}
|
||||
// handled below in ExportSpecifier
|
||||
return;
|
||||
}
|
||||
|
||||
switch (node.declaration.type) {
|
||||
case 'FunctionDeclaration': {
|
||||
if (!node.declaration.id) {
|
||||
throw new Error(`Expected function declaration to have an id in ${filename}`);
|
||||
}
|
||||
const name = node.declaration.id.name;
|
||||
local = name;
|
||||
exported = name;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'ExportSpecifier': {
|
||||
if (node.exported.type === 'Identifier') {
|
||||
exported = node.exported.name;
|
||||
if (node.local.type === 'Identifier') {
|
||||
local = node.local.name;
|
||||
if (node.parent.source) {
|
||||
const resolved = path.resolve(path.dirname(filename), node.parent.source.value);
|
||||
local = `module:${resolved}~${local}`;
|
||||
}
|
||||
} else {
|
||||
local = '';
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!(filename in exportLookup)) {
|
||||
exportLookup[filename] = {};
|
||||
}
|
||||
const exports = exportLookup[filename];
|
||||
if (exports.hasOwnProperty(exported)) {
|
||||
throw new Error(`Duplicate export {${local} as ${exported}} in ${filename}`);
|
||||
}
|
||||
exports[exported] = local;
|
||||
},
|
||||
|
||||
newDoclet(event) {
|
||||
const doclet = event.doclet;
|
||||
if (doclet.kind === 'module') {
|
||||
const filepath = path.join(doclet.meta.path, doclet.meta.filename);
|
||||
if (filepath in moduleLookup) {
|
||||
throw new Error(`Duplicate @module annotation in ${filepath}`);
|
||||
}
|
||||
moduleLookup[filepath] = doclet;
|
||||
}
|
||||
},
|
||||
|
||||
parseComplete(event) {
|
||||
for (const filepath in moduleLookup) {
|
||||
const doclet = moduleLookup[filepath];
|
||||
const exports = exportLookup[filepath];
|
||||
for (const exported in exports) {
|
||||
const local = exports[exported];
|
||||
const match = local.match(MODULE_PATH);
|
||||
if (match) {
|
||||
const filepath = match[1];
|
||||
const mod = moduleLookup[filepath];
|
||||
if (mod) {
|
||||
exports[exported] = `module:${mod.name}~${match[2]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
doclet.exports = exports; // undefined if no exports
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @fileoverview Generates JSON output based on exportable symbols.
|
||||
* @fileoverview Generates JSON output based on exportable symbols (those with
|
||||
* an api tag) and boolean defines (with a define tag and a default value).
|
||||
*/
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
@@ -21,7 +22,7 @@ exports.publish = function(data, opts) {
|
||||
return types;
|
||||
}
|
||||
|
||||
// get all doclets with the "api" property
|
||||
// get all doclets with the "api" property or define (excluding events)
|
||||
const classes = {};
|
||||
const docs = data(
|
||||
[
|
||||
@@ -33,7 +34,7 @@ exports.publish = function(data, opts) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (this.kind === 'module' || typeof this.api == 'boolean' ||
|
||||
return (typeof this.api == 'boolean' ||
|
||||
this.meta && (/[\\\/]externs$/).test(this.meta.path));
|
||||
}
|
||||
],
|
||||
@@ -42,9 +43,9 @@ exports.publish = function(data, opts) {
|
||||
|
||||
// get symbols data, filter out those that are members of private classes
|
||||
const symbols = [];
|
||||
const defines = [];
|
||||
const typedefs = [];
|
||||
const externs = [];
|
||||
const modules = [];
|
||||
let base = [];
|
||||
const augments = {};
|
||||
const symbolsByName = {};
|
||||
@@ -58,11 +59,13 @@ exports.publish = function(data, opts) {
|
||||
}
|
||||
return include;
|
||||
}).forEach(function(doc) {
|
||||
if (doc.kind == 'module') {
|
||||
modules.push({
|
||||
const isExterns = (/[\\\/]externs$/).test(doc.meta.path);
|
||||
if (doc.define) {
|
||||
defines.push({
|
||||
name: doc.longname,
|
||||
exports: doc.exports || null,
|
||||
path: path.join(doc.meta.path, doc.meta.filename)
|
||||
description: doc.description,
|
||||
path: path.join(doc.meta.path, doc.meta.filename),
|
||||
default: doc.define.default
|
||||
});
|
||||
} else if (doc.kind == 'typedef' || doc.isEnum === true) {
|
||||
typedefs.push({
|
||||
@@ -79,9 +82,6 @@ exports.publish = function(data, opts) {
|
||||
if (doc.augments) {
|
||||
symbol.extends = doc.augments[0];
|
||||
}
|
||||
if (doc.memberof) {
|
||||
symbol.memberof = doc.memberof;
|
||||
}
|
||||
if (doc.virtual) {
|
||||
symbol.virtual = true;
|
||||
}
|
||||
@@ -92,8 +92,7 @@ exports.publish = function(data, opts) {
|
||||
const params = [];
|
||||
doc.params.forEach(function(param) {
|
||||
const paramInfo = {
|
||||
name: param.name,
|
||||
description: param.description
|
||||
name: param.name
|
||||
};
|
||||
params.push(paramInfo);
|
||||
paramInfo.types = getTypes(param.type.names);
|
||||
@@ -127,7 +126,7 @@ exports.publish = function(data, opts) {
|
||||
});
|
||||
}
|
||||
|
||||
const target = doc.api ? symbols : base;
|
||||
const target = isExterns ? externs : (doc.api ? symbols : base);
|
||||
const existingSymbol = symbolsByName[symbol.name];
|
||||
if (existingSymbol) {
|
||||
const idx = target.indexOf(existingSymbol);
|
||||
@@ -156,10 +155,10 @@ exports.publish = function(data, opts) {
|
||||
process.stdout.write(
|
||||
JSON.stringify({
|
||||
symbols: symbols,
|
||||
defines: defines,
|
||||
typedefs: typedefs,
|
||||
externs: externs,
|
||||
base: base,
|
||||
modules: modules
|
||||
base: base
|
||||
}, null, 2));
|
||||
});
|
||||
|
||||
|
||||
16
config/jsdoc/info/virtual-plugin.js
Normal file
16
config/jsdoc/info/virtual-plugin.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Handle the interface and abstract annotations.
|
||||
* @param {Object} dictionary The tag dictionary.
|
||||
*/
|
||||
exports.defineTags = function(dictionary) {
|
||||
|
||||
const classTag = dictionary.lookUp('class');
|
||||
dictionary.defineTag('interface', {
|
||||
mustHaveValue: false,
|
||||
onTagged: function(doclet, tag) {
|
||||
classTag.onTagged.apply(this, arguments);
|
||||
doclet.virtual = true;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
// Rollup configuration for the full build
|
||||
|
||||
import noderesolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import {uglify} from 'rollup-plugin-uglify';
|
||||
import buble from 'rollup-plugin-buble';
|
||||
import sourcemaps from 'rollup-plugin-sourcemaps';
|
||||
|
||||
export default {
|
||||
input: 'src/index.js',
|
||||
output: [
|
||||
{file: 'build/ol.js', format: 'iife', sourcemap: true}
|
||||
],
|
||||
plugins: [
|
||||
noderesolve(),
|
||||
commonjs(),
|
||||
buble(),
|
||||
uglify(),
|
||||
sourcemaps()
|
||||
]
|
||||
};
|
||||
14
config/webpack.js
Normal file
14
config/webpack.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const webpack = require('webpack');
|
||||
const MinifyPlugin = require('babel-minify-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
filename: 'build/ol.js'
|
||||
},
|
||||
devtool: 'source-map',
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
new MinifyPlugin()
|
||||
]
|
||||
};
|
||||
37
doc/faq.md
37
doc/faq.md
@@ -21,6 +21,9 @@ Table of contents:
|
||||
* [Why aren't there any features in my source?](#why-aren-t-there-any-features-in-my-source-)
|
||||
* [How do I force a re-render of the map?](#how-do-i-force-a-re-render-of-the-map-)
|
||||
* [Why are my features not found?](#why-are-my-features-not-found-)
|
||||
* [How do I create a custom build of OpenLayers?](#how-do-i-create-a-custom-build-of-openlayers-)
|
||||
* [Do I need to write my own code using Closure library?](#do-i-need-to-write-my-own-code-using-closure-library-)
|
||||
* [Do I need to compress my code with Closure compiler?](#do-i-need-to-compress-my-code-with-closure-compiler-)
|
||||
|
||||
|
||||
## What projection is OpenLayers using?
|
||||
@@ -332,3 +335,37 @@ var vectorLayer = new ol.layer.Vector({
|
||||
```
|
||||
|
||||
The recommended value is the size of the largest symbol, line width or label.
|
||||
|
||||
## How do I create a custom build of OpenLayers?
|
||||
|
||||
Please refer to the [official create custom builds tutorial](tutorials/custom-builds.html)
|
||||
which explains how to create a custom build of OpenLayers with just those parts
|
||||
included that you want.
|
||||
|
||||
|
||||
## Do I need to write my own code using Closure library?
|
||||
|
||||
OpenLayers is built on top of the [Google Closure JavaScript
|
||||
library](https://developers.google.com/closure/library/), but this
|
||||
does not mean that you must use that library in your application code.
|
||||
|
||||
OpenLayers should play well with all sorts of JavaScript libraries out there,
|
||||
and you are in no way forced to use a specific one. Choose one that looks
|
||||
right for you.
|
||||
|
||||
|
||||
## Do I need to compress my code with Closure compiler?
|
||||
|
||||
No, you don't need to do compress your code with the [Google Closure
|
||||
compiler](https://developers.google.com/closure/compiler/).
|
||||
|
||||
It may be a good choice though, because when your application code and the
|
||||
OpenLayers source code is compiled together using closure compiler, the
|
||||
resulting build will most probably be the smallest in terms of byte-size. For
|
||||
more details refer to the
|
||||
[compile application and OpenLayers together tutorial](tutorials/closure.html).
|
||||
|
||||
If you don't want to use the closure compiler, or you can't, you are not at all
|
||||
forced to use it.
|
||||
|
||||
|
||||
|
||||
301
doc/tutorials/closure.md
Normal file
301
doc/tutorials/closure.md
Normal file
@@ -0,0 +1,301 @@
|
||||
---
|
||||
title: Compiling Application with Closure Compiler
|
||||
layout: doc.hbs
|
||||
---
|
||||
|
||||
# Compiling Application with Closure Compiler
|
||||
|
||||
**Note**: When building an application with dependencies that are available as [npm](https://npmjs.com/) packages, it will probably be easier to use the [ol](https://npmjs.com/package/ol) package and follow the instructions there.
|
||||
|
||||
The OpenLayers code uses the Closure Library, and it is compiled with the
|
||||
Closure Compiler. Using OpenLayers in an application does not require using
|
||||
Closure. But using Closure in an OpenLayers application is possible. And this
|
||||
is what this tutorial is about.
|
||||
|
||||
When you want to include OpenLayers as separate script without bundling with your application, follow the [Creating custom builds](./custom-builds.html) tutorial instead.
|
||||
|
||||
This tutorial will teach you how to set up an OpenLayers application based on
|
||||
the [`closure-util`](https://github.com/openlayers/closure-util) node package,
|
||||
which provides utilities for working with Closure. Using `closure-util` is one
|
||||
way to use Closure in a web application, but there are others. This tutorial
|
||||
just covers the "`closure-util`" way.
|
||||
|
||||
The `closure-util` documentation is available on the [`closure-util` readme
|
||||
page](https://github.com/openlayers/closure-util/blob/master/readme.md). You
|
||||
don't need to read the `closure-util` documentation to follow this tutorial,
|
||||
but it's available in `closure-util`'s [readme
|
||||
file](https://github.com/openlayers/closure-util/blob/master/readme.md) if you
|
||||
need it.
|
||||
|
||||
Also, the sample application built in this tutorial is
|
||||
[available](https://github.com/openlayers/openlayers-closure-application) on
|
||||
GitHub.
|
||||
|
||||
## Advantages of using Closure
|
||||
|
||||
This tutorial will show you how to use the Closure Compiler to compile an
|
||||
application and OpenLayers together. Compiling the application code together
|
||||
with the OpenLayers code has a number of advantages.
|
||||
|
||||
First of all, it allows you to only "pay" for the OpenLayers code your
|
||||
application uses, as the compiler will exclude the OpenLayers code that the
|
||||
application doesn't use. And there is no need to write and maintain a list of
|
||||
"exports", which is necessary when creating custom builds of OpenLayers.
|
||||
|
||||
Also, compiling the application and OpenLayers together allows using
|
||||
OpenLayers functions and objects that are not part of the official OpenLayers
|
||||
3 API. Using non-API functions and objects may be risky, but it is mitigated by
|
||||
the fact that the compiler will complain if you use functions or objects
|
||||
that are not in OpenLayers anymore.
|
||||
|
||||
## Setting up the Application
|
||||
|
||||
First, create a directory for the application. We will name that directory
|
||||
`openlayers-closure-application` in this tutorial.
|
||||
|
||||
$ mkdir openlayers-closure-application
|
||||
|
||||
Now change to that directory:
|
||||
|
||||
$ cd openlayers-closure-application
|
||||
|
||||
Our application will be a `node` application, and the `openlayers` and
|
||||
`closure-util` node packages will be downloaded from the node package registry
|
||||
using the `npm` command line tool.
|
||||
|
||||
So we're going to create a `package.json` file for the application, which every
|
||||
node application includes. This file basically includes metadata for the
|
||||
application.
|
||||
|
||||
Create the application's `package.json` file:
|
||||
|
||||
$ npm init
|
||||
|
||||
You can pretty much use the default answers to the questions `npm init` asks
|
||||
you.
|
||||
|
||||
Now install OpenLayers using:
|
||||
|
||||
$ npm install openlayers --save
|
||||
|
||||
The `--save` flag persists the `openlayers` dependency in the application's
|
||||
`package.json` file. You can edit `package.json` to verify that the dependency
|
||||
was added.
|
||||
|
||||
`closure-util` is a dependency of the `openlayers` package, so it should have
|
||||
been installed with `openlayers`. Use the following to verify that
|
||||
`closure-util` is installed:
|
||||
|
||||
$ ./node_modules/openlayers/node_modules/.bin/closure-util
|
||||
|
||||
command argument is required
|
||||
|
||||
Usage: node closure-util <command> [options]
|
||||
|
||||
command
|
||||
update-compiler Update the Compiler
|
||||
update-library Update the Library
|
||||
update Update both the Library and the Compiler
|
||||
build Build with Closure Compiler
|
||||
serve Start the development server
|
||||
|
||||
Options:
|
||||
-l LEVEL, --loglevel LEVEL Log level [info]
|
||||
|
||||
|
||||
## Create an OpenLayers map
|
||||
|
||||
You're now going to create a JavaScript file that creates an OpenLayers map.
|
||||
This is the file that we will define the application's entry point.
|
||||
|
||||
First of all create an `src` directory at the root of the application:
|
||||
|
||||
$ mkdir src
|
||||
|
||||
Now add a file `main.js` to `src`, with the following content:
|
||||
|
||||
```js
|
||||
goog.provide('app');
|
||||
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.source.OSM');
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.PluggableMap}
|
||||
*/
|
||||
app.map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
})
|
||||
],
|
||||
view: new ol.View({
|
||||
center: [0, 0],
|
||||
zoom: 4
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
`goog.provide('app')` creates the namespace `app` for the application. The
|
||||
`goog.require` statements that follow define the OpenLayers constructors and
|
||||
namespaces that the application uses. The rest of the code just creates the
|
||||
OpenLayers map as you would do in any OpenLayers application.
|
||||
|
||||
## Compiling the Application
|
||||
|
||||
We're now going to compile the application and OpenLayers together, using the
|
||||
Closure Compiler and `closure-util`. For this we need to create a JSON config
|
||||
file, that we will then pass as an input file to the `closure-util` command.
|
||||
|
||||
The minimum config file looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"lib": [
|
||||
"node_modules/openlayers/src/**/*.js",
|
||||
"node_modules/openlayers/build/ol.ext/**/*.js",
|
||||
"src/**/*.js"
|
||||
],
|
||||
"compile": {
|
||||
"closure_entry_point": "app",
|
||||
"externs": [
|
||||
"node_modules/openlayers/externs/bingmaps.js",
|
||||
"node_modules/openlayers/externs/cartodb.js",
|
||||
"node_modules/openlayers/externs/closure-compiler.js",
|
||||
"node_modules/openlayers/externs/esrijson.js",
|
||||
"node_modules/openlayers/externs/geojson.js",
|
||||
"node_modules/openlayers/externs/proj4js.js",
|
||||
"node_modules/openlayers/externs/tilejson.js",
|
||||
"node_modules/openlayers/externs/topojson.js"
|
||||
],
|
||||
"define": [
|
||||
"ol.ENABLE_WEBGL=false"
|
||||
],
|
||||
"js": [
|
||||
"node_modules/openlayers/externs/oli.js"
|
||||
],
|
||||
"extra_annotation_name": [
|
||||
"api", "observable"
|
||||
],
|
||||
"rewrite_polyfills": "false",
|
||||
"compilation_level": "ADVANCED",
|
||||
"warning_level": "VERBOSE",
|
||||
"output_wrapper": "(function(){%output%})();",
|
||||
"use_types_for_optimization": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Create a `config.json` file with the above content at the root of the
|
||||
application directory.
|
||||
|
||||
We can now use `closure-util` to compile the code:
|
||||
|
||||
$ ./node_modules/openlayers/node_modules/.bin/closure-util build config.json app.js
|
||||
|
||||
The resulting `app.js` file, which you can view in your editor if you're
|
||||
curious, includes a minified version of the application code (`main.js`), and
|
||||
the OpenLayers code that the application code uses.
|
||||
|
||||
Here is a version of `config.json` with more compilation checks enabled:
|
||||
|
||||
```json
|
||||
{
|
||||
"lib": [
|
||||
"node_modules/openlayers/src/**/*.js",
|
||||
"node_modules/openlayers/build/ol.ext/**/*.js",
|
||||
"src/**/*.js"
|
||||
],
|
||||
"compile": {
|
||||
"closure_entry_point": "app",
|
||||
"externs": [
|
||||
"node_modules/openlayers/externs/bingmaps.js",
|
||||
"node_modules/openlayers/externs/cartodb.js",
|
||||
"node_modules/openlayers/externs/closure-compiler.js",
|
||||
"node_modules/openlayers/externs/esrijson.js",
|
||||
"node_modules/openlayers/externs/geojson.js",
|
||||
"node_modules/openlayers/externs/proj4js.js",
|
||||
"node_modules/openlayers/externs/tilejson.js",
|
||||
"node_modules/openlayers/externs/topojson.js"
|
||||
],
|
||||
"define": [
|
||||
"ol.ENABLE_WEBGL=false"
|
||||
],
|
||||
"js": [
|
||||
"node_modules/openlayers/externs/oli.js"
|
||||
],
|
||||
"jscomp_error": [
|
||||
"*"
|
||||
],
|
||||
"jscomp_off": [
|
||||
"unknownDefines",
|
||||
"lintChecks",
|
||||
"analyzerChecks"
|
||||
],
|
||||
"extra_annotation_name": [
|
||||
"api", "observable"
|
||||
],
|
||||
"compilation_level": "ADVANCED",
|
||||
"warning_level": "VERBOSE",
|
||||
"output_wrapper": "(function(){%output%})();",
|
||||
"use_types_for_optimization": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Create an HTML file for the Application
|
||||
|
||||
You can now go ahead and create a simple HTML for the application. Create
|
||||
a `index.html` file with the following content at the root the application
|
||||
directory:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<link rel="stylesheet" href="node_modules/openlayers/css/ol.css" type="text/css">
|
||||
<title>Simple example</title>
|
||||
<style>
|
||||
#map {
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script src="app.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Note that the page includes a `script` tag referencing the `app.js` file,
|
||||
which is the file resulting from the compilation.
|
||||
|
||||
You are done!
|
||||
|
||||
## Run Application in Debug Mode
|
||||
|
||||
As a bonus, we're going to show how to use `closure-util` to run the
|
||||
application in "debug" mode, where the original application and OpenLayers
|
||||
scripts are loaded one by one in the page.
|
||||
|
||||
Start the `closure-util` development server:
|
||||
|
||||
$ ./node_modules/openlayers/node_modules/.bin/closure-util serve config.json
|
||||
|
||||
Now change the `script` tag to the following in the `index.html` file:
|
||||
|
||||
```html
|
||||
<script src="@?main=src/main.js" type="text/javascript"></script>
|
||||
```
|
||||
|
||||
Reload the page in your browser and you should see that scripts are now loaded
|
||||
individually, making debugging much easier.
|
||||
233
doc/tutorials/custom-builds.md
Normal file
233
doc/tutorials/custom-builds.md
Normal file
@@ -0,0 +1,233 @@
|
||||
---
|
||||
title: Custom builds
|
||||
layout: doc.hbs
|
||||
---
|
||||
|
||||
# Creating custom builds
|
||||
|
||||
OpenLayers is a big library providing a lot of functionality. So it is unlikely that an application will need and use all the functionality OpenLayers provides. This is why creating application-specific OpenLayers builds, with just the functionality your application needs, is often a good idea.
|
||||
|
||||
An alternative to creating custom builds is to compile your application code together with OpenLayers. See the [Compiling Application with Closure Compiler](closure.html) tutorial for more information.
|
||||
|
||||
This particular tutorial explains how to create custom builds of OpenLayers.
|
||||
|
||||
## Requirements
|
||||
|
||||
OpenLayers's build tools use Node and Java, so you need to have Node and Java installed on your machine. You can run `node --version` and `java -version` to test that Node and Java are installed, respectively. See [developing guide](https://github.com/openlayers/openlayers/blob/master/DEVELOPING.md) for minimum version numbers required.
|
||||
|
||||
## Download OpenLayers
|
||||
|
||||
Obviously, creating a custom build requires the OpenLayers source and specific build scripts.
|
||||
|
||||
To get the OpenLayers source and the build scripts you can clone the openlayers [repository](https://github.com/openlayers/openlayers), or you can download one of the release archives. You can also download the `openlayers` Node package from the Node package registry, using NPM (the Node Package Manager). This is the method we are going to use in this tutorial.
|
||||
|
||||
Create a directory:
|
||||
|
||||
$ mkdir openlayers
|
||||
|
||||
Download the OpenLayers distribution using NPM:
|
||||
|
||||
$ npm install openlayers
|
||||
|
||||
This will download the latest stable version of OpenLayers, and install it under `node_modules`. You can list the content of `node_modules` to verify that it effectively contains a directory named "openlayers".
|
||||
|
||||
The Node packages onto which the `openlayers` package depends are installed under `node_modules/openlayers/node_modules`. That directory should, for example, include `closure-util`, which is the utility library OpenLayers uses for Closure.
|
||||
|
||||
You should now have everything you need to create custom builds of OpenLayers!
|
||||
|
||||
## Create a build configuration file
|
||||
|
||||
Creating a custom build requires writing a build configuration file. The format of build configuration files is JSON. Here is a simple example of a build configuration file:
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": [
|
||||
"ol.Map",
|
||||
"ol.View",
|
||||
"ol.control.defaults",
|
||||
"ol.layer.Tile",
|
||||
"ol.source.OSM"
|
||||
],
|
||||
"compile": {
|
||||
"externs": [
|
||||
"externs/bingmaps.js",
|
||||
"externs/cartodb.js",
|
||||
"externs/closure-compiler.js",
|
||||
"externs/esrijson.js",
|
||||
"externs/geojson.js",
|
||||
"externs/oli.js",
|
||||
"externs/proj4js.js",
|
||||
"externs/tilejson.js",
|
||||
"externs/topojson.js"
|
||||
],
|
||||
"extra_annotation_name": [
|
||||
"api", "observable"
|
||||
],
|
||||
"compilation_level": "ADVANCED",
|
||||
"manage_closure_dependencies": true,
|
||||
"rewrite_polyfills": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Create a file named `ol-custom.json` with that content, and save it under the `node_modules/openlayers/build` directory. (You can save it to any location really.)
|
||||
|
||||
The most relevant part of this configuration object is the `"exports"` array. This array declares the functions/constructors you use in your JavaScript code. For example, the above configuration file is what you'd use for the following JavaScript code:
|
||||
|
||||
```js
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
})
|
||||
],
|
||||
controls: ol.control.defaults({
|
||||
attributionOptions: {
|
||||
collapsible: false
|
||||
}
|
||||
}),
|
||||
view: new ol.View({
|
||||
center: [0, 0],
|
||||
zoom: 4
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
Note that this JavaScript code corresponds to OpenLayers's [`simple`](https://openlayers.org/en/master/examples/simple.html) example.
|
||||
|
||||
You are now ready to create your first OpenLayers build. Use the following command to create the build:
|
||||
|
||||
$ cd node_modules/openlayers
|
||||
$ node tasks/build.js build/ol-custom.json build/ol-custom.js
|
||||
|
||||
The build command may take some time, but it should end with an output in the console such as the following:
|
||||
|
||||
info ol Parsing dependencies
|
||||
info ol Compiling 364 sources
|
||||
|
||||
The build command should have created an `ol-custom.js` file in the `node_modules/openlayers/build` directory. You can verify that the file was created. You can even open it in your editor if you're curious.
|
||||
|
||||
As a test, you can use the following HTML file to verify that your custom build works as expected:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>OpenLayers example</title>
|
||||
<link rel="stylesheet" href="node_modules/openlayers/css/ol.css" />
|
||||
<style>
|
||||
#map {
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script src="node_modules/openlayers/build/ol-custom.js"></script>
|
||||
<script>
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
})
|
||||
],
|
||||
view: new ol.View({
|
||||
center: [0, 0],
|
||||
zoom: 4
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## More on the config file
|
||||
|
||||
### `define`'s
|
||||
|
||||
Closure allows you to define constants that can be set at compile time. The OpenLayers code defines several such values.
|
||||
|
||||
Setting some of these to `false` means that the portions of the code relating to this setting become "dead", i.e. are never executed. As Closure Compiler's `ADVANCED` mode removes dead code, this makes the size of the advanced compiled file smaller.
|
||||
|
||||
You might have noticed that the build file you've just created is considerably smaller than the full build, but it can be reduced further. This is because both renderers and other optional code are included by default. We only need one renderer, and we do not use the optional code, so can exclude what we don't use by setting properties with `define`s. So add a define section to the config above:
|
||||
```
|
||||
"define": [
|
||||
"ol.ENABLE_WEBGL=false",
|
||||
"ol.ENABLE_PROJ4JS=false",
|
||||
"ol.ENABLE_RASTER_REPROJECTION=false"
|
||||
],
|
||||
```
|
||||
|
||||
and re-run the build script. The build size should now be smaller.
|
||||
|
||||
### Externs
|
||||
|
||||
The Closure documentation explains that "externs" are for external names used in the code being compiled. The compiler includes externs for built-ins such as `document`. The `externs` directory of the OpenLayers code includes files for all those used in some part of the library. For example, if you use Bing Maps, you should include the Bing externs file in the `externs` section of the config file.
|
||||
|
||||
### Other compiler options
|
||||
|
||||
There are a couple of other compiler options in the config file above. `manage_closure_dependencies` and `rewrite_polyfills` should always be used.
|
||||
|
||||
You can specify any of the other compiler options here as needed, such as the renaming reports, output manifest, or source maps. There is a full list of available options in [closure-util](https://github.com/openlayers/closure-util/blob/master/compiler-options.txt).
|
||||
|
||||
Note that `build.js` currently requires you to enter an output file and will write the output from the compiler to it; it does not use the `js_output_file` compiler option. If you specify this in the config file, there will be no compiler output, so `build.js`'s output file will be empty.
|
||||
|
||||
## A more complicated example
|
||||
|
||||
Now let's try a more complicated example: [`heatmaps-earthquakes`](https://openlayers.org/en/master/examples/heatmap-earthquakes.html). The build configuration file looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": [
|
||||
"ol.layer.Heatmap",
|
||||
"ol.source.Vector",
|
||||
"ol.format.KML",
|
||||
"ol.layer.Heatmap#getSource",
|
||||
"ol.source.Vector#on",
|
||||
"ol.source.Vector.Event#feature",
|
||||
"ol.Feature#get",
|
||||
"ol.Feature#set",
|
||||
"ol.layer.Tile",
|
||||
"ol.source.Stamen",
|
||||
"ol.Map",
|
||||
"ol.View",
|
||||
"ol.layer.Heatmap#setRadius",
|
||||
"ol.layer.Heatmap#setBlur"
|
||||
],
|
||||
"compile": {
|
||||
"externs": [
|
||||
"externs/bingmaps.js",
|
||||
"externs/cartodb.js",
|
||||
"externs/closure-compiler.js",
|
||||
"externs/esrijson.js",
|
||||
"externs/geojson.js",
|
||||
"externs/oli.js",
|
||||
"externs/proj4js.js",
|
||||
"externs/tilejson.js",
|
||||
"externs/topojson.js"
|
||||
],
|
||||
"define": [
|
||||
"ol.ENABLE_WEBGL=false",
|
||||
"ol.ENABLE_PROJ4JS=false",
|
||||
"ol.ENABLE_RASTER_REPROJECTION=false"
|
||||
],
|
||||
"compilation_level": "ADVANCED",
|
||||
"manage_closure_dependencies": true,
|
||||
"rewrite_polyfills": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The exports are given here in the order in which they occur in the `heatmaps-earthquakes` example's JavaScript code. In this example we not only use the `ol.` functions and constructors, but also `prototype` methods where the `ol` namespace is not directly used. In the code, we have for example `vector.getSource().on()`. This means we are using the `getSource` method of `layer.Heatmap` and the `on` method of `source.KML`, so this is what has to be exported. Similarly, `event.feature.get()` means we are using the `feature` property of `source.Vector.Event` and the `get` method of `Feature`. If any of these names are left out, the compile will complete successfully, but the missing names will be obfuscated and you will get a 'property undefined' error when you try and run the script.
|
||||
|
||||
## Maintaining the code
|
||||
|
||||
If you installed OpenLayers from the Node package, you can use `npm` to upgrade to the latest version. If you cloned the Github repo, simply pulling in the latest code may not be enough, as some of the packages used, for example, the compiler, may need upgrading too. Do this by using `npm install` rather than `npm update`.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This tutorial should have given you the information you need to create custom builds, i.e. builds tailored to your application. See the [tasks readme](https://github.com/openlayers/openlayers/tree/master/tasks/readme.md) for more information on the build scripts and the properties you can use in the build configuration file.
|
||||
@@ -9,4 +9,5 @@ layout: doc.hbs
|
||||
* [Basic Concepts](concepts.html)
|
||||
* [Create Custom Builds](custom-builds.html)
|
||||
* [Bundle Application and OpenLayers using Browserify](browserify.html)
|
||||
* [Compile Application and OpenLayers together](closure.html)
|
||||
* [Raster Reprojection](raster-reprojection.html)
|
||||
|
||||
@@ -12,6 +12,9 @@ The initial release aims to support much of the functionality provided by versio
|
||||
|
||||
It is also designed such that major new features, such as displaying 3D maps, or using WebGL to quickly display large vector data sets, can be added in later releases.
|
||||
|
||||
## Google Closure
|
||||
OpenLayers was written in a way so it can be compiled with [__Closure Compiler__](https://developers.google.com/closure/compiler/). Its 'advanced' compilation mode offers a level of compression that exceeds anything else available.
|
||||
|
||||
## Public API
|
||||
Using the advanced optimizations of the Closure Compiler means that properties and methods are renamed – `longMeaningfulName` might become `xB` – and so are effectively unusable in applications using the library. To be usable, they have to be explicitly `exported`. This means the exported names, those not renamed, effectively become the public API of the library. These __exportable__ properties and methods are marked in the source, and documented in the [API docs](../../apidoc). This is the officially supported API of the library. A build containing all these exportable names is known as a __full build__. A hosted version of this is available, which can be used by any application.
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@ layout: example.html
|
||||
title: Styling feature with CanvasGradient or CanvasPattern
|
||||
shortdesc: Example showing the countries vector layer styled with patterns and gradients.
|
||||
docs: >
|
||||
This example creates a [`CanvasPattern`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern)
|
||||
First this example creates a reusable [`CanvasPattern`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern)
|
||||
and a [`CanvasGradient`](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient). The countries are loaded from
|
||||
a GeoJSON file. A style function determines for each country whether to use a fill with the
|
||||
CanvasGradient (rainbow colors) or a CanvasPattern (repeating stacked circles). **Note**: For seamless repeat patterns,
|
||||
image width and height of the pattern image must be a factor of two (2, 4, 8, ..., 512).
|
||||
a GeoJSON file. A style function determines for each country whether to use a fill with the pregenerated
|
||||
CanvasGradient (rainbow colors) or a CanvasPattern (repeating stacked circles).
|
||||
tags: "canvas, gradient, pattern, style"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {getWidth} from '../src/ol/extent.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
import {DEVICE_PIXEL_RATIO} from '../src/ol/has.js';
|
||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||
@@ -15,8 +16,14 @@ const context = canvas.getContext('2d');
|
||||
const pixelRatio = DEVICE_PIXEL_RATIO;
|
||||
|
||||
// Generate a rainbow gradient
|
||||
const gradient = (function() {
|
||||
const grad = context.createLinearGradient(0, 0, 512 * pixelRatio, 0);
|
||||
function gradient(feature, resolution) {
|
||||
const extent = feature.getGeometry().getExtent();
|
||||
// Gradient starts on the left edge of each feature, and ends on the right.
|
||||
// Coordinate origin is the top-left corner of the extent of the geometry, so
|
||||
// we just divide the geometry's extent width by resolution and multiply with
|
||||
// pixelRatio to match the renderer's pixel coordinate system.
|
||||
const grad = context.createLinearGradient(0, 0,
|
||||
getWidth(extent) / resolution * pixelRatio, 0);
|
||||
grad.addColorStop(0, 'red');
|
||||
grad.addColorStop(1 / 6, 'orange');
|
||||
grad.addColorStop(2 / 6, 'yellow');
|
||||
@@ -25,24 +32,24 @@ const gradient = (function() {
|
||||
grad.addColorStop(5 / 6, 'blue');
|
||||
grad.addColorStop(1, 'purple');
|
||||
return grad;
|
||||
})();
|
||||
}
|
||||
|
||||
// Generate a canvasPattern with two circles on white background
|
||||
const pattern = (function() {
|
||||
canvas.width = 8 * pixelRatio;
|
||||
canvas.height = 8 * pixelRatio;
|
||||
canvas.width = 11 * pixelRatio;
|
||||
canvas.height = 11 * pixelRatio;
|
||||
// white background
|
||||
context.fillStyle = 'white';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// outer circle
|
||||
context.fillStyle = 'rgba(102, 0, 102, 0.5)';
|
||||
context.beginPath();
|
||||
context.arc(4 * pixelRatio, 4 * pixelRatio, 3 * pixelRatio, 0, 2 * Math.PI);
|
||||
context.arc(5 * pixelRatio, 5 * pixelRatio, 4 * pixelRatio, 0, 2 * Math.PI);
|
||||
context.fill();
|
||||
// inner circle
|
||||
context.fillStyle = 'rgb(55, 0, 170)';
|
||||
context.beginPath();
|
||||
context.arc(4 * pixelRatio, 4 * pixelRatio, 1.5 * pixelRatio, 0, 2 * Math.PI);
|
||||
context.arc(5 * pixelRatio, 5 * pixelRatio, 2 * pixelRatio, 0, 2 * Math.PI);
|
||||
context.fill();
|
||||
return context.createPattern(canvas, 'repeat');
|
||||
}());
|
||||
@@ -62,11 +69,12 @@ const style = new Style({
|
||||
* which either contains the aboove gradient or pattern.
|
||||
*
|
||||
* @param {module:ol/Feature~Feature} feature The feature to style.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {module:ol/style/Style} The style to use for the feature.
|
||||
*/
|
||||
const getStackedStyle = function(feature) {
|
||||
const getStackedStyle = function(feature, resolution) {
|
||||
const id = feature.getId();
|
||||
fill.setColor(id > 'J' ? gradient : pattern);
|
||||
fill.setColor(id > 'J' ? gradient(feature, resolution) : pattern);
|
||||
return style;
|
||||
};
|
||||
|
||||
@@ -86,7 +94,7 @@ const map = new Map({
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: fromLonLat([16, 48]),
|
||||
center: fromLonLat([7, 52]),
|
||||
zoom: 3
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import ImageLayer from '../src/ol/layer/Image.js';
|
||||
|
||||
1
examples/d3.js
vendored
1
examples/d3.js
vendored
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {getWidth, getCenter} from '../src/ol/extent.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {defaults as defaultControls} from '../src/ol/control.js';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// NOCOMPILE
|
||||
// this example uses FileSaver.js for which we don't have an externs file.
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {defaults as defaultControls} from '../src/ol/control.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {defaults as defaultControls} from '../src/ol/control.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Feature from '../src/ol/Feature.js';
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
|
||||
@@ -42,7 +42,8 @@ map.addOverlay(marker);
|
||||
// LineString to store the different geolocation positions. This LineString
|
||||
// is time aware.
|
||||
// The Z dimension is actually used to store the rotation (heading).
|
||||
const positions = new LineString([], /** @type {module:ol/geom/GeometryLayout} */ ('XYZM'));
|
||||
const positions = new LineString([],
|
||||
/** @type {module:ol/geom/GeometryLayout~GeometryLayout} */ ('XYZM'));
|
||||
|
||||
// Geolocation Control
|
||||
const geolocation = new Geolocation({
|
||||
|
||||
@@ -7,6 +7,6 @@ docs: >
|
||||
with OpenLayers.
|
||||
tags: "vector, jsts, buffer"
|
||||
resources:
|
||||
- https://cdn.rawgit.com/bjornharrtell/jsts/gh-pages/1.6.0/jsts.min.js
|
||||
- https://cdn.rawgit.com/bjornharrtell/jsts/gh-pages/1.4.0/jsts.min.js
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// NOCOMPILE
|
||||
// this example uses JSTS for which we don't have an externs file.
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
@@ -5,8 +7,7 @@ import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {fromLonLat} from '../src/ol/proj.js';
|
||||
import OSM from '../src/ol/source/OSM.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import LinearRing from '../src/ol/geom/LinearRing.js';
|
||||
import {Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon} from '../src/ol/geom.js';
|
||||
|
||||
|
||||
const source = new VectorSource();
|
||||
fetch('data/geojson/roads-seoul.geojson').then(function(response) {
|
||||
@@ -16,7 +17,6 @@ fetch('data/geojson/roads-seoul.geojson').then(function(response) {
|
||||
const features = format.readFeatures(json, {featureProjection: 'EPSG:3857'});
|
||||
|
||||
const parser = new jsts.io.OL3Parser();
|
||||
parser.inject(Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon);
|
||||
|
||||
for (let i = 0; i < features.length; i++) {
|
||||
const feature = features[i];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// NOCOMPILE
|
||||
// this example uses d3 for which we don't have an externs file.
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOCOMPILE
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<div class="row-fluid">
|
||||
<div id="source-controls">
|
||||
<a id="copy-button" data-clipboard-target="#example-source"><i class="fa fa-clipboard"></i> Copy</a>
|
||||
<!-- <a id="codepen-button"><i class="fa fa-codepen"></i> Edit</a> -->
|
||||
<a id="codepen-button"><i class="fa fa-codepen"></i> Edit</a>
|
||||
</div>
|
||||
<form method="POST" id="codepen-form" target="_blank" action="https://codepen.io/pen/define/">
|
||||
<textarea class="hidden" name="title">{{ title }}</textarea>
|
||||
@@ -66,6 +66,7 @@
|
||||
<textarea class="hidden" name="js">{{ js.source }}</textarea>
|
||||
<textarea class="hidden" name="css">{{ css.source }}</textarea>
|
||||
<textarea class="hidden" name="html">{{ contents }}</textarea>
|
||||
<input type="hidden" name="resources" value="https://openlayers.org/en/v{{ olVersion }}/css/ol.css,https://openlayers.org/en/v{{ olVersion }}/build/ol.js{{ extraResources }}">
|
||||
<input type="hidden" name="data">
|
||||
</form>
|
||||
<pre><code id="example-source" class="language-markup"><!DOCTYPE html>
|
||||
@@ -75,7 +76,7 @@
|
||||
<link rel="stylesheet" href="https://openlayers.org/en/v{{ olVersion }}/css/ol.css" type="text/css">
|
||||
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
|
||||
{{#if extraHead.remote}}
|
||||
<script src="https://openlayers.org/en/v{{ olVersion }}/build/ol.js"></script>{{#if extraHead.remote}}
|
||||
{{ indent extraHead.remote spaces=4 }}{{/if}}{{#if css.source}}
|
||||
<style>
|
||||
{{ indent css.source spaces=6 }} </style>{{/if}}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// NOCOMPILE
|
||||
// this example uses topolis and toastr for which we don't have an externs file.
|
||||
|
||||
import Feature from '../src/ol/Feature.js';
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// NOCOMPILE
|
||||
// this example uses turf.js for which we don't have an externs file.
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
const MinifyPlugin = require('babel-minify-webpack-plugin');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const ExampleBuilder = require('./example-builder');
|
||||
const fs = require('fs');
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const src = path.join(__dirname, '..');
|
||||
|
||||
@@ -14,21 +17,15 @@ examples.forEach(example => {
|
||||
entry[example] = `./${example}.js`;
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
const main = {
|
||||
context: src,
|
||||
target: 'web',
|
||||
entry: entry,
|
||||
optimization: {
|
||||
runtimeChunk: {
|
||||
name: 'common'
|
||||
},
|
||||
splitChunks: {
|
||||
name: 'common',
|
||||
chunks: 'initial',
|
||||
minChunks: 2
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'common',
|
||||
minChunks: 2
|
||||
}),
|
||||
new ExampleBuilder({
|
||||
templates: path.join(__dirname, '..', 'templates'),
|
||||
common: 'common'
|
||||
@@ -47,3 +44,39 @@ module.exports = {
|
||||
path: path.join(__dirname, '..', '..', 'build', 'examples')
|
||||
}
|
||||
};
|
||||
|
||||
// configuration specific to the dev environment
|
||||
const dev = {
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(
|
||||
Object.assign({NODE_ENV: 'development'}, process.env)
|
||||
)
|
||||
]
|
||||
};
|
||||
|
||||
// configuration specific to the prod environment
|
||||
const prod = {
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(
|
||||
Object.assign({NODE_ENV: 'production'}, process.env)
|
||||
),
|
||||
new MinifyPlugin()
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
module.exports = env => {
|
||||
let config;
|
||||
|
||||
switch (env) {
|
||||
case 'prod': {
|
||||
config = merge(main, prod);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
config = merge(main, dev);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ const marked = require('marked');
|
||||
const path = require('path');
|
||||
const pkg = require('../../package.json');
|
||||
const promisify = require('util').promisify;
|
||||
const RawSource = require('webpack-sources').RawSource;
|
||||
|
||||
const readFile = promisify(fs.readFile);
|
||||
const isCssRegEx = /\.css$/;
|
||||
@@ -61,28 +60,6 @@ function createWordIndex(exampleData) {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source for the chunk that matches the jsPath
|
||||
* @param {Object} chunk Chunk.
|
||||
* @param {string} jsPath Path of the file.
|
||||
* @return {string} The source.
|
||||
*/
|
||||
function getJsSource(chunk, jsPath) {
|
||||
let jsSource;
|
||||
for (let i = 0, ii = chunk.modules.length; i < ii; ++i) {
|
||||
const module = chunk.modules[i];
|
||||
if (module.modules) {
|
||||
jsSource = getJsSource(module, jsPath);
|
||||
if (jsSource) {
|
||||
return jsSource;
|
||||
}
|
||||
}
|
||||
if (module.identifier == jsPath) {
|
||||
return module.source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A webpack plugin that builds the html files for our examples.
|
||||
* @param {Object} config Plugin configuration. Requires a `templates` property
|
||||
@@ -100,7 +77,7 @@ function ExampleBuilder(config) {
|
||||
* @param {Object} compiler The webpack compiler.
|
||||
*/
|
||||
ExampleBuilder.prototype.apply = function(compiler) {
|
||||
compiler.hooks.emit.tapPromise('ExampleBuilder', async (compilation) => {
|
||||
compiler.plugin('emit', async (compilation, callback) => {
|
||||
const chunks = compilation.getStats().toJson().chunks
|
||||
.filter(chunk => chunk.names[0] !== this.common);
|
||||
|
||||
@@ -117,11 +94,19 @@ ExampleBuilder.prototype.apply = function(compiler) {
|
||||
});
|
||||
|
||||
for (const file in assets) {
|
||||
compilation.assets[file] = new RawSource(assets[file]);
|
||||
compilation.assets[file] = {
|
||||
source: () => assets[file],
|
||||
size: () => assets[file].length
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
try {
|
||||
await Promise.all(promises);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const info = {
|
||||
examples: exampleData,
|
||||
@@ -129,7 +114,12 @@ ExampleBuilder.prototype.apply = function(compiler) {
|
||||
};
|
||||
|
||||
const indexSource = `var info = ${JSON.stringify(info)}`;
|
||||
compilation.assets['index.js'] = new RawSource(indexSource);
|
||||
compilation.assets['index.js'] = {
|
||||
source: () => indexSource,
|
||||
size: () => indexSource.length
|
||||
};
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -152,8 +142,14 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
|
||||
// add in script tag
|
||||
const jsName = `${name}.js`;
|
||||
const jsPath = path.join(dir, jsName);
|
||||
let jsSource = getJsSource(chunk, jsPath);
|
||||
jsSource = jsSource.replace(/'\.\.\/src\//g, '\'');
|
||||
let jsSource;
|
||||
for (let i = 0, ii = chunk.modules.length; i < ii; ++i) {
|
||||
const module = chunk.modules[i];
|
||||
if (module.identifier == jsPath) {
|
||||
jsSource = module.source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data.cloak) {
|
||||
for (const entry of data.cloak) {
|
||||
jsSource = jsSource.replace(new RegExp(entry.key, 'g'), entry.value);
|
||||
|
||||
385
externs/oli.js
Normal file
385
externs/oli.js
Normal file
@@ -0,0 +1,385 @@
|
||||
/**
|
||||
* @externs
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
let oli;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.AssertionError = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
oli.AssertionError.prototype.code;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.events.Event = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.events.Event.prototype.target;
|
||||
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
oli.events.Event.prototype.type;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
oli.events.Event.prototype.preventDefault = function() {};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
oli.events.Event.prototype.stopPropagation = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.Collection.Event = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {*}
|
||||
*/
|
||||
oli.Collection.Event.prototype.element;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.DragBoxEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
oli.DragBoxEvent.prototype.coordinate;
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/MapBrowserEvent~MapBrowserEvent}
|
||||
*/
|
||||
oli.DragBoxEvent.prototype.mapBrowserEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.DrawEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/Feature~Feature}
|
||||
*/
|
||||
oli.DrawEvent.prototype.feature;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.ExtentEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
oli.ExtentEvent.prototype.extent;
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.ModifyEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Collection.<module:ol/Feature~Feature>}
|
||||
*/
|
||||
oli.ModifyEvent.prototype.features;
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/MapBrowserEvent~MapBrowserEvent}
|
||||
*/
|
||||
oli.ModifyEvent.prototype.mapBrowserEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.Object;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.Object.Event = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
oli.Object.Event.prototype.key;
|
||||
|
||||
|
||||
/**
|
||||
* @type {*}
|
||||
*/
|
||||
oli.Object.Event.prototype.oldValue;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.MapBrowserEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
oli.MapBrowserEvent.prototype.coordinate;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Event}
|
||||
*/
|
||||
oli.MapBrowserEvent.prototype.originalEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Pixel}
|
||||
*/
|
||||
oli.MapBrowserEvent.prototype.pixel;
|
||||
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
oli.MapBrowserEvent.prototype.dragging;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.MapEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.PluggableMap}
|
||||
*/
|
||||
oli.MapEvent.prototype.map;
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/PluggableMap~FrameState}
|
||||
*/
|
||||
oli.MapEvent.prototype.frameState;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.SelectEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Array.<module:ol/Feature~Feature>}
|
||||
*/
|
||||
oli.SelectEvent.prototype.deselected;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Array.<module:ol/Feature~Feature>}
|
||||
*/
|
||||
oli.SelectEvent.prototype.selected;
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/MapBrowserEvent~MapBrowserEvent}
|
||||
*/
|
||||
oli.SelectEvent.prototype.mapBrowserEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.control;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.control.Control = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.PluggableMap} map Map.
|
||||
* @return {undefined} Undefined.
|
||||
*/
|
||||
oli.control.Control.prototype.setMap = function(map) {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.interaction;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.interaction.DragAndDropEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Array.<module:ol/Feature~Feature>|undefined}
|
||||
*/
|
||||
oli.interaction.DragAndDropEvent.prototype.features;
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/proj/Projection~Projection|undefined}
|
||||
*/
|
||||
oli.interaction.DragAndDropEvent.prototype.projection;
|
||||
|
||||
|
||||
/**
|
||||
* @type {File}
|
||||
*/
|
||||
oli.interaction.DragAndDropEvent.prototype.file;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.interaction.TranslateEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Collection.<module:ol/Feature~Feature>}
|
||||
*/
|
||||
oli.interaction.TranslateEvent.prototype.features;
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
oli.interaction.TranslateEvent.prototype.coordinate;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.render;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.render.Event = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {CanvasRenderingContext2D|null|undefined}
|
||||
*/
|
||||
oli.render.Event.prototype.context;
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/PluggableMap~FrameState|undefined}
|
||||
*/
|
||||
oli.render.Event.prototype.frameState;
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.webgl.Context|null|undefined}
|
||||
*/
|
||||
oli.render.Event.prototype.glContext;
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.render.VectorContext|undefined}
|
||||
*/
|
||||
oli.render.Event.prototype.vectorContext;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.source;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.source.ImageEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Image}
|
||||
*/
|
||||
oli.source.ImageEvent.prototype.image;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.source.RasterEvent = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
*/
|
||||
oli.source.RasterEvent.prototype.extent;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
oli.source.RasterEvent.prototype.resolution;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
oli.source.RasterEvent.prototype.data;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.source.Tile.Event = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {ol.Tile}
|
||||
*/
|
||||
oli.source.Tile.Event.prototype.tile;
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.source.Vector.Event = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @type {module:ol/Feature~Feature|undefined}
|
||||
*/
|
||||
oli.source.Vector.Event.prototype.feature;
|
||||
@@ -1,3 +1,84 @@
|
||||
# Externs
|
||||
|
||||
TODO: remove this directory
|
||||
This directory contains externs files, which tell the Closure compiler about symbols and properties that it should not rename.
|
||||
|
||||
## oli.js
|
||||
|
||||
These are special externs that belong to OpenLayers, and this document explains their purpose and how they are used.
|
||||
|
||||
### Prevent class properties from being renamed
|
||||
|
||||
For events, we make properties available to the application. Methods can be made available by just marking them with the `@api` annotation directly where they are defined; properties should also be added to `oli.js`:
|
||||
|
||||
```js
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.MapBrowserEvent = function() {};
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
oli.MapBrowserEvent.prototype.coordinate;
|
||||
```
|
||||
In the source file (`src/ol/MapBrowserEvent.js`), the class needs to implement this interface:
|
||||
```js
|
||||
/**
|
||||
* ...
|
||||
* @constructor
|
||||
* @implements {oli.MapBrowserEvent}
|
||||
*/
|
||||
ol.MapBrowserEvent = function(type, map, originalEvent, opt_frameState) {
|
||||
|
||||
// ...
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
* @api
|
||||
*/
|
||||
this.coordinate = map.getEventCoordinate(this.originalEvent);
|
||||
|
||||
// ...
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
### Override methods in custom classes
|
||||
|
||||
For custom subclasses in applications, which can be created using `ol.inherits`, the API may want to make certain methods available to override. In addition to marking such methods as `@api`, they should also be added to an interface in `oli.js`:
|
||||
```js
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
oli.control.Control = function() {};
|
||||
|
||||
/**
|
||||
* @param {ol.PluggableMap} map Map.
|
||||
* @return {undefined} Undefined.
|
||||
*/
|
||||
oli.control.Control.prototype.setMap = function(map) {};
|
||||
|
||||
```
|
||||
This interface must be implemented by the class in the source file (`src/ol/control/control.js`):
|
||||
```js
|
||||
/**
|
||||
* ...
|
||||
* @constructor
|
||||
* @implements {oli.control.Control}
|
||||
*/
|
||||
ol.control.Control = function(options) {
|
||||
// ...
|
||||
};
|
||||
|
||||
// ...
|
||||
|
||||
/**
|
||||
* Application subclasses may override this.
|
||||
* @param {ol.PluggableMap} map Map.
|
||||
* @api
|
||||
*/
|
||||
ol.control.Control.prototype.setMap = function(map) {
|
||||
// ...
|
||||
};
|
||||
```
|
||||
See Custom controls example for an example of how this can be used.
|
||||
|
||||
56
package.json
56
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openlayers",
|
||||
"version": "5.0.0-beta.12",
|
||||
"version": "4.6.5",
|
||||
"description": "Build tools and sources for developing OpenLayers based mapping applications",
|
||||
"keywords": [
|
||||
"map",
|
||||
@@ -14,17 +14,15 @@
|
||||
"posttest": "npm run typecheck",
|
||||
"test": "npm run karma -- --single-run",
|
||||
"karma": "karma start test/karma.config.js",
|
||||
"serve-examples": "mkdir -p build/examples && webpack --config examples/webpack/config.js --mode development --watch & serve build/examples",
|
||||
"build-examples": "webpack --config examples/webpack/config.js --mode production",
|
||||
"build-index": "node tasks/generate-index",
|
||||
"build-site": "node tasks/generate-info.js && cd site && npm install && npm run build",
|
||||
"serve-examples": "mkdir -p build/examples && webpack --config examples/webpack/config.js --watch & serve build/examples",
|
||||
"build-examples": "webpack --config examples/webpack/config.js --env=prod",
|
||||
"build-index": "node tasks/generate-index.js",
|
||||
"prebuild": "npm run build-index",
|
||||
"build": "rollup --config config/rollup.js",
|
||||
"build": "webpack --config config/webpack.js",
|
||||
"presrc-closure": "npm run prebuild",
|
||||
"src-closure": "node tasks/transform-types",
|
||||
"src-closure": "babel -q --out-dir build/src-closure src/",
|
||||
"pretypecheck": "npm run src-closure",
|
||||
"typecheck": "node tasks/typecheck",
|
||||
"apidoc": "jsdoc config/jsdoc/api/index.md -c config/jsdoc/api/conf.json -P package.json -d build/apidoc"
|
||||
"typecheck": "node tasks/typecheck"
|
||||
},
|
||||
"main": "src/ol/index.js",
|
||||
"repository": {
|
||||
@@ -40,29 +38,26 @@
|
||||
"css/ol.css"
|
||||
],
|
||||
"dependencies": {
|
||||
"babel-eslint": "^8.2.3",
|
||||
"pbf": "3.1.0",
|
||||
"pixelworks": "1.1.0",
|
||||
"rbush": "2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-cli": "6.26.0",
|
||||
"babel-minify-webpack-plugin": "^0.3.0",
|
||||
"babel-plugin-jsdoc-closure": "1.5.1",
|
||||
"chaikin-smooth": "^1.0.4",
|
||||
"chaikin-smooth": "1.0.4",
|
||||
"clean-css-cli": "4.1.11",
|
||||
"copy-webpack-plugin": "^4.4.1",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"coveralls": "3.0.1",
|
||||
"eslint": "4.19.1",
|
||||
"eslint-config-openlayers": "^9.2.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-prettier": "^2.6.0",
|
||||
"eslint-plugin-react": "^7.7.0",
|
||||
"expect.js": "0.3.1",
|
||||
"front-matter": "^2.1.2",
|
||||
"fs-extra": "^6.0.0",
|
||||
"glob": "^7.1.2",
|
||||
"google-closure-compiler": "20180506.0.0",
|
||||
"google-closure-compiler": "20180402.0.0",
|
||||
"handlebars": "4.0.11",
|
||||
"html-webpack-plugin": "^3.0.1",
|
||||
"istanbul": "0.4.5",
|
||||
"jquery": "3.3.1",
|
||||
"jsdoc": "3.5.5",
|
||||
@@ -72,28 +67,19 @@
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-mocha": "1.3.0",
|
||||
"karma-sauce-launcher": "1.2.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-webpack": "4.0.0-beta.0",
|
||||
"marked": "0.4.0",
|
||||
"mocha": "5.2.0",
|
||||
"karma-webpack": "3.0.0",
|
||||
"marked": "0.3.19",
|
||||
"mocha": "5.1.1",
|
||||
"mustache": "^2.3.0",
|
||||
"pixelmatch": "^4.0.2",
|
||||
"prettier": "^1.12.0",
|
||||
"proj4": "2.4.4",
|
||||
"recast": "0.15.0",
|
||||
"rollup": "0.60.2",
|
||||
"rollup-plugin-buble": "0.19.2",
|
||||
"rollup-plugin-commonjs": "9.1.3",
|
||||
"rollup-plugin-node-resolve": "3.3.0",
|
||||
"rollup-plugin-sourcemaps": "0.4.2",
|
||||
"rollup-plugin-uglify": "4.0.0",
|
||||
"serve": "^8.1.1",
|
||||
"sinon": "^6.0.0",
|
||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||
"recast": "0.14.7",
|
||||
"serve": "^6.5.5",
|
||||
"sinon": "^5.0.1",
|
||||
"url-polyfill": "^1.0.13",
|
||||
"walk": "^2.3.9",
|
||||
"webpack": "4.12.0",
|
||||
"webpack-cli": "^3.0.3"
|
||||
"webpack": "3.11.0",
|
||||
"webpack-merge": "4.1.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "openlayers"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "openlayers/react",
|
||||
"parser": "babel-eslint",
|
||||
"globals": {
|
||||
"graphql": false
|
||||
}
|
||||
}
|
||||
4
site/.gitignore
vendored
4
site/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
/node_modules/
|
||||
/.cache/
|
||||
/public/
|
||||
/build/
|
||||
@@ -1,30 +0,0 @@
|
||||
const path = require('path');
|
||||
const typography = require('./src/utils/typography');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
{
|
||||
resolve: 'gatsby-plugin-typography',
|
||||
options: {
|
||||
pathToConfigModule: 'src/utils/typography.js'
|
||||
}
|
||||
},
|
||||
'gatsby-plugin-emotion',
|
||||
{
|
||||
resolve: 'gatsby-source-filesystem',
|
||||
options: {
|
||||
name: 'examples',
|
||||
path: path.join(__dirname, 'src', 'examples')
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: 'examples',
|
||||
options: {
|
||||
sourceInstanceName: 'examples',
|
||||
baseCss: typography.toString()
|
||||
}
|
||||
},
|
||||
'gatsby-transformer-remark',
|
||||
'gatsby-plugin-react-next'
|
||||
]
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
// exports.onPreBuild = () => {
|
||||
// // TODO: empty public folder
|
||||
// };
|
||||
15861
site/package-lock.json
generated
15861
site/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"name": "@ol/site",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "gatsby develop",
|
||||
"build": "gatsby build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"emotion": "^9.1.3",
|
||||
"emotion-server": "^9.1.3",
|
||||
"gatsby": "1.9.250",
|
||||
"gatsby-link": "1.6.40",
|
||||
"gatsby-plugin-emotion": "^1.1.16",
|
||||
"gatsby-plugin-react-helmet": "2.0.10",
|
||||
"gatsby-plugin-react-next": "^1.0.11",
|
||||
"gatsby-plugin-typography": "1.7.18",
|
||||
"gatsby-source-filesystem": "1.5.31",
|
||||
"gatsby-transformer-remark": "^1.7.40",
|
||||
"prop-types": "15.6.1",
|
||||
"react-emotion": "^9.1.3",
|
||||
"react-helmet": "5.2.0",
|
||||
"react-markdown": "^3.3.2",
|
||||
"rollup": "^0.58.1",
|
||||
"rollup-plugin-commonjs": "^9.1.0",
|
||||
"rollup-plugin-node-resolve": "^3.3.0",
|
||||
"string-template": "^1.0.0",
|
||||
"typography-plugin-code": "^0.16.11",
|
||||
"typography-theme-noriega": "^0.15.10"
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
import {object} from 'prop-types';
|
||||
import ExampleList from './ExampleList';
|
||||
import React, {Component, Fragment} from 'react';
|
||||
import styled from 'react-emotion';
|
||||
|
||||
const Wrapper = styled('div')({
|
||||
display: 'flex'
|
||||
});
|
||||
|
||||
const Sidebar = styled('div')({
|
||||
marginRight: '1em'
|
||||
});
|
||||
|
||||
const Content = styled('div')({
|
||||
minWidth: 300,
|
||||
flexGrow: 1
|
||||
});
|
||||
|
||||
const Embed = styled('iframe')({
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
height: 350,
|
||||
width: '100%'
|
||||
});
|
||||
|
||||
const Aside = styled('aside')({
|
||||
textAlign: 'right',
|
||||
fontSize: '0.75em'
|
||||
});
|
||||
|
||||
const Block = styled('pre')({
|
||||
overflow: 'auto'
|
||||
});
|
||||
|
||||
class Example extends Component {
|
||||
render() {
|
||||
const example = this.props.data.sitePage.context;
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Sidebar>
|
||||
<ExampleList active={example.slug} />
|
||||
</Sidebar>
|
||||
<Content>
|
||||
<h1>{example.frontmatter.title}</h1>
|
||||
<Embed src={example.embedUrl} frameBorder="0" />
|
||||
<Aside>
|
||||
<p>
|
||||
<a href={example.embedUrl}>stand-alone version</a>
|
||||
</p>
|
||||
</Aside>
|
||||
<h3>script</h3>
|
||||
<Block>
|
||||
<code>{example.js}</code>
|
||||
</Block>
|
||||
<h3>markup</h3>
|
||||
<Block>
|
||||
<code>{example.html}</code>
|
||||
</Block>
|
||||
{example.css && (
|
||||
<Fragment>
|
||||
<h3>style</h3>
|
||||
<Block>
|
||||
<code>{example.css}</code>
|
||||
</Block>
|
||||
</Fragment>
|
||||
)}
|
||||
</Content>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Example.propTypes = {
|
||||
data: object.isRequired
|
||||
};
|
||||
|
||||
export const query = graphql`
|
||||
query ExampleQuery($slug: String!) {
|
||||
sitePage(context: {slug: {eq: $slug}}) {
|
||||
context {
|
||||
slug
|
||||
frontmatter {
|
||||
title
|
||||
}
|
||||
embedUrl
|
||||
html
|
||||
js
|
||||
css
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default Example;
|
||||
@@ -1,54 +0,0 @@
|
||||
import Link from 'gatsby-link';
|
||||
import React, {Component} from 'react';
|
||||
import styled from 'react-emotion';
|
||||
|
||||
const Wrapper = styled('div')({
|
||||
minWidth: '10em'
|
||||
});
|
||||
|
||||
const List = styled('ul')({
|
||||
margin: 0,
|
||||
listStyle: 'none'
|
||||
});
|
||||
|
||||
class ExampleList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
index: null
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
fetch('../index.json')
|
||||
.then(response => response.json())
|
||||
.then(index => {
|
||||
this.setState({index});
|
||||
});
|
||||
}
|
||||
|
||||
renderList() {
|
||||
const index = this.state.index;
|
||||
if (!index) {
|
||||
return '...';
|
||||
}
|
||||
|
||||
const list = [];
|
||||
for (const id in index) {
|
||||
const example = index[id];
|
||||
list.push(
|
||||
<li key={id}>
|
||||
<Link to={example.slug}>{example.title}</Link>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
return <List>{list}</List>;
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Wrapper>{this.renderList()}</Wrapper>;
|
||||
}
|
||||
}
|
||||
|
||||
export default ExampleList;
|
||||
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charSet="utf-8">
|
||||
<title>{title}</title>
|
||||
<style>{baseCss}</style>
|
||||
<style>{olCss}</style>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#map {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<style>{exampleCss}</style>
|
||||
</head>
|
||||
<body>
|
||||
{html}
|
||||
<script type="module" src="{mainBundleUrl}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,197 +0,0 @@
|
||||
const path = require('path');
|
||||
const {createFilePath} = require('gatsby-source-filesystem');
|
||||
const rollup = require('rollup');
|
||||
const resolve = require('rollup-plugin-node-resolve');
|
||||
const common = require('rollup-plugin-commonjs');
|
||||
const fse = require('fs-extra');
|
||||
const compileTemplate = require('string-template/compile');
|
||||
|
||||
let rollupCache;
|
||||
const rollupPlugins = [resolve(), common()];
|
||||
|
||||
let olCss;
|
||||
async function getOLCss() {
|
||||
if (olCss) {
|
||||
return olCss;
|
||||
}
|
||||
const cssPath = path.join(__dirname, '..', '..', '..', 'css', 'ol.css');
|
||||
olCss = await fse.readFile(cssPath, {encoding: 'utf8'});
|
||||
return olCss;
|
||||
}
|
||||
|
||||
let embedTemplate;
|
||||
async function getEmbedTemplate() {
|
||||
if (embedTemplate) {
|
||||
return embedTemplate;
|
||||
}
|
||||
const embedPath = path.join(__dirname, 'embed.html');
|
||||
const src = await fse.readFile(embedPath, {encoding: 'utf8'});
|
||||
embedTemplate = compileTemplate(src);
|
||||
return embedTemplate;
|
||||
}
|
||||
|
||||
exports.onCreateNode = ({node, getNode, boundActionCreators}) => {
|
||||
const {createNodeField} = boundActionCreators;
|
||||
if (node.internal.type === 'MarkdownRemark') {
|
||||
const slug = createFilePath({node, getNode});
|
||||
createNodeField({
|
||||
node,
|
||||
name: 'slug',
|
||||
value: `/examples${slug}` // TODO: get this from options
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.createPages = async (
|
||||
{graphql, boundActionCreators},
|
||||
{sourceInstanceName, baseCss = ''}
|
||||
) => {
|
||||
const {createPage, createRedirect} = boundActionCreators;
|
||||
|
||||
createRedirect({
|
||||
fromPath: `/examples/`,
|
||||
isPermanent: true,
|
||||
redirectInBrowser: true,
|
||||
toPath: `/examples/map/`
|
||||
});
|
||||
|
||||
const {data} = await graphql(`
|
||||
{
|
||||
allFile(
|
||||
filter: {sourceInstanceName: {eq: "${sourceInstanceName}"}, extension: {ne: ""}}
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
base
|
||||
name
|
||||
extension
|
||||
absolutePath
|
||||
childMarkdownRemark {
|
||||
frontmatter {
|
||||
title
|
||||
}
|
||||
fields {
|
||||
slug
|
||||
}
|
||||
html
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const rollupInputs = [];
|
||||
|
||||
const examples = {};
|
||||
data.allFile.edges.forEach(({node}) => {
|
||||
const name = node.name;
|
||||
if (!(name in examples)) {
|
||||
examples[name] = {};
|
||||
}
|
||||
examples[name][node.extension] = node;
|
||||
if (node.extension === 'js') {
|
||||
rollupInputs.push(node.absolutePath);
|
||||
}
|
||||
});
|
||||
|
||||
const bundle = await rollup.rollup({
|
||||
input: rollupInputs,
|
||||
plugins: rollupPlugins,
|
||||
experimentalCodeSplitting: true,
|
||||
cache: rollupCache
|
||||
});
|
||||
|
||||
const embedDirName = 'example-embeds';
|
||||
const embedDir = path.join(__dirname, '..', '..', 'public', embedDirName);
|
||||
const exampleDir = path.join(__dirname, '..', '..', 'public', 'examples');
|
||||
|
||||
rollupCache = await bundle.write({
|
||||
format: 'es',
|
||||
sourcemap: true,
|
||||
dir: embedDir
|
||||
});
|
||||
|
||||
const writes = [];
|
||||
const index = {};
|
||||
|
||||
for (const name in examples) {
|
||||
const node = examples[name].md;
|
||||
if (!node) {
|
||||
throw new Error(`Missing ${name}.md`);
|
||||
}
|
||||
const markdownNode = node.childMarkdownRemark;
|
||||
if (!markdownNode) {
|
||||
throw new Error(`Expected a MarkdownRemark node for ${name}`);
|
||||
}
|
||||
|
||||
const mainBundleUrl = `${name}.js`;
|
||||
const bundleInfo = rollupCache[mainBundleUrl];
|
||||
if (!bundleInfo) {
|
||||
throw new Error(`Expected a js bundle for ${name}`);
|
||||
}
|
||||
|
||||
const jsNode = examples[name].js;
|
||||
if (!jsNode) {
|
||||
throw new Error(`Missing ${name}.js`);
|
||||
}
|
||||
|
||||
const moduleIndex = bundleInfo.map.sources.findIndex(
|
||||
filepath => path.resolve(filepath) === jsNode.absolutePath
|
||||
);
|
||||
if (moduleIndex < 0) {
|
||||
throw new Error(`Could not find ${node.absolutePath} in module list`);
|
||||
}
|
||||
const source = bundleInfo.map.sourcesContent[moduleIndex];
|
||||
if (!source) {
|
||||
throw new Error(`Could not find source for ${jsNode.absolutePath}`);
|
||||
}
|
||||
|
||||
let exampleCss = '';
|
||||
const cssNode = examples[name].css;
|
||||
if (cssNode) {
|
||||
exampleCss = await fse.readFile(cssNode.absolutePath, {encoding: 'utf8'});
|
||||
await fse.writeFile(path.join(embedDir, cssNode.base), exampleCss);
|
||||
}
|
||||
|
||||
const embedTemplate = await getEmbedTemplate();
|
||||
const embed = embedTemplate({
|
||||
title: markdownNode.frontmatter.title,
|
||||
baseCss,
|
||||
olCss: await getOLCss(),
|
||||
exampleCss,
|
||||
html: markdownNode.html,
|
||||
mainBundleUrl
|
||||
});
|
||||
|
||||
const embedName = `${name}.html`;
|
||||
writes.push(fse.writeFile(path.join(embedDir, embedName), embed));
|
||||
|
||||
const slug = markdownNode.fields.slug;
|
||||
index[name] = {
|
||||
title: markdownNode.frontmatter.title,
|
||||
slug
|
||||
};
|
||||
|
||||
createPage({
|
||||
path: slug,
|
||||
component: path.join(__dirname, 'components', 'Example.js'),
|
||||
context: {
|
||||
slug,
|
||||
frontmatter: markdownNode.frontmatter,
|
||||
embedUrl: `/${embedDirName}/${embedName}`,
|
||||
html: markdownNode.html,
|
||||
js: source.replace(/'\.\.\/\.\.\/\.\.\/src\/(.*?)\.js/g, "'$1"),
|
||||
css: exampleCss
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await fse.ensureDir(exampleDir);
|
||||
|
||||
writes.push(
|
||||
fse.writeFile(path.join(exampleDir, 'index.json'), JSON.stringify(index))
|
||||
);
|
||||
|
||||
await Promise.all(writes);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
// no-op
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "examples",
|
||||
"main": "index.js"
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import React, {Component, Fragment} from 'react';
|
||||
import {string, array} from 'prop-types';
|
||||
import Markdown from 'react-markdown';
|
||||
import {slugify, getShortName, getShortModuleName} from '../../utils/doc';
|
||||
|
||||
class Class extends Component {
|
||||
static propTypes = {
|
||||
name: string.isRequired,
|
||||
description: string,
|
||||
params: array,
|
||||
exported: string
|
||||
};
|
||||
|
||||
renderArguments() {
|
||||
if (!this.props.params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h4>Arguments</h4>
|
||||
<ul>{this.props.params.map(this.renderArgument)}</ul>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderArgument(arg) {
|
||||
return (
|
||||
<li key={arg.name}>
|
||||
<code>{arg.name}</code>: {arg.description}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const name = this.props.name;
|
||||
const shortName = getShortName(name);
|
||||
const moduleName = getShortModuleName(name);
|
||||
const slug = slugify(name);
|
||||
const exported = this.props.exported;
|
||||
|
||||
let importSyntax;
|
||||
if (exported) {
|
||||
if (exported === 'default') {
|
||||
importSyntax = `import ${shortName} from '${moduleName}';\n\n`;
|
||||
} else if (exported !== shortName) {
|
||||
importSyntax = `import {${exported} as ${shortName}} from '${moduleName}';\n\n`;
|
||||
} else {
|
||||
importSyntax = `import {${exported}} from '${moduleName}';\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
const params = this.props.params || [];
|
||||
const usage = `new ${shortName}(${params
|
||||
.map(param => param.name)
|
||||
.join(', ')});`;
|
||||
|
||||
const description = this.props.description || '';
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<a name={slug} href={`#${slug}`} />
|
||||
<pre>
|
||||
<code>
|
||||
{importSyntax}
|
||||
{usage}
|
||||
</code>
|
||||
</pre>
|
||||
<Markdown source={description} />
|
||||
{this.renderArguments()}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Class;
|
||||
@@ -1,76 +0,0 @@
|
||||
import React, {Component, Fragment} from 'react';
|
||||
import {string, array} from 'prop-types';
|
||||
import Markdown from 'react-markdown';
|
||||
import {slugify, getShortName, getShortModuleName} from '../../utils/doc';
|
||||
|
||||
class Func extends Component {
|
||||
static propTypes = {
|
||||
name: string.isRequired,
|
||||
description: string,
|
||||
params: array,
|
||||
exported: string
|
||||
};
|
||||
|
||||
renderArguments() {
|
||||
if (!this.props.params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h4>Arguments</h4>
|
||||
<ul>{this.props.params.map(this.renderArgument)}</ul>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderArgument(arg) {
|
||||
return (
|
||||
<li key={arg.name}>
|
||||
<code>{arg.name}</code>: {arg.description}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const name = this.props.name;
|
||||
const shortName = getShortName(name);
|
||||
const moduleName = getShortModuleName(name);
|
||||
const slug = slugify(name);
|
||||
const exported = this.props.exported;
|
||||
|
||||
let importSyntax;
|
||||
if (exported) {
|
||||
if (exported === 'default') {
|
||||
importSyntax = `import ${shortName} from '${moduleName}';\n\n`;
|
||||
} else if (exported !== shortName) {
|
||||
importSyntax = `import {${exported} as ${shortName}} from '${moduleName}';\n\n`;
|
||||
} else {
|
||||
importSyntax = `import {${exported}} from '${moduleName}';\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
const params = this.props.params || [];
|
||||
const usage = `${shortName}(${params
|
||||
.map(param => param.name)
|
||||
.join(', ')});`;
|
||||
|
||||
const description = this.props.description || '';
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<a name={slug} href={`#${slug}`} />
|
||||
<pre>
|
||||
<code>
|
||||
{importSyntax}
|
||||
{usage}
|
||||
</code>
|
||||
</pre>
|
||||
<Markdown source={description} />
|
||||
{this.renderArguments()}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Func;
|
||||
@@ -1,57 +0,0 @@
|
||||
import React, {Component, Fragment} from 'react';
|
||||
import {string, array} from 'prop-types';
|
||||
import {slugify, getShortModuleName} from '../../utils/doc';
|
||||
import Func from './Func';
|
||||
import Class from './Class';
|
||||
|
||||
class Module extends Component {
|
||||
static propTypes = {
|
||||
name: string.isRequired,
|
||||
classes: array.isRequired,
|
||||
functions: array.isRequired
|
||||
};
|
||||
|
||||
renderClasses() {
|
||||
if (this.props.classes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h3>Classes</h3>
|
||||
{this.props.classes.map(cls => <Class key={cls.name} {...cls} />)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderFuncs() {
|
||||
if (this.props.functions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h3>Functions</h3>
|
||||
{this.props.functions.map(func => <Func key={func.name} {...func} />)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const name = this.props.name;
|
||||
const slug = slugify(name);
|
||||
return (
|
||||
<section>
|
||||
<a name={slug} href={`#${slug}`}>
|
||||
<h1>
|
||||
<code>{getShortModuleName(name)}</code>
|
||||
</h1>
|
||||
</a>
|
||||
{this.renderClasses()}
|
||||
{this.renderFuncs()}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Module;
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"varsIgnorePattern": "^map"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import Map from '../../../src/ol/Map.js';
|
||||
import View from '../../../src/ol/View.js';
|
||||
import GeoJSON from '../../../src/ol/format/GeoJSON.js';
|
||||
import {
|
||||
Tile as TileLayer,
|
||||
Vector as VectorLayer
|
||||
} from '../../../src/ol/layer.js';
|
||||
import {BingMaps, Vector as VectorSource} from '../../../src/ol/source.js';
|
||||
import {Style, Stroke} from '../../../src/ol/style.js';
|
||||
|
||||
const map = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new BingMaps({
|
||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
||||
imagerySet: 'Aerial'
|
||||
})
|
||||
}),
|
||||
new VectorLayer({
|
||||
source: new VectorSource({
|
||||
format: new GeoJSON(),
|
||||
url:
|
||||
'https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json'
|
||||
}),
|
||||
opacity: 0.5,
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
width: 1.25,
|
||||
color: 'lightgrey'
|
||||
})
|
||||
})
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: [0, 0],
|
||||
zoom: 2
|
||||
})
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
title: Multiple Layers
|
||||
shortdesc: Using layers to compose a map.
|
||||
docs: >
|
||||
Layers control how data is rendered on a map. In this example, a `Vector` layer displays GeoJSON over tiles from a `Tile` layer.
|
||||
cloak:
|
||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
||||
---
|
||||
<div id="map"></div>
|
||||
@@ -1,17 +0,0 @@
|
||||
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';
|
||||
|
||||
const map = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM()
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: [0, 0],
|
||||
zoom: 1
|
||||
})
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: My First Map
|
||||
shortdesc: Example of a map with a single layer.
|
||||
docs: >
|
||||
A map with an OSM source.
|
||||
---
|
||||
<div id="map"></div>
|
||||
@@ -1,44 +0,0 @@
|
||||
import {func} from 'prop-types';
|
||||
import Link from 'gatsby-link';
|
||||
import React from 'react';
|
||||
import styled from 'react-emotion';
|
||||
|
||||
const Page = styled('div')({
|
||||
margin: '1em auto',
|
||||
maxWidth: '960px'
|
||||
});
|
||||
|
||||
const Header = styled('header')({
|
||||
display: 'flex',
|
||||
alignItems: 'baseline',
|
||||
padding: '0 2em',
|
||||
marginBottom: '2em',
|
||||
'& h1': {
|
||||
margin: '0 auto 0 0'
|
||||
}
|
||||
});
|
||||
|
||||
const Main = styled('main')({
|
||||
padding: '0 2em'
|
||||
});
|
||||
|
||||
const Layout = ({children}) => (
|
||||
<Page>
|
||||
<Header>
|
||||
<h1>
|
||||
<Link to="/">OpenLayers</Link>
|
||||
</h1>
|
||||
<div>
|
||||
<Link to="/docs/">docs</Link>
|
||||
<Link to="/examples/">examples</Link>
|
||||
</div>
|
||||
</Header>
|
||||
<Main>{children()}</Main>
|
||||
</Page>
|
||||
);
|
||||
|
||||
Layout.propTypes = {
|
||||
children: func.isRequired
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
@@ -1,19 +0,0 @@
|
||||
import React, {Component, Fragment} from 'react';
|
||||
import Module from '../components/doc/Module';
|
||||
import {getModules} from '../utils/doc';
|
||||
|
||||
import info from '../../../build/info.json';
|
||||
|
||||
const modules = getModules(info);
|
||||
|
||||
class Docs extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
{modules.map(mod => <Module key={mod.name} {...mod} />)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Docs;
|
||||
@@ -1,42 +0,0 @@
|
||||
import React, {Component} from 'react';
|
||||
import {object} from 'prop-types';
|
||||
import Link from 'gatsby-link';
|
||||
|
||||
class Examples extends Component {
|
||||
renderExample({node}) {
|
||||
const context = node.context;
|
||||
return (
|
||||
<li key={node.id}>
|
||||
<Link to={context.slug}>{context.frontmatter.title}</Link>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <ul>{this.props.data.allSitePage.edges.map(this.renderExample)}</ul>;
|
||||
}
|
||||
}
|
||||
|
||||
Examples.propTypes = {
|
||||
data: object.isRequired
|
||||
};
|
||||
|
||||
export const query = graphql`
|
||||
query ExampleList {
|
||||
allSitePage(filter: {pluginCreator: {name: {eq: "examples"}}}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
context {
|
||||
slug
|
||||
frontmatter {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default Examples;
|
||||
@@ -1,3 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default () => <p>This is the home page</p>;
|
||||
@@ -1,111 +0,0 @@
|
||||
function getLongModuleName(name) {
|
||||
return name.split(/[~\.]/).shift();
|
||||
}
|
||||
|
||||
export function getShortModuleName(longname) {
|
||||
return getLongModuleName(longname).slice(7);
|
||||
}
|
||||
|
||||
export function getShortName(longname) {
|
||||
return longname.split(/[~\.]/).pop();
|
||||
}
|
||||
|
||||
export function slugify(name) {
|
||||
return name.replace(/[#~\.]/g, '-');
|
||||
}
|
||||
|
||||
function getExported(name, exports) {
|
||||
const local = getShortName(name);
|
||||
for (const exported in exports) {
|
||||
if (exports[exported] === local) {
|
||||
return exported;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getModules(info) {
|
||||
const moduleLookup = {};
|
||||
info.modules.forEach(mod => {
|
||||
moduleLookup[mod.name] = {...mod, functions: [], classes: []};
|
||||
});
|
||||
|
||||
// extract classes
|
||||
const classLookup = {};
|
||||
info.symbols.forEach(symbol => {
|
||||
const name = symbol.name;
|
||||
const parent = symbol.memberof;
|
||||
|
||||
if (symbol.kind === 'class') {
|
||||
const mod = moduleLookup[parent];
|
||||
if (!mod) {
|
||||
throw new Error(
|
||||
`No module found for class ${name} with parent ${parent}`
|
||||
);
|
||||
}
|
||||
const cls = {
|
||||
...symbol,
|
||||
methods: [],
|
||||
properties: [],
|
||||
exported: getExported(name, mod.exports)
|
||||
};
|
||||
|
||||
mod.classes.push(cls);
|
||||
classLookup[name] = cls;
|
||||
}
|
||||
});
|
||||
|
||||
info.symbols.forEach(symbol => {
|
||||
const name = symbol.name;
|
||||
const parent = symbol.memberof;
|
||||
|
||||
if (symbol.kind === 'member') {
|
||||
if (parent in classLookup) {
|
||||
classLookup[parent].properties.push(symbol);
|
||||
return;
|
||||
}
|
||||
|
||||
// instance property where constructor is not marked @api
|
||||
const moduleId = getLongModuleName(name);
|
||||
const mod = moduleLookup[moduleId];
|
||||
if (!mod) {
|
||||
throw new Error(`Unexpected member: ${name}`);
|
||||
}
|
||||
|
||||
const cls = {name: parent, methods: [], properties: [symbol]};
|
||||
mod.classes.push(cls);
|
||||
classLookup[parent] = cls;
|
||||
return;
|
||||
}
|
||||
|
||||
if (symbol.kind === 'function') {
|
||||
if (parent in moduleLookup) {
|
||||
moduleLookup[parent].functions.push({
|
||||
...symbol,
|
||||
exported: getExported(name, moduleLookup[parent].exports)
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent in classLookup) {
|
||||
classLookup[parent].methods.push(symbol);
|
||||
return;
|
||||
}
|
||||
|
||||
// method where constructor is not marked @api
|
||||
const moduleId = getLongModuleName(name);
|
||||
const mod = moduleLookup[moduleId];
|
||||
if (!mod) {
|
||||
throw new Error(`Unexpected function: ${name}`);
|
||||
}
|
||||
|
||||
const cls = {name: parent, methods: [symbol], properties: []};
|
||||
mod.classes.push(cls);
|
||||
classLookup[parent] = cls;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return Object.keys(moduleLookup)
|
||||
.sort()
|
||||
.map(id => moduleLookup[id]);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
const Typography = require('typography');
|
||||
const theme = require('typography-theme-noriega').default;
|
||||
const CodePlugin = require('typography-plugin-code').default;
|
||||
|
||||
theme.plugins = [new CodePlugin()];
|
||||
|
||||
theme.overrideThemeStyles = () => ({
|
||||
a: {
|
||||
color: '#003c88',
|
||||
textDecoration: 'none'
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = new Typography(theme);
|
||||
@@ -9,6 +9,7 @@ import {VERSION, inherits} from './index.js';
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error}
|
||||
* @constructor
|
||||
* @extends {Error}
|
||||
* @implements {oli.AssertionError}
|
||||
* @param {number} code Error code.
|
||||
*/
|
||||
const AssertionError = function(code) {
|
||||
|
||||
@@ -24,6 +24,7 @@ const Property = {
|
||||
*
|
||||
* @constructor
|
||||
* @extends {module:ol/events/Event}
|
||||
* @implements {oli.CollectionEvent}
|
||||
* @param {module:ol/CollectionEventType} type Type.
|
||||
* @param {*=} opt_element Element.
|
||||
*/
|
||||
@@ -115,7 +116,8 @@ Collection.prototype.clear = function() {
|
||||
* @api
|
||||
*/
|
||||
Collection.prototype.extend = function(arr) {
|
||||
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
||||
let i, ii;
|
||||
for (i = 0, ii = arr.length; i < ii; ++i) {
|
||||
this.push(arr[i]);
|
||||
}
|
||||
return this;
|
||||
@@ -224,7 +226,8 @@ Collection.prototype.push = function(elem) {
|
||||
*/
|
||||
Collection.prototype.remove = function(elem) {
|
||||
const arr = this.array_;
|
||||
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
||||
let i, ii;
|
||||
for (i = 0, ii = arr.length; i < ii; ++i) {
|
||||
if (arr[i] === elem) {
|
||||
return this.removeAt(i);
|
||||
}
|
||||
@@ -268,7 +271,8 @@ Collection.prototype.setAt = function(index, elem) {
|
||||
this.dispatchEvent(
|
||||
new CollectionEvent(CollectionEventType.ADD, elem));
|
||||
} else {
|
||||
for (let j = n; j < index; ++j) {
|
||||
let j;
|
||||
for (j = n; j < index; ++j) {
|
||||
this.insertAt(j, undefined);
|
||||
}
|
||||
this.insertAt(index, elem);
|
||||
|
||||
@@ -61,10 +61,6 @@ const INTERVALS = [
|
||||
* longitudes. This function is called with the longitude as argument, and
|
||||
* should return a formatted string representing the longitude. By default,
|
||||
* labels are formatted as degrees, minutes, seconds and hemisphere.
|
||||
* @property {function(number):string} [latLabelFormatter] Label formatter for
|
||||
* latitudes. This function is called with the latitude as argument, and
|
||||
* should return a formatted string representing the latitude. By default,
|
||||
* labels are formatted as degrees, minutes, seconds and hemisphere.
|
||||
* @property {number} [lonLabelPosition=0] Longitude label position in fractions
|
||||
* (0..1) of view extent. 0 means at the bottom of the viewport, 1 means at the
|
||||
* top.
|
||||
@@ -89,7 +85,7 @@ const INTERVALS = [
|
||||
* Note that the default's `textBaseline` configuration will not work well for
|
||||
* `lonLabelPosition` configurations that position labels close to the top of
|
||||
* the viewport.
|
||||
* @property {module:ol/style/Text} [latLabelStyle] Latitude label text style.
|
||||
* @param {module:ol/style/Text} [latLabelStyle] Latitude label text style.
|
||||
* If not provided, the following style will be used:
|
||||
* ```js
|
||||
* new Text({
|
||||
|
||||
@@ -23,7 +23,7 @@ import {getHeight} from './extent.js';
|
||||
* post requests or - in general - through XHR requests, where the src of the
|
||||
* image element would be set to a data URI when the content is loaded.
|
||||
*
|
||||
* @typedef {function(module:ol/Image, string)} LoadFunction
|
||||
* @typedef {function(module:ol/Image~Image, string)} LoadFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ ImageCanvas.prototype.load = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @return {HTMLCanvasElement} Canvas element.
|
||||
* @inheritDoc
|
||||
*/
|
||||
ImageCanvas.prototype.getImage = function() {
|
||||
return this.canvas_;
|
||||
|
||||
@@ -35,7 +35,7 @@ import CanvasVectorTileLayerRenderer from './renderer/canvas/VectorTileLayer.js'
|
||||
* target: 'map'
|
||||
* });
|
||||
*
|
||||
* The above snippet creates a map using a {@link module:ol/layer/Tile} to
|
||||
* The above snippet creates a map using a {@link module:ol/layer/Tile~Tile} to
|
||||
* display {@link module:ol/source/OSM~OSM} OSM data and render it to a DOM
|
||||
* element with the id `map`.
|
||||
*
|
||||
|
||||
@@ -11,6 +11,7 @@ import MapEvent from './MapEvent.js';
|
||||
*
|
||||
* @constructor
|
||||
* @extends {module:ol/MapEvent}
|
||||
* @implements {oli.MapBrowserEvent}
|
||||
* @param {string} type Event type.
|
||||
* @param {module:ol/PluggableMap} map Map.
|
||||
* @param {Event} browserEvent Browser event.
|
||||
|
||||
@@ -11,6 +11,7 @@ import Event from './events/Event.js';
|
||||
*
|
||||
* @constructor
|
||||
* @extends {module:ol/events/Event}
|
||||
* @implements {oli.MapEvent}
|
||||
* @param {string} type Event type.
|
||||
* @param {module:ol/PluggableMap} map Map.
|
||||
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
|
||||
|
||||
@@ -17,6 +17,7 @@ import {assign} from './obj.js';
|
||||
* @param {string} key The property name.
|
||||
* @param {*} oldValue The old value for `key`.
|
||||
* @extends {module:ol/events/Event}
|
||||
* @implements {oli.Object.Event}
|
||||
* @constructor
|
||||
*/
|
||||
const ObjectEvent = function(type, key, oldValue) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
export default {
|
||||
/**
|
||||
* Triggered when a property is changed.
|
||||
* @event module:ol/Object~ObjectEvent#propertychange
|
||||
* @event module:ol/Object~Event#propertychange
|
||||
* @api
|
||||
*/
|
||||
PROPERTYCHANGE: 'propertychange'
|
||||
|
||||
@@ -87,7 +87,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
|
||||
* @typedef {Object} MapOptions
|
||||
* @property {module:ol/Collection.<module:ol/control/Control>|Array.<module:ol/control/Control>} [controls]
|
||||
* Controls initially added to the map. If not specified,
|
||||
* {@link module:ol/control/util~defaults} is used.
|
||||
* {@link module:ol/control~defaults} is used.
|
||||
* @property {number} [pixelRatio=window.devicePixelRatio] The ratio between
|
||||
* physical pixels and device-independent pixels (dips) on the device.
|
||||
* @property {module:ol/Collection.<module:ol/interaction/Interaction>|Array.<module:ol/interaction/Interaction>} [interactions]
|
||||
@@ -303,9 +303,12 @@ const PluggableMap = function(options) {
|
||||
*/
|
||||
this.keyHandlerKeys_ = null;
|
||||
|
||||
listen(this.viewport_, EventType.CONTEXTMENU, this.handleBrowserEvent, this);
|
||||
listen(this.viewport_, EventType.WHEEL, this.handleBrowserEvent, this);
|
||||
listen(this.viewport_, EventType.MOUSEWHEEL, this.handleBrowserEvent, this);
|
||||
listen(this.viewport_, EventType.CONTEXTMENU,
|
||||
this.handleBrowserEvent, this);
|
||||
listen(this.viewport_, EventType.WHEEL,
|
||||
this.handleBrowserEvent, this);
|
||||
listen(this.viewport_, EventType.MOUSEWHEEL,
|
||||
this.handleBrowserEvent, this);
|
||||
|
||||
/**
|
||||
* @type {module:ol/Collection.<module:ol/control/Control>}
|
||||
@@ -390,9 +393,9 @@ const PluggableMap = function(options) {
|
||||
* @param {module:ol/control/Control} control Control.
|
||||
* @this {module:ol/PluggableMap}
|
||||
*/
|
||||
(function(control) {
|
||||
function(control) {
|
||||
control.setMap(this);
|
||||
}).bind(this));
|
||||
}.bind(this));
|
||||
|
||||
listen(this.controls, CollectionEventType.ADD,
|
||||
/**
|
||||
@@ -415,9 +418,9 @@ const PluggableMap = function(options) {
|
||||
* @param {module:ol/interaction/Interaction} interaction Interaction.
|
||||
* @this {module:ol/PluggableMap}
|
||||
*/
|
||||
(function(interaction) {
|
||||
function(interaction) {
|
||||
interaction.setMap(this);
|
||||
}).bind(this));
|
||||
}.bind(this));
|
||||
|
||||
listen(this.interactions, CollectionEventType.ADD,
|
||||
/**
|
||||
@@ -787,13 +790,13 @@ PluggableMap.prototype.getInteractions = function() {
|
||||
|
||||
/**
|
||||
* Get the layergroup associated with this map.
|
||||
* @return {module:ol/layer/Group} A layer group containing the layers in this map.
|
||||
* @return {module:ol/layer/Group~Group} A layer group containing the layers in this map.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
PluggableMap.prototype.getLayerGroup = function() {
|
||||
return (
|
||||
/** @type {module:ol/layer/Group} */ (this.get(MapProperty.LAYERGROUP))
|
||||
/** @type {module:ol/layer/Group~Group} */ (this.get(MapProperty.LAYERGROUP))
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1307,7 +1310,8 @@ PluggableMap.prototype.renderFrame_ = function(time) {
|
||||
|
||||
/**
|
||||
* Sets the layergroup of this map.
|
||||
* @param {module:ol/layer/Group} layerGroup A layer group containing the layers in this map.
|
||||
* @param {module:ol/layer/Group~Group} layerGroup A layer group containing the layers in
|
||||
* this map.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
|
||||
@@ -27,18 +27,20 @@ const TileQueue = function(tilePriorityFunction, tileChangeCallback) {
|
||||
PriorityQueue.call(
|
||||
this,
|
||||
/**
|
||||
* @param {Array} element Element.
|
||||
* @return {number} Priority.
|
||||
*/
|
||||
* @param {Array} element Element.
|
||||
* @return {number} Priority.
|
||||
*/
|
||||
function(element) {
|
||||
return tilePriorityFunction.apply(null, element);
|
||||
},
|
||||
/**
|
||||
* @param {Array} element Element.
|
||||
* @return {string} Key.
|
||||
*/
|
||||
* @param {Array} element Element.
|
||||
* @return {string} Key.
|
||||
*/
|
||||
function(element) {
|
||||
return (/** @type {module:ol/Tile} */ (element[0]).getKey());
|
||||
return (
|
||||
/** @type {module:ol/Tile} */ (element[0]).getKey()
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -71,7 +73,8 @@ TileQueue.prototype.enqueue = function(element) {
|
||||
const added = PriorityQueue.prototype.enqueue.call(this, element);
|
||||
if (added) {
|
||||
const tile = element[0];
|
||||
listen(tile, EventType.CHANGE, this.handleTileChange, this);
|
||||
listen(tile, EventType.CHANGE,
|
||||
this.handleTileChange, this);
|
||||
}
|
||||
return added;
|
||||
};
|
||||
@@ -94,7 +97,8 @@ TileQueue.prototype.handleTileChange = function(event) {
|
||||
const state = tile.getState();
|
||||
if (state === TileState.LOADED || state === TileState.ERROR ||
|
||||
state === TileState.EMPTY || state === TileState.ABORT) {
|
||||
unlisten(tile, EventType.CHANGE, this.handleTileChange, this);
|
||||
unlisten(tile, EventType.CHANGE,
|
||||
this.handleTileChange, this);
|
||||
const tileKey = tile.getKey();
|
||||
if (tileKey in this.tilesLoadingKeys_) {
|
||||
delete this.tilesLoadingKeys_[tileKey];
|
||||
|
||||
@@ -9,7 +9,6 @@ import {listen, unlistenByKey} from './events.js';
|
||||
import {getHeight, getIntersection, getWidth} from './extent.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import {loadFeaturesXhr} from './featureloader.js';
|
||||
import {UNDEFINED} from './functions.js';
|
||||
|
||||
|
||||
/**
|
||||
@@ -41,13 +40,13 @@ import {UNDEFINED} from './functions.js';
|
||||
* instantiate for source tiles.
|
||||
* @param {function(this: module:ol/source/VectorTile, module:ol/events/Event)} handleTileChange
|
||||
* Function to call when a source tile's state changes.
|
||||
* @param {number} zoom Integer zoom to render the tile for.
|
||||
* @param {module:ol/Tile~Options=} opt_options Tile options.
|
||||
*/
|
||||
const VectorImageTile = function(tileCoord, state, sourceRevision, format,
|
||||
tileLoadFunction, urlTileCoord, tileUrlFunction, sourceTileGrid, tileGrid,
|
||||
sourceTiles, pixelRatio, projection, tileClass, handleTileChange, zoom) {
|
||||
sourceTiles, pixelRatio, projection, tileClass, handleTileChange, opt_options) {
|
||||
|
||||
Tile.call(this, tileCoord, state, {transition: 0});
|
||||
Tile.call(this, tileCoord, state, opt_options);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -79,11 +78,6 @@ const VectorImageTile = function(tileCoord, state, sourceRevision, format,
|
||||
*/
|
||||
this.tileKeys = [];
|
||||
|
||||
/**
|
||||
* @type {module:ol/extent~Extent}
|
||||
*/
|
||||
this.extent = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
@@ -105,11 +99,9 @@ const VectorImageTile = function(tileCoord, state, sourceRevision, format,
|
||||
this.sourceTileListenerKeys_ = [];
|
||||
|
||||
if (urlTileCoord) {
|
||||
const extent = this.extent = tileGrid.getTileCoordExtent(urlTileCoord);
|
||||
const resolution = tileGrid.getResolution(zoom);
|
||||
const extent = tileGrid.getTileCoordExtent(urlTileCoord);
|
||||
const resolution = tileGrid.getResolution(tileCoord[0]);
|
||||
const sourceZ = sourceTileGrid.getZForResolution(resolution);
|
||||
const useLoadedOnly = zoom != tileCoord[0];
|
||||
let loadCount = 0;
|
||||
sourceTileGrid.forEachTileCoord(extent, sourceZ, function(sourceTileCoord) {
|
||||
let sharedExtent = getIntersection(extent,
|
||||
sourceTileGrid.getTileCoordExtent(sourceTileCoord));
|
||||
@@ -120,10 +112,9 @@ const VectorImageTile = function(tileCoord, state, sourceRevision, format,
|
||||
if (getWidth(sharedExtent) / resolution >= 0.5 &&
|
||||
getHeight(sharedExtent) / resolution >= 0.5) {
|
||||
// only include source tile if overlap is at least 1 pixel
|
||||
++loadCount;
|
||||
const sourceTileKey = sourceTileCoord.toString();
|
||||
let sourceTile = sourceTiles[sourceTileKey];
|
||||
if (!sourceTile && !useLoadedOnly) {
|
||||
if (!sourceTile) {
|
||||
const tileUrl = tileUrlFunction(sourceTileCoord, pixelRatio, projection);
|
||||
sourceTile = sourceTiles[sourceTileKey] = new tileClass(sourceTileCoord,
|
||||
tileUrl == undefined ? TileState.EMPTY : TileState.IDLE,
|
||||
@@ -132,29 +123,10 @@ const VectorImageTile = function(tileCoord, state, sourceRevision, format,
|
||||
this.sourceTileListenerKeys_.push(
|
||||
listen(sourceTile, EventType.CHANGE, handleTileChange));
|
||||
}
|
||||
if (sourceTile && (!useLoadedOnly || sourceTile.getState() == TileState.LOADED)) {
|
||||
sourceTile.consumers++;
|
||||
this.tileKeys.push(sourceTileKey);
|
||||
}
|
||||
sourceTile.consumers++;
|
||||
this.tileKeys.push(sourceTileKey);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (useLoadedOnly && loadCount == this.tileKeys.length) {
|
||||
this.finishLoading_();
|
||||
}
|
||||
|
||||
if (zoom <= tileCoord[0] && this.state != TileState.LOADED) {
|
||||
while (zoom > tileGrid.getMinZoom()) {
|
||||
const tile = new VectorImageTile(tileCoord, state, sourceRevision,
|
||||
format, tileLoadFunction, urlTileCoord, tileUrlFunction,
|
||||
sourceTileGrid, tileGrid, sourceTiles, pixelRatio, projection,
|
||||
tileClass, UNDEFINED, --zoom);
|
||||
if (tile.state == TileState.LOADED) {
|
||||
this.interimTile = tile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ const VectorTile = function(tileCoord, state, src, format, tileLoadFunction, opt
|
||||
* @private
|
||||
* @type {module:ol/proj/Projection}
|
||||
*/
|
||||
this.projection_ = null;
|
||||
this.projection_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
||||
@@ -280,7 +280,8 @@ View.prototype.applyOptions_ = function(options) {
|
||||
properties[ViewProperty.CENTER] = options.center !== undefined ?
|
||||
options.center : null;
|
||||
|
||||
const resolutionConstraintInfo = createResolutionConstraint(options);
|
||||
const resolutionConstraintInfo = createResolutionConstraint(
|
||||
options);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -637,8 +638,10 @@ View.prototype.calculateCenterZoom = function(resolution, anchor) {
|
||||
const currentCenter = this.getCenter();
|
||||
const currentResolution = this.getResolution();
|
||||
if (currentCenter !== undefined && currentResolution !== undefined) {
|
||||
const x = anchor[0] - resolution * (anchor[0] - currentCenter[0]) / currentResolution;
|
||||
const y = anchor[1] - resolution * (anchor[1] - currentCenter[1]) / currentResolution;
|
||||
const x = anchor[0] -
|
||||
resolution * (anchor[0] - currentCenter[0]) / currentResolution;
|
||||
const y = anchor[1] -
|
||||
resolution * (anchor[1] - currentCenter[1]) / currentResolution;
|
||||
center = [x, y];
|
||||
}
|
||||
return center;
|
||||
@@ -919,7 +922,8 @@ View.prototype.getValueForResolutionFunction = function(opt_power) {
|
||||
* @return {number} Value.
|
||||
*/
|
||||
function(resolution) {
|
||||
const value = (Math.log(maxResolution / resolution) / Math.log(power)) / max;
|
||||
const value =
|
||||
(Math.log(maxResolution / resolution) / Math.log(power)) / max;
|
||||
return value;
|
||||
});
|
||||
};
|
||||
@@ -1171,7 +1175,7 @@ View.prototype.setCenter = function(center) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {module:ol/ViewHint} hint Hint.
|
||||
* @param {module:ol/ViewHint~ViewHint} hint Hint.
|
||||
* @param {number} delta Delta.
|
||||
* @return {number} New value.
|
||||
*/
|
||||
|
||||
@@ -8,9 +8,8 @@ import {toString} from './color.js';
|
||||
* A type accepted by CanvasRenderingContext2D.fillStyle
|
||||
* or CanvasRenderingContext2D.strokeStyle.
|
||||
* Represents a color, pattern, or gradient. The origin for patterns and
|
||||
* gradients as fill style is an increment of 512 css pixels from map coordinate
|
||||
* `[0, 0]`. For seamless repeat patterns, width and height of the pattern image
|
||||
* must be a factor of two (2, 4, 8, ..., 512).
|
||||
* gradients as fill style is the top-left corner of the extent of the geometry
|
||||
* being filled.
|
||||
*
|
||||
* @typedef {string|CanvasPattern|CanvasGradient} ColorLike
|
||||
* @api
|
||||
|
||||
@@ -231,13 +231,6 @@ Attribution.prototype.updateElement_ = function(frameState) {
|
||||
}
|
||||
|
||||
const attributions = this.getSourceAttributions_(frameState);
|
||||
|
||||
const visible = attributions.length > 0;
|
||||
if (this.renderedVisible_ != visible) {
|
||||
this.element.style.display = visible ? '' : 'none';
|
||||
this.renderedVisible_ = visible;
|
||||
}
|
||||
|
||||
if (equals(attributions, this.renderedAttributions_)) {
|
||||
return;
|
||||
}
|
||||
@@ -251,6 +244,13 @@ Attribution.prototype.updateElement_ = function(frameState) {
|
||||
this.ulElement_.appendChild(element);
|
||||
}
|
||||
|
||||
|
||||
const visible = attributions.length > 0;
|
||||
if (this.renderedVisible_ != visible) {
|
||||
this.element.style.display = visible ? '' : 'none';
|
||||
this.renderedVisible_ = visible;
|
||||
}
|
||||
|
||||
this.renderedAttributions_ = attributions;
|
||||
};
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import {listen, unlistenByKey} from '../events.js';
|
||||
*
|
||||
* @constructor
|
||||
* @extends {module:ol/Object}
|
||||
* @implements {oli.control.Control}
|
||||
* @param {module:ol/control/Control~Options} options Control options.
|
||||
* @api
|
||||
*/
|
||||
@@ -115,6 +116,7 @@ Control.prototype.getMap = function() {
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {module:ol/PluggableMap} map Map.
|
||||
* @override
|
||||
* @api
|
||||
*/
|
||||
Control.prototype.setMap = function(map) {
|
||||
|
||||
@@ -38,8 +38,8 @@ const MIN_RATIO = 0.1;
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-overviewmap'] CSS class name.
|
||||
* @property {boolean} [collapsed=true] Whether the control should start collapsed or not (expanded).
|
||||
* @property {boolean} [collapsed=true] Whether the control should start collapsed
|
||||
* or not (expanded).
|
||||
* @property {string|Element} [collapseLabel='«'] Text label to use for the
|
||||
* expanded overviewmap button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {boolean} [collapsible=true] Whether the control can be collapsed or not.
|
||||
@@ -151,9 +151,9 @@ const OverviewMap = function(opt_options) {
|
||||
/**
|
||||
* @param {module:ol/layer/Layer} layer Layer.
|
||||
*/
|
||||
(function(layer) {
|
||||
function(layer) {
|
||||
ovmap.addLayer(layer);
|
||||
}).bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
const box = document.createElement('DIV');
|
||||
|
||||
@@ -36,7 +36,6 @@ import Zoom from './Zoom.js';
|
||||
* Defaults options.
|
||||
* @return {module:ol/Collection.<module:ol/control/Control>}
|
||||
* Controls.
|
||||
* @function module:ol/control.defaults
|
||||
* @api
|
||||
*/
|
||||
export function defaults(opt_options) {
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
* @return {CanvasRenderingContext2D} The context.
|
||||
*/
|
||||
export function createCanvasContext2D(opt_width, opt_height) {
|
||||
const canvas = /** @type {HTMLCanvasElement} */ (document.createElement('CANVAS'));
|
||||
const canvas = document.createElement('CANVAS');
|
||||
if (opt_width) {
|
||||
canvas.width = opt_width;
|
||||
}
|
||||
if (opt_height) {
|
||||
canvas.height = opt_height;
|
||||
}
|
||||
return /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
|
||||
return canvas.getContext('2d');
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user