Automated class transform
npx lebab --replace src --transform class
This commit is contained in:
@@ -47,163 +47,272 @@ import {visibleAtResolution} from '../layer/Layer.js';
|
||||
* @param {module:ol/control/Attribution~Options=} opt_options Attribution options.
|
||||
* @api
|
||||
*/
|
||||
const Attribution = function(opt_options) {
|
||||
class Attribution {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.ulElement_ = document.createElement('UL');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ = options.collapsible !== undefined ?
|
||||
options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-attribution';
|
||||
|
||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
|
||||
|
||||
const collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB';
|
||||
|
||||
if (typeof collapseLabel === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.collapseLabel_ = document.createElement('span');
|
||||
this.collapseLabel_.textContent = collapseLabel;
|
||||
} else {
|
||||
this.collapseLabel_ = collapseLabel;
|
||||
}
|
||||
this.ulElement_ = document.createElement('UL');
|
||||
|
||||
const label = options.label !== undefined ? options.label : 'i';
|
||||
|
||||
if (typeof label === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ = options.collapsible !== undefined ?
|
||||
options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-attribution';
|
||||
|
||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
|
||||
|
||||
const collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB';
|
||||
|
||||
if (typeof collapseLabel === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.collapseLabel_ = document.createElement('span');
|
||||
this.collapseLabel_.textContent = collapseLabel;
|
||||
} else {
|
||||
this.collapseLabel_ = collapseLabel;
|
||||
}
|
||||
|
||||
const label = options.label !== undefined ? options.label : 'i';
|
||||
|
||||
if (typeof label === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
}
|
||||
|
||||
|
||||
const activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||
this.collapseLabel_ : this.label_;
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(activeLabel);
|
||||
|
||||
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.ulElement_);
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* A list of currently rendered resolutions.
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
this.renderedAttributions_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
const activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||
this.collapseLabel_ : this.label_;
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(activeLabel);
|
||||
|
||||
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.ulElement_);
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* A list of currently rendered resolutions.
|
||||
* @type {Array.<string>}
|
||||
* Get a list of visible attributions.
|
||||
* @param {module:ol/PluggableMap~FrameState} frameState Frame state.
|
||||
* @return {Array.<string>} Attributions.
|
||||
* @private
|
||||
*/
|
||||
this.renderedAttributions_ = [];
|
||||
getSourceAttributions_(frameState) {
|
||||
/**
|
||||
* Used to determine if an attribution already exists.
|
||||
* @type {!Object.<string, boolean>}
|
||||
*/
|
||||
const lookup = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = true;
|
||||
/**
|
||||
* A list of visible attributions.
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
const visibleAttributions = [];
|
||||
|
||||
};
|
||||
const layerStatesArray = frameState.layerStatesArray;
|
||||
const resolution = frameState.viewState.resolution;
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
const layerState = layerStatesArray[i];
|
||||
if (!visibleAtResolution(layerState, resolution)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inherits(Attribution, Control);
|
||||
const source = layerState.layer.getSource();
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const attributionGetter = source.getAttributions();
|
||||
if (!attributionGetter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of visible attributions.
|
||||
* @param {module:ol/PluggableMap~FrameState} frameState Frame state.
|
||||
* @return {Array.<string>} Attributions.
|
||||
* @private
|
||||
*/
|
||||
Attribution.prototype.getSourceAttributions_ = function(frameState) {
|
||||
/**
|
||||
* Used to determine if an attribution already exists.
|
||||
* @type {!Object.<string, boolean>}
|
||||
*/
|
||||
const lookup = {};
|
||||
const attributions = attributionGetter(frameState);
|
||||
if (!attributions) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of visible attributions.
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
const visibleAttributions = [];
|
||||
|
||||
const layerStatesArray = frameState.layerStatesArray;
|
||||
const resolution = frameState.viewState.resolution;
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
const layerState = layerStatesArray[i];
|
||||
if (!visibleAtResolution(layerState, resolution)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const source = layerState.layer.getSource();
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const attributionGetter = source.getAttributions();
|
||||
if (!attributionGetter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const attributions = attributionGetter(frameState);
|
||||
if (!attributions) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(attributions)) {
|
||||
for (let j = 0, jj = attributions.length; j < jj; ++j) {
|
||||
if (!(attributions[j] in lookup)) {
|
||||
visibleAttributions.push(attributions[j]);
|
||||
lookup[attributions[j]] = true;
|
||||
if (Array.isArray(attributions)) {
|
||||
for (let j = 0, jj = attributions.length; j < jj; ++j) {
|
||||
if (!(attributions[j] in lookup)) {
|
||||
visibleAttributions.push(attributions[j]);
|
||||
lookup[attributions[j]] = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(attributions in lookup)) {
|
||||
visibleAttributions.push(attributions);
|
||||
lookup[attributions] = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(attributions in lookup)) {
|
||||
visibleAttributions.push(attributions);
|
||||
lookup[attributions] = true;
|
||||
}
|
||||
return visibleAttributions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {?module:ol/PluggableMap~FrameState} frameState Frame state.
|
||||
*/
|
||||
updateElement_(frameState) {
|
||||
if (!frameState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
removeChildren(this.ulElement_);
|
||||
|
||||
// append the attributions
|
||||
for (let i = 0, ii = attributions.length; i < ii; ++i) {
|
||||
const element = document.createElement('LI');
|
||||
element.innerHTML = attributions[i];
|
||||
this.ulElement_.appendChild(element);
|
||||
}
|
||||
|
||||
this.renderedAttributions_ = attributions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleToggle_() {
|
||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||
if (this.collapsed_) {
|
||||
replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if the attribution is collapsible, `false` otherwise.
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
getCollapsible() {
|
||||
return this.collapsible_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the attribution should be collapsible.
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
setCollapsible(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
this.element.classList.toggle('ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
}
|
||||
return visibleAttributions;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collapse or expand the attribution according to the passed parameter. Will
|
||||
* not do anything if the attribution isn't collapsible or if the current
|
||||
* collapsed state is already the one requested.
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
setCollapsed(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` when the attribution is currently collapsed or `false`
|
||||
* otherwise.
|
||||
* @return {boolean} True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
getCollapsed() {
|
||||
return this.collapsed_;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Attribution, Control);
|
||||
|
||||
|
||||
/**
|
||||
@@ -217,117 +326,4 @@ export function render(mapEvent) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {?module:ol/PluggableMap~FrameState} frameState Frame state.
|
||||
*/
|
||||
Attribution.prototype.updateElement_ = function(frameState) {
|
||||
if (!frameState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
removeChildren(this.ulElement_);
|
||||
|
||||
// append the attributions
|
||||
for (let i = 0, ii = attributions.length; i < ii; ++i) {
|
||||
const element = document.createElement('LI');
|
||||
element.innerHTML = attributions[i];
|
||||
this.ulElement_.appendChild(element);
|
||||
}
|
||||
|
||||
this.renderedAttributions_ = attributions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
Attribution.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Attribution.prototype.handleToggle_ = function() {
|
||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||
if (this.collapsed_) {
|
||||
replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return `true` if the attribution is collapsible, `false` otherwise.
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
Attribution.prototype.getCollapsible = function() {
|
||||
return this.collapsible_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set whether the attribution should be collapsible.
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
Attribution.prototype.setCollapsible = function(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
this.element.classList.toggle('ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Collapse or expand the attribution according to the passed parameter. Will
|
||||
* not do anything if the attribution isn't collapsible or if the current
|
||||
* collapsed state is already the one requested.
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
Attribution.prototype.setCollapsed = function(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return `true` when the attribution is currently collapsed or `false`
|
||||
* otherwise.
|
||||
* @return {boolean} True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
Attribution.prototype.getCollapsed = function() {
|
||||
return this.collapsed_;
|
||||
};
|
||||
export default Attribution;
|
||||
|
||||
@@ -49,108 +49,108 @@ import {listen, unlistenByKey} from '../events.js';
|
||||
* @param {module:ol/control/Control~Options} options Control options.
|
||||
* @api
|
||||
*/
|
||||
const Control = function(options) {
|
||||
class Control {
|
||||
constructor(options) {
|
||||
|
||||
BaseObject.call(this);
|
||||
BaseObject.call(this);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Element}
|
||||
*/
|
||||
this.element = options.element ? options.element : null;
|
||||
/**
|
||||
* @protected
|
||||
* @type {Element}
|
||||
*/
|
||||
this.element = options.element ? options.element : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.target_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.target_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/PluggableMap}
|
||||
*/
|
||||
this.map_ = null;
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/PluggableMap}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Array.<module:ol/events~EventsKey>}
|
||||
*/
|
||||
this.listenerKeys = [];
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Array.<module:ol/events~EventsKey>}
|
||||
*/
|
||||
this.listenerKeys = [];
|
||||
|
||||
/**
|
||||
* @type {function(module:ol/MapEvent)}
|
||||
*/
|
||||
this.render = options.render ? options.render : UNDEFINED;
|
||||
/**
|
||||
* @type {function(module:ol/MapEvent)}
|
||||
*/
|
||||
this.render = options.render ? options.render : UNDEFINED;
|
||||
|
||||
if (options.target) {
|
||||
this.setTarget(options.target);
|
||||
}
|
||||
if (options.target) {
|
||||
this.setTarget(options.target);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
disposeInternal() {
|
||||
removeNode(this.element);
|
||||
BaseObject.prototype.disposeInternal.call(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map associated with this control.
|
||||
* @return {module:ol/PluggableMap} Map.
|
||||
* @api
|
||||
*/
|
||||
getMap() {
|
||||
return this.map_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {module:ol/PluggableMap} map Map.
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
if (this.map_) {
|
||||
removeNode(this.element);
|
||||
}
|
||||
for (let i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
|
||||
unlistenByKey(this.listenerKeys[i]);
|
||||
}
|
||||
this.listenerKeys.length = 0;
|
||||
this.map_ = map;
|
||||
if (this.map_) {
|
||||
const target = this.target_ ?
|
||||
this.target_ : map.getOverlayContainerStopEvent();
|
||||
target.appendChild(this.element);
|
||||
if (this.render !== UNDEFINED) {
|
||||
this.listenerKeys.push(listen(map,
|
||||
MapEventType.POSTRENDER, this.render, this));
|
||||
}
|
||||
map.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to set a target element for the control. It has no
|
||||
* effect if it is called after the control has been added to the map (i.e.
|
||||
* after `setMap` is called on the control). If no `target` is set in the
|
||||
* options passed to the control constructor and if `setTarget` is not called
|
||||
* then the control is added to the map's overlay container.
|
||||
* @param {Element|string} target Target.
|
||||
* @api
|
||||
*/
|
||||
setTarget(target) {
|
||||
this.target_ = typeof target === 'string' ?
|
||||
document.getElementById(target) :
|
||||
target;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Control, BaseObject);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
Control.prototype.disposeInternal = function() {
|
||||
removeNode(this.element);
|
||||
BaseObject.prototype.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the map associated with this control.
|
||||
* @return {module:ol/PluggableMap} Map.
|
||||
* @api
|
||||
*/
|
||||
Control.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {module:ol/PluggableMap} map Map.
|
||||
* @api
|
||||
*/
|
||||
Control.prototype.setMap = function(map) {
|
||||
if (this.map_) {
|
||||
removeNode(this.element);
|
||||
}
|
||||
for (let i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
|
||||
unlistenByKey(this.listenerKeys[i]);
|
||||
}
|
||||
this.listenerKeys.length = 0;
|
||||
this.map_ = map;
|
||||
if (this.map_) {
|
||||
const target = this.target_ ?
|
||||
this.target_ : map.getOverlayContainerStopEvent();
|
||||
target.appendChild(this.element);
|
||||
if (this.render !== UNDEFINED) {
|
||||
this.listenerKeys.push(listen(map,
|
||||
MapEventType.POSTRENDER, this.render, this));
|
||||
}
|
||||
map.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This function is used to set a target element for the control. It has no
|
||||
* effect if it is called after the control has been added to the map (i.e.
|
||||
* after `setMap` is called on the control). If no `target` is set in the
|
||||
* options passed to the control constructor and if `setTarget` is not called
|
||||
* then the control is added to the map's overlay container.
|
||||
* @param {Element|string} target Target.
|
||||
* @api
|
||||
*/
|
||||
Control.prototype.setTarget = function(target) {
|
||||
this.target_ = typeof target === 'string' ?
|
||||
document.getElementById(target) :
|
||||
target;
|
||||
};
|
||||
export default Control;
|
||||
|
||||
@@ -67,149 +67,148 @@ const getChangeType = (function() {
|
||||
* @param {module:ol/control/FullScreen~Options=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
const FullScreen = function(opt_options) {
|
||||
class FullScreen {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.cssClassName_ = options.className !== undefined ? options.className :
|
||||
'ol-full-screen';
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u2922';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.labelNode_ = typeof label === 'string' ?
|
||||
document.createTextNode(label) : label;
|
||||
|
||||
const labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.labelActiveNode_ = typeof labelActive === 'string' ?
|
||||
document.createTextNode(labelActive) : labelActive;
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
const button = document.createElement('button');
|
||||
button.className = this.cssClassName_ + '-' + isFullScreen();
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(this.labelNode_);
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
this.handleClick_, this);
|
||||
|
||||
const cssClasses = this.cssClassName_ + ' ' + CLASS_UNSELECTABLE +
|
||||
' ' + CLASS_CONTROL + ' ' +
|
||||
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.keys_ = options.keys !== undefined ? options.keys : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element|string|undefined}
|
||||
*/
|
||||
this.source_ = options.source;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleFullScreen_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.cssClassName_ = options.className !== undefined ? options.className :
|
||||
'ol-full-screen';
|
||||
handleFullScreen_() {
|
||||
if (!isFullScreenSupported()) {
|
||||
return;
|
||||
}
|
||||
const map = this.getMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
if (isFullScreen()) {
|
||||
exitFullScreen();
|
||||
} else {
|
||||
let element;
|
||||
if (this.source_) {
|
||||
element = typeof this.source_ === 'string' ?
|
||||
document.getElementById(this.source_) :
|
||||
this.source_;
|
||||
} else {
|
||||
element = map.getTargetElement();
|
||||
}
|
||||
if (this.keys_) {
|
||||
requestFullScreenWithKeys(element);
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u2922';
|
||||
} else {
|
||||
requestFullScreen(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.labelNode_ = typeof label === 'string' ?
|
||||
document.createTextNode(label) : label;
|
||||
|
||||
const labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';
|
||||
handleFullScreenChange_() {
|
||||
const button = this.element.firstElementChild;
|
||||
const map = this.getMap();
|
||||
if (isFullScreen()) {
|
||||
button.className = this.cssClassName_ + '-true';
|
||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
} else {
|
||||
button.className = this.cssClassName_ + '-false';
|
||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
}
|
||||
if (map) {
|
||||
map.updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
this.labelActiveNode_ = typeof labelActive === 'string' ?
|
||||
document.createTextNode(labelActive) : labelActive;
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
const button = document.createElement('button');
|
||||
button.className = this.cssClassName_ + '-' + isFullScreen();
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(this.labelNode_);
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
this.handleClick_, this);
|
||||
|
||||
const cssClasses = this.cssClassName_ + ' ' + CLASS_UNSELECTABLE +
|
||||
' ' + CLASS_CONTROL + ' ' +
|
||||
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.keys_ = options.keys !== undefined ? options.keys : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element|string|undefined}
|
||||
*/
|
||||
this.source_ = options.source;
|
||||
|
||||
};
|
||||
setMap(map) {
|
||||
Control.prototype.setMap.call(this, map);
|
||||
if (map) {
|
||||
this.listenerKeys.push(listen(document,
|
||||
getChangeType(),
|
||||
this.handleFullScreenChange_, this)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(FullScreen, Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
FullScreen.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleFullScreen_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FullScreen.prototype.handleFullScreen_ = function() {
|
||||
if (!isFullScreenSupported()) {
|
||||
return;
|
||||
}
|
||||
const map = this.getMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
if (isFullScreen()) {
|
||||
exitFullScreen();
|
||||
} else {
|
||||
let element;
|
||||
if (this.source_) {
|
||||
element = typeof this.source_ === 'string' ?
|
||||
document.getElementById(this.source_) :
|
||||
this.source_;
|
||||
} else {
|
||||
element = map.getTargetElement();
|
||||
}
|
||||
if (this.keys_) {
|
||||
requestFullScreenWithKeys(element);
|
||||
|
||||
} else {
|
||||
requestFullScreen(element);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FullScreen.prototype.handleFullScreenChange_ = function() {
|
||||
const button = this.element.firstElementChild;
|
||||
const map = this.getMap();
|
||||
if (isFullScreen()) {
|
||||
button.className = this.cssClassName_ + '-true';
|
||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
} else {
|
||||
button.className = this.cssClassName_ + '-false';
|
||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
}
|
||||
if (map) {
|
||||
map.updateSize();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
FullScreen.prototype.setMap = function(map) {
|
||||
Control.prototype.setMap.call(this, map);
|
||||
if (map) {
|
||||
this.listenerKeys.push(listen(document,
|
||||
getChangeType(),
|
||||
this.handleFullScreenChange_, this)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean} Fullscreen is supported by the current platform.
|
||||
*/
|
||||
|
||||
@@ -52,67 +52,197 @@ const COORDINATE_FORMAT = 'coordinateFormat';
|
||||
* options.
|
||||
* @api
|
||||
*/
|
||||
const MousePosition = function(opt_options) {
|
||||
class MousePosition {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const element = document.createElement('DIV');
|
||||
element.className = options.className !== undefined ? options.className : 'ol-mouse-position';
|
||||
const element = document.createElement('DIV');
|
||||
element.className = options.className !== undefined ? options.className : 'ol-mouse-position';
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
listen(this,
|
||||
getChangeEventType(PROJECTION),
|
||||
this.handleProjectionChanged_, this);
|
||||
listen(this,
|
||||
getChangeEventType(PROJECTION),
|
||||
this.handleProjectionChanged_, this);
|
||||
|
||||
if (options.coordinateFormat) {
|
||||
this.setCoordinateFormat(options.coordinateFormat);
|
||||
}
|
||||
if (options.projection) {
|
||||
this.setProjection(options.projection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.undefinedHTML_ = 'undefinedHTML' in options ? options.undefinedHTML : ' ';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderOnMouseOut_ = !!this.undefinedHTML_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = element.innerHTML;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/proj/Projection}
|
||||
*/
|
||||
this.mapProjection_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?module:ol/proj~TransformFunction}
|
||||
*/
|
||||
this.transform_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol~Pixel}
|
||||
*/
|
||||
this.lastMouseMovePixel_ = null;
|
||||
|
||||
if (options.coordinateFormat) {
|
||||
this.setCoordinateFormat(options.coordinateFormat);
|
||||
}
|
||||
if (options.projection) {
|
||||
this.setProjection(options.projection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.undefinedHTML_ = 'undefinedHTML' in options ? options.undefinedHTML : ' ';
|
||||
handleProjectionChanged_() {
|
||||
this.transform_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
* Return the coordinate format type used to render the current position or
|
||||
* undefined.
|
||||
* @return {module:ol/coordinate~CoordinateFormat|undefined} The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
this.renderOnMouseOut_ = !!this.undefinedHTML_;
|
||||
getCoordinateFormat() {
|
||||
return (
|
||||
/** @type {module:ol/coordinate~CoordinateFormat|undefined} */ (this.get(COORDINATE_FORMAT))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
* Return the projection that is used to report the mouse position.
|
||||
* @return {module:ol/proj/Projection|undefined} The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
this.renderedHTML_ = element.innerHTML;
|
||||
getProjection() {
|
||||
return (
|
||||
/** @type {module:ol/proj/Projection|undefined} */ (this.get(PROJECTION))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol/proj/Projection}
|
||||
* @param {Event} event Browser event.
|
||||
* @protected
|
||||
*/
|
||||
this.mapProjection_ = null;
|
||||
handleMouseMove(event) {
|
||||
const map = this.getMap();
|
||||
this.lastMouseMovePixel_ = map.getEventPixel(event);
|
||||
this.updateHTML_(this.lastMouseMovePixel_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?module:ol/proj~TransformFunction}
|
||||
* @param {Event} event Browser event.
|
||||
* @protected
|
||||
*/
|
||||
this.transform_ = null;
|
||||
handleMouseOut(event) {
|
||||
this.updateHTML_(null);
|
||||
this.lastMouseMovePixel_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:ol~Pixel}
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
this.lastMouseMovePixel_ = null;
|
||||
setMap(map) {
|
||||
Control.prototype.setMap.call(this, map);
|
||||
if (map) {
|
||||
const viewport = map.getViewport();
|
||||
this.listenerKeys.push(
|
||||
listen(viewport, EventType.MOUSEMOVE, this.handleMouseMove, this)
|
||||
);
|
||||
if (this.renderOnMouseOut_) {
|
||||
this.listenerKeys.push(
|
||||
listen(viewport, EventType.MOUSEOUT, this.handleMouseOut, this)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
/**
|
||||
* Set the coordinate format type used to render the current position.
|
||||
* @param {module:ol/coordinate~CoordinateFormat} format The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setCoordinateFormat(format) {
|
||||
this.set(COORDINATE_FORMAT, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection that is used to report the mouse position.
|
||||
* @param {module:ol/proj~ProjectionLike} projection The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setProjection(projection) {
|
||||
this.set(PROJECTION, getProjection(projection));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?module:ol~Pixel} pixel Pixel.
|
||||
* @private
|
||||
*/
|
||||
updateHTML_(pixel) {
|
||||
let html = this.undefinedHTML_;
|
||||
if (pixel && this.mapProjection_) {
|
||||
if (!this.transform_) {
|
||||
const projection = this.getProjection();
|
||||
if (projection) {
|
||||
this.transform_ = getTransformFromProjections(
|
||||
this.mapProjection_, projection);
|
||||
} else {
|
||||
this.transform_ = identityTransform;
|
||||
}
|
||||
}
|
||||
const map = this.getMap();
|
||||
const coordinate = map.getCoordinateFromPixel(pixel);
|
||||
if (coordinate) {
|
||||
this.transform_(coordinate, coordinate);
|
||||
const coordinateFormat = this.getCoordinateFormat();
|
||||
if (coordinateFormat) {
|
||||
html = coordinateFormat(coordinate);
|
||||
} else {
|
||||
html = coordinate.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.renderedHTML_ || html !== this.renderedHTML_) {
|
||||
this.element.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(MousePosition, Control);
|
||||
|
||||
@@ -137,141 +267,4 @@ export function render(mapEvent) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
MousePosition.prototype.handleProjectionChanged_ = function() {
|
||||
this.transform_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the coordinate format type used to render the current position or
|
||||
* undefined.
|
||||
* @return {module:ol/coordinate~CoordinateFormat|undefined} The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
MousePosition.prototype.getCoordinateFormat = function() {
|
||||
return (
|
||||
/** @type {module:ol/coordinate~CoordinateFormat|undefined} */ (this.get(COORDINATE_FORMAT))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the projection that is used to report the mouse position.
|
||||
* @return {module:ol/proj/Projection|undefined} The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
MousePosition.prototype.getProjection = function() {
|
||||
return (
|
||||
/** @type {module:ol/proj/Projection|undefined} */ (this.get(PROJECTION))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Event} event Browser event.
|
||||
* @protected
|
||||
*/
|
||||
MousePosition.prototype.handleMouseMove = function(event) {
|
||||
const map = this.getMap();
|
||||
this.lastMouseMovePixel_ = map.getEventPixel(event);
|
||||
this.updateHTML_(this.lastMouseMovePixel_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Event} event Browser event.
|
||||
* @protected
|
||||
*/
|
||||
MousePosition.prototype.handleMouseOut = function(event) {
|
||||
this.updateHTML_(null);
|
||||
this.lastMouseMovePixel_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
MousePosition.prototype.setMap = function(map) {
|
||||
Control.prototype.setMap.call(this, map);
|
||||
if (map) {
|
||||
const viewport = map.getViewport();
|
||||
this.listenerKeys.push(
|
||||
listen(viewport, EventType.MOUSEMOVE, this.handleMouseMove, this)
|
||||
);
|
||||
if (this.renderOnMouseOut_) {
|
||||
this.listenerKeys.push(
|
||||
listen(viewport, EventType.MOUSEOUT, this.handleMouseOut, this)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the coordinate format type used to render the current position.
|
||||
* @param {module:ol/coordinate~CoordinateFormat} format The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
MousePosition.prototype.setCoordinateFormat = function(format) {
|
||||
this.set(COORDINATE_FORMAT, format);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the projection that is used to report the mouse position.
|
||||
* @param {module:ol/proj~ProjectionLike} projection The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
MousePosition.prototype.setProjection = function(projection) {
|
||||
this.set(PROJECTION, getProjection(projection));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?module:ol~Pixel} pixel Pixel.
|
||||
* @private
|
||||
*/
|
||||
MousePosition.prototype.updateHTML_ = function(pixel) {
|
||||
let html = this.undefinedHTML_;
|
||||
if (pixel && this.mapProjection_) {
|
||||
if (!this.transform_) {
|
||||
const projection = this.getProjection();
|
||||
if (projection) {
|
||||
this.transform_ = getTransformFromProjections(
|
||||
this.mapProjection_, projection);
|
||||
} else {
|
||||
this.transform_ = identityTransform;
|
||||
}
|
||||
}
|
||||
const map = this.getMap();
|
||||
const coordinate = map.getCoordinateFromPixel(pixel);
|
||||
if (coordinate) {
|
||||
this.transform_(coordinate, coordinate);
|
||||
const coordinateFormat = this.getCoordinateFormat();
|
||||
if (coordinateFormat) {
|
||||
html = coordinateFormat(coordinate);
|
||||
} else {
|
||||
html = coordinate.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.renderedHTML_ || html !== this.renderedHTML_) {
|
||||
this.element.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default MousePosition;
|
||||
|
||||
@@ -66,258 +66,506 @@ const MIN_RATIO = 0.1;
|
||||
* @param {module:ol/control/OverviewMap~Options=} opt_options OverviewMap options.
|
||||
* @api
|
||||
*/
|
||||
const OverviewMap = function(opt_options) {
|
||||
class OverviewMap {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ = options.collapsible !== undefined ?
|
||||
options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-overviewmap';
|
||||
|
||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Overview map';
|
||||
|
||||
const collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00AB';
|
||||
|
||||
if (typeof collapseLabel === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapseLabel_ = document.createElement('span');
|
||||
this.collapseLabel_.textContent = collapseLabel;
|
||||
} else {
|
||||
this.collapseLabel_ = collapseLabel;
|
||||
}
|
||||
this.collapsible_ = options.collapsible !== undefined ?
|
||||
options.collapsible : true;
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u00BB';
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-overviewmap';
|
||||
|
||||
if (typeof label === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
}
|
||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Overview map';
|
||||
|
||||
const activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||
this.collapseLabel_ : this.label_;
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(activeLabel);
|
||||
const collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00AB';
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
this.handleClick_, this);
|
||||
|
||||
/**
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.ovmapDiv_ = document.createElement('DIV');
|
||||
this.ovmapDiv_.className = 'ol-overviewmap-map';
|
||||
|
||||
/**
|
||||
* @type {module:ol/Map}
|
||||
* @private
|
||||
*/
|
||||
this.ovmap_ = new Map({
|
||||
controls: new Collection(),
|
||||
interactions: new Collection(),
|
||||
view: options.view
|
||||
});
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (options.layers) {
|
||||
options.layers.forEach(
|
||||
if (typeof collapseLabel === 'string') {
|
||||
/**
|
||||
* @param {module:ol/layer/Layer} layer Layer.
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
(function(layer) {
|
||||
ovmap.addLayer(layer);
|
||||
}).bind(this));
|
||||
}
|
||||
this.collapseLabel_ = document.createElement('span');
|
||||
this.collapseLabel_.textContent = collapseLabel;
|
||||
} else {
|
||||
this.collapseLabel_ = collapseLabel;
|
||||
}
|
||||
|
||||
const box = document.createElement('DIV');
|
||||
box.className = 'ol-overviewmap-box';
|
||||
box.style.boxSizing = 'border-box';
|
||||
const label = options.label !== undefined ? options.label : '\u00BB';
|
||||
|
||||
|
||||
if (typeof label === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
}
|
||||
|
||||
const activeLabel = (this.collapsible_ && !this.collapsed_) ?
|
||||
this.collapseLabel_ : this.label_;
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(activeLabel);
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
this.handleClick_, this);
|
||||
|
||||
/**
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.ovmapDiv_ = document.createElement('DIV');
|
||||
this.ovmapDiv_.className = 'ol-overviewmap-map';
|
||||
|
||||
/**
|
||||
* @type {module:ol/Map}
|
||||
* @private
|
||||
*/
|
||||
this.ovmap_ = new Map({
|
||||
controls: new Collection(),
|
||||
interactions: new Collection(),
|
||||
view: options.view
|
||||
});
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (options.layers) {
|
||||
options.layers.forEach(
|
||||
/**
|
||||
* @param {module:ol/layer/Layer} layer Layer.
|
||||
*/
|
||||
(function(layer) {
|
||||
ovmap.addLayer(layer);
|
||||
}).bind(this));
|
||||
}
|
||||
|
||||
const box = document.createElement('DIV');
|
||||
box.className = 'ol-overviewmap-box';
|
||||
box.style.boxSizing = 'border-box';
|
||||
|
||||
/**
|
||||
* @type {module:ol/Overlay}
|
||||
* @private
|
||||
*/
|
||||
this.boxOverlay_ = new Overlay({
|
||||
position: [0, 0],
|
||||
positioning: OverlayPositioning.BOTTOM_LEFT,
|
||||
element: box
|
||||
});
|
||||
this.ovmap_.addOverlay(this.boxOverlay_);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.ovmapDiv_);
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/* Interactive map */
|
||||
|
||||
const scope = this;
|
||||
|
||||
const overlay = this.boxOverlay_;
|
||||
const overlayBox = this.boxOverlay_.getElement();
|
||||
|
||||
/* Functions definition */
|
||||
|
||||
const computeDesiredMousePosition = function(mousePosition) {
|
||||
return {
|
||||
clientX: mousePosition.clientX - (overlayBox.offsetWidth / 2),
|
||||
clientY: mousePosition.clientY + (overlayBox.offsetHeight / 2)
|
||||
};
|
||||
};
|
||||
|
||||
const move = function(event) {
|
||||
const coordinates = ovmap.getEventCoordinate(computeDesiredMousePosition(event));
|
||||
|
||||
overlay.setPosition(coordinates);
|
||||
};
|
||||
|
||||
const endMoving = function(event) {
|
||||
const coordinates = ovmap.getEventCoordinate(event);
|
||||
|
||||
scope.getMap().getView().setCenter(coordinates);
|
||||
|
||||
window.removeEventListener('mousemove', move);
|
||||
window.removeEventListener('mouseup', endMoving);
|
||||
};
|
||||
|
||||
/* Binding */
|
||||
|
||||
overlayBox.addEventListener('mousedown', function() {
|
||||
window.addEventListener('mousemove', move);
|
||||
window.addEventListener('mouseup', endMoving);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module:ol/Overlay}
|
||||
* @private
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
this.boxOverlay_ = new Overlay({
|
||||
position: [0, 0],
|
||||
positioning: OverlayPositioning.BOTTOM_LEFT,
|
||||
element: box
|
||||
});
|
||||
this.ovmap_.addOverlay(this.boxOverlay_);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.ovmapDiv_);
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/* Interactive map */
|
||||
|
||||
const scope = this;
|
||||
|
||||
const overlay = this.boxOverlay_;
|
||||
const overlayBox = this.boxOverlay_.getElement();
|
||||
|
||||
/* Functions definition */
|
||||
|
||||
const computeDesiredMousePosition = function(mousePosition) {
|
||||
return {
|
||||
clientX: mousePosition.clientX - (overlayBox.offsetWidth / 2),
|
||||
clientY: mousePosition.clientY + (overlayBox.offsetHeight / 2)
|
||||
};
|
||||
};
|
||||
|
||||
const move = function(event) {
|
||||
const coordinates = ovmap.getEventCoordinate(computeDesiredMousePosition(event));
|
||||
|
||||
overlay.setPosition(coordinates);
|
||||
};
|
||||
|
||||
const endMoving = function(event) {
|
||||
const coordinates = ovmap.getEventCoordinate(event);
|
||||
|
||||
scope.getMap().getView().setCenter(coordinates);
|
||||
|
||||
window.removeEventListener('mousemove', move);
|
||||
window.removeEventListener('mouseup', endMoving);
|
||||
};
|
||||
|
||||
/* Binding */
|
||||
|
||||
overlayBox.addEventListener('mousedown', function() {
|
||||
window.addEventListener('mousemove', move);
|
||||
window.addEventListener('mouseup', endMoving);
|
||||
});
|
||||
};
|
||||
|
||||
inherits(OverviewMap, Control);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
OverviewMap.prototype.setMap = function(map) {
|
||||
const oldMap = this.getMap();
|
||||
if (map === oldMap) {
|
||||
return;
|
||||
}
|
||||
if (oldMap) {
|
||||
const oldView = oldMap.getView();
|
||||
if (oldView) {
|
||||
this.unbindView_(oldView);
|
||||
setMap(map) {
|
||||
const oldMap = this.getMap();
|
||||
if (map === oldMap) {
|
||||
return;
|
||||
}
|
||||
this.ovmap_.setTarget(null);
|
||||
}
|
||||
Control.prototype.setMap.call(this, map);
|
||||
|
||||
if (map) {
|
||||
this.ovmap_.setTarget(this.ovmapDiv_);
|
||||
this.listenerKeys.push(listen(
|
||||
map, ObjectEventType.PROPERTYCHANGE,
|
||||
this.handleMapPropertyChange_, this));
|
||||
|
||||
// TODO: to really support map switching, this would need to be reworked
|
||||
if (this.ovmap_.getLayers().getLength() === 0) {
|
||||
this.ovmap_.setLayerGroup(map.getLayerGroup());
|
||||
if (oldMap) {
|
||||
const oldView = oldMap.getView();
|
||||
if (oldView) {
|
||||
this.unbindView_(oldView);
|
||||
}
|
||||
this.ovmap_.setTarget(null);
|
||||
}
|
||||
Control.prototype.setMap.call(this, map);
|
||||
|
||||
const view = map.getView();
|
||||
if (view) {
|
||||
this.bindView_(view);
|
||||
if (view.isDef()) {
|
||||
this.ovmap_.updateSize();
|
||||
this.resetExtent_();
|
||||
if (map) {
|
||||
this.ovmap_.setTarget(this.ovmapDiv_);
|
||||
this.listenerKeys.push(listen(
|
||||
map, ObjectEventType.PROPERTYCHANGE,
|
||||
this.handleMapPropertyChange_, this));
|
||||
|
||||
// TODO: to really support map switching, this would need to be reworked
|
||||
if (this.ovmap_.getLayers().getLength() === 0) {
|
||||
this.ovmap_.setLayerGroup(map.getLayerGroup());
|
||||
}
|
||||
|
||||
const view = map.getView();
|
||||
if (view) {
|
||||
this.bindView_(view);
|
||||
if (view.isDef()) {
|
||||
this.ovmap_.updateSize();
|
||||
this.resetExtent_();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle map property changes. This only deals with changes to the map's view.
|
||||
* @param {module:ol/Object~ObjectEvent} event The propertychange event.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.handleMapPropertyChange_ = function(event) {
|
||||
if (event.key === MapProperty.VIEW) {
|
||||
const oldView = /** @type {module:ol/View} */ (event.oldValue);
|
||||
if (oldView) {
|
||||
this.unbindView_(oldView);
|
||||
/**
|
||||
* Handle map property changes. This only deals with changes to the map's view.
|
||||
* @param {module:ol/Object~ObjectEvent} event The propertychange event.
|
||||
* @private
|
||||
*/
|
||||
handleMapPropertyChange_(event) {
|
||||
if (event.key === MapProperty.VIEW) {
|
||||
const oldView = /** @type {module:ol/View} */ (event.oldValue);
|
||||
if (oldView) {
|
||||
this.unbindView_(oldView);
|
||||
}
|
||||
const newView = this.getMap().getView();
|
||||
this.bindView_(newView);
|
||||
}
|
||||
const newView = this.getMap().getView();
|
||||
this.bindView_(newView);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Register listeners for view property changes.
|
||||
* @param {module:ol/View} view The view.
|
||||
* @private
|
||||
*/
|
||||
bindView_(view) {
|
||||
listen(view,
|
||||
getChangeEventType(ViewProperty.ROTATION),
|
||||
this.handleRotationChanged_, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listeners for view property changes.
|
||||
* @param {module:ol/View} view The view.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.bindView_ = function(view) {
|
||||
listen(view,
|
||||
getChangeEventType(ViewProperty.ROTATION),
|
||||
this.handleRotationChanged_, this);
|
||||
};
|
||||
/**
|
||||
* Unregister listeners for view property changes.
|
||||
* @param {module:ol/View} view The view.
|
||||
* @private
|
||||
*/
|
||||
unbindView_(view) {
|
||||
unlisten(view,
|
||||
getChangeEventType(ViewProperty.ROTATION),
|
||||
this.handleRotationChanged_, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle rotation changes to the main map.
|
||||
* TODO: This should rotate the extent rectrangle instead of the
|
||||
* overview map's view.
|
||||
* @private
|
||||
*/
|
||||
handleRotationChanged_() {
|
||||
this.ovmap_.getView().setRotation(this.getMap().getView().getRotation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listeners for view property changes.
|
||||
* @param {module:ol/View} view The view.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.unbindView_ = function(view) {
|
||||
unlisten(view,
|
||||
getChangeEventType(ViewProperty.ROTATION),
|
||||
this.handleRotationChanged_, this);
|
||||
};
|
||||
/**
|
||||
* Reset the overview map extent if the box size (width or
|
||||
* height) is less than the size of the overview map size times minRatio
|
||||
* or is greater than the size of the overview size times maxRatio.
|
||||
*
|
||||
* If the map extent was not reset, the box size can fits in the defined
|
||||
* ratio sizes. This method then checks if is contained inside the overview
|
||||
* map current extent. If not, recenter the overview map to the current
|
||||
* main map center location.
|
||||
* @private
|
||||
*/
|
||||
validateExtent_() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle rotation changes to the main map.
|
||||
* TODO: This should rotate the extent rectrangle instead of the
|
||||
* overview map's view.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.handleRotationChanged_ = function() {
|
||||
this.ovmap_.getView().setRotation(this.getMap().getView().getRotation());
|
||||
};
|
||||
const mapSize = /** @type {module:ol/size~Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
const extent = view.calculateExtent(mapSize);
|
||||
|
||||
const ovmapSize = /** @type {module:ol/size~Size} */ (ovmap.getSize());
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
const ovextent = ovview.calculateExtent(ovmapSize);
|
||||
|
||||
const topLeftPixel =
|
||||
ovmap.getPixelFromCoordinate(getTopLeft(extent));
|
||||
const bottomRightPixel =
|
||||
ovmap.getPixelFromCoordinate(getBottomRight(extent));
|
||||
|
||||
const boxWidth = Math.abs(topLeftPixel[0] - bottomRightPixel[0]);
|
||||
const boxHeight = Math.abs(topLeftPixel[1] - bottomRightPixel[1]);
|
||||
|
||||
const ovmapWidth = ovmapSize[0];
|
||||
const ovmapHeight = ovmapSize[1];
|
||||
|
||||
if (boxWidth < ovmapWidth * MIN_RATIO ||
|
||||
boxHeight < ovmapHeight * MIN_RATIO ||
|
||||
boxWidth > ovmapWidth * MAX_RATIO ||
|
||||
boxHeight > ovmapHeight * MAX_RATIO) {
|
||||
this.resetExtent_();
|
||||
} else if (!containsExtent(ovextent, extent)) {
|
||||
this.recenter_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the overview map extent to half calculated min and max ratio times
|
||||
* the extent of the main map.
|
||||
* @private
|
||||
*/
|
||||
resetExtent_() {
|
||||
if (MAX_RATIO === 0 || MIN_RATIO === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
const mapSize = /** @type {module:ol/size~Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
const extent = view.calculateExtent(mapSize);
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
// get how many times the current map overview could hold different
|
||||
// box sizes using the min and max ratio, pick the step in the middle used
|
||||
// to calculate the extent from the main map to set it to the overview map,
|
||||
const steps = Math.log(
|
||||
MAX_RATIO / MIN_RATIO) / Math.LN2;
|
||||
const ratio = 1 / (Math.pow(2, steps / 2) * MIN_RATIO);
|
||||
scaleFromCenter(extent, ratio);
|
||||
ovview.fit(extent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the center of the overview map to the map center without changing its
|
||||
* resolution.
|
||||
* @private
|
||||
*/
|
||||
recenter_() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
const view = map.getView();
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
ovview.setCenter(view.getCenter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the box using the main map extent
|
||||
* @private
|
||||
*/
|
||||
updateBox_() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mapSize = /** @type {module:ol/size~Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
const rotation = view.getRotation();
|
||||
|
||||
const overlay = this.boxOverlay_;
|
||||
const box = this.boxOverlay_.getElement();
|
||||
const extent = view.calculateExtent(mapSize);
|
||||
const ovresolution = ovview.getResolution();
|
||||
const bottomLeft = getBottomLeft(extent);
|
||||
const topRight = getTopRight(extent);
|
||||
|
||||
// set position using bottom left coordinates
|
||||
const rotateBottomLeft = this.calculateCoordinateRotate_(rotation, bottomLeft);
|
||||
overlay.setPosition(rotateBottomLeft);
|
||||
|
||||
// set box size calculated from map extent size and overview map resolution
|
||||
if (box) {
|
||||
box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px';
|
||||
box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} rotation Target rotation.
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @return {module:ol/coordinate~Coordinate|undefined} Coordinate for rotation and center anchor.
|
||||
* @private
|
||||
*/
|
||||
calculateCoordinateRotate_(rotation, coordinate) {
|
||||
let coordinateRotate;
|
||||
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
|
||||
const currentCenter = view.getCenter();
|
||||
|
||||
if (currentCenter) {
|
||||
coordinateRotate = [
|
||||
coordinate[0] - currentCenter[0],
|
||||
coordinate[1] - currentCenter[1]
|
||||
];
|
||||
rotateCoordinate(coordinateRotate, rotation);
|
||||
addCoordinate(coordinateRotate, currentCenter);
|
||||
}
|
||||
return coordinateRotate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleToggle_() {
|
||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||
if (this.collapsed_) {
|
||||
replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
|
||||
// manage overview map if it had not been rendered before and control
|
||||
// is expanded
|
||||
const ovmap = this.ovmap_;
|
||||
if (!this.collapsed_ && !ovmap.isRendered()) {
|
||||
ovmap.updateSize();
|
||||
this.resetExtent_();
|
||||
listenOnce(ovmap, MapEventType.POSTRENDER,
|
||||
function(event) {
|
||||
this.updateBox_();
|
||||
},
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if the overview map is collapsible, `false` otherwise.
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
getCollapsible() {
|
||||
return this.collapsible_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the overview map should be collapsible.
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
setCollapsible(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
this.element.classList.toggle('ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse or expand the overview map according to the passed parameter. Will
|
||||
* not do anything if the overview map isn't collapsible or if the current
|
||||
* collapsed state is already the one requested.
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
setCollapsed(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the overview map is collapsed.
|
||||
* @return {boolean} The overview map is collapsed.
|
||||
* @api
|
||||
*/
|
||||
getCollapsed() {
|
||||
return this.collapsed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the overview map.
|
||||
* @return {module:ol/PluggableMap} Overview map.
|
||||
* @api
|
||||
*/
|
||||
getOverviewMap() {
|
||||
return this.ovmap_;
|
||||
}
|
||||
}
|
||||
|
||||
inherits(OverviewMap, Control);
|
||||
|
||||
|
||||
/**
|
||||
@@ -332,266 +580,4 @@ export function render(mapEvent) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset the overview map extent if the box size (width or
|
||||
* height) is less than the size of the overview map size times minRatio
|
||||
* or is greater than the size of the overview size times maxRatio.
|
||||
*
|
||||
* If the map extent was not reset, the box size can fits in the defined
|
||||
* ratio sizes. This method then checks if is contained inside the overview
|
||||
* map current extent. If not, recenter the overview map to the current
|
||||
* main map center location.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.validateExtent_ = function() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mapSize = /** @type {module:ol/size~Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
const extent = view.calculateExtent(mapSize);
|
||||
|
||||
const ovmapSize = /** @type {module:ol/size~Size} */ (ovmap.getSize());
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
const ovextent = ovview.calculateExtent(ovmapSize);
|
||||
|
||||
const topLeftPixel =
|
||||
ovmap.getPixelFromCoordinate(getTopLeft(extent));
|
||||
const bottomRightPixel =
|
||||
ovmap.getPixelFromCoordinate(getBottomRight(extent));
|
||||
|
||||
const boxWidth = Math.abs(topLeftPixel[0] - bottomRightPixel[0]);
|
||||
const boxHeight = Math.abs(topLeftPixel[1] - bottomRightPixel[1]);
|
||||
|
||||
const ovmapWidth = ovmapSize[0];
|
||||
const ovmapHeight = ovmapSize[1];
|
||||
|
||||
if (boxWidth < ovmapWidth * MIN_RATIO ||
|
||||
boxHeight < ovmapHeight * MIN_RATIO ||
|
||||
boxWidth > ovmapWidth * MAX_RATIO ||
|
||||
boxHeight > ovmapHeight * MAX_RATIO) {
|
||||
this.resetExtent_();
|
||||
} else if (!containsExtent(ovextent, extent)) {
|
||||
this.recenter_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reset the overview map extent to half calculated min and max ratio times
|
||||
* the extent of the main map.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.resetExtent_ = function() {
|
||||
if (MAX_RATIO === 0 || MIN_RATIO === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
const mapSize = /** @type {module:ol/size~Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
const extent = view.calculateExtent(mapSize);
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
// get how many times the current map overview could hold different
|
||||
// box sizes using the min and max ratio, pick the step in the middle used
|
||||
// to calculate the extent from the main map to set it to the overview map,
|
||||
const steps = Math.log(
|
||||
MAX_RATIO / MIN_RATIO) / Math.LN2;
|
||||
const ratio = 1 / (Math.pow(2, steps / 2) * MIN_RATIO);
|
||||
scaleFromCenter(extent, ratio);
|
||||
ovview.fit(extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the center of the overview map to the map center without changing its
|
||||
* resolution.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.recenter_ = function() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
const view = map.getView();
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
ovview.setCenter(view.getCenter());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the box using the main map extent
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.updateBox_ = function() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mapSize = /** @type {module:ol/size~Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
const rotation = view.getRotation();
|
||||
|
||||
const overlay = this.boxOverlay_;
|
||||
const box = this.boxOverlay_.getElement();
|
||||
const extent = view.calculateExtent(mapSize);
|
||||
const ovresolution = ovview.getResolution();
|
||||
const bottomLeft = getBottomLeft(extent);
|
||||
const topRight = getTopRight(extent);
|
||||
|
||||
// set position using bottom left coordinates
|
||||
const rotateBottomLeft = this.calculateCoordinateRotate_(rotation, bottomLeft);
|
||||
overlay.setPosition(rotateBottomLeft);
|
||||
|
||||
// set box size calculated from map extent size and overview map resolution
|
||||
if (box) {
|
||||
box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px';
|
||||
box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} rotation Target rotation.
|
||||
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
|
||||
* @return {module:ol/coordinate~Coordinate|undefined} Coordinate for rotation and center anchor.
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.calculateCoordinateRotate_ = function(
|
||||
rotation, coordinate) {
|
||||
let coordinateRotate;
|
||||
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
|
||||
const currentCenter = view.getCenter();
|
||||
|
||||
if (currentCenter) {
|
||||
coordinateRotate = [
|
||||
coordinate[0] - currentCenter[0],
|
||||
coordinate[1] - currentCenter[1]
|
||||
];
|
||||
rotateCoordinate(coordinateRotate, rotation);
|
||||
addCoordinate(coordinateRotate, currentCenter);
|
||||
}
|
||||
return coordinateRotate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
OverviewMap.prototype.handleToggle_ = function() {
|
||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||
if (this.collapsed_) {
|
||||
replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
|
||||
// manage overview map if it had not been rendered before and control
|
||||
// is expanded
|
||||
const ovmap = this.ovmap_;
|
||||
if (!this.collapsed_ && !ovmap.isRendered()) {
|
||||
ovmap.updateSize();
|
||||
this.resetExtent_();
|
||||
listenOnce(ovmap, MapEventType.POSTRENDER,
|
||||
function(event) {
|
||||
this.updateBox_();
|
||||
},
|
||||
this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return `true` if the overview map is collapsible, `false` otherwise.
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
OverviewMap.prototype.getCollapsible = function() {
|
||||
return this.collapsible_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set whether the overview map should be collapsible.
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
OverviewMap.prototype.setCollapsible = function(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
this.element.classList.toggle('ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Collapse or expand the overview map according to the passed parameter. Will
|
||||
* not do anything if the overview map isn't collapsible or if the current
|
||||
* collapsed state is already the one requested.
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
OverviewMap.prototype.setCollapsed = function(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the overview map is collapsed.
|
||||
* @return {boolean} The overview map is collapsed.
|
||||
* @api
|
||||
*/
|
||||
OverviewMap.prototype.getCollapsed = function() {
|
||||
return this.collapsed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the overview map.
|
||||
* @return {module:ol/PluggableMap} Overview map.
|
||||
* @api
|
||||
*/
|
||||
OverviewMap.prototype.getOverviewMap = function() {
|
||||
return this.ovmap_;
|
||||
};
|
||||
export default OverviewMap;
|
||||
|
||||
@@ -38,117 +38,117 @@ import {inherits} from '../util.js';
|
||||
* @param {module:ol/control/Rotate~Options=} opt_options Rotate options.
|
||||
* @api
|
||||
*/
|
||||
const Rotate = function(opt_options) {
|
||||
class Rotate {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-rotate';
|
||||
const className = options.className !== undefined ? options.className : 'ol-rotate';
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u21E7';
|
||||
const label = options.label !== undefined ? options.label : '\u21E7';
|
||||
|
||||
/**
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.label_ = null;
|
||||
/**
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.label_ = null;
|
||||
|
||||
if (typeof label === 'string') {
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.className = 'ol-compass';
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
this.label_.classList.add('ol-compass');
|
||||
}
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
|
||||
|
||||
const button = document.createElement('button');
|
||||
button.className = className + '-reset';
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(this.label_);
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
Rotate.prototype.handleClick_, this);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
|
||||
this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.rotation_ = undefined;
|
||||
|
||||
if (this.autoHide_) {
|
||||
this.element.classList.add(CLASS_HIDDEN);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inherits(Rotate, Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
Rotate.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
if (this.callResetNorth_ !== undefined) {
|
||||
this.callResetNorth_();
|
||||
} else {
|
||||
this.resetNorth_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Rotate.prototype.resetNorth_ = function() {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
if (!view) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
if (view.getRotation() !== undefined) {
|
||||
if (this.duration_ > 0) {
|
||||
view.animate({
|
||||
rotation: 0,
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
if (typeof label === 'string') {
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.className = 'ol-compass';
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
view.setRotation(0);
|
||||
this.label_ = label;
|
||||
this.label_.classList.add('ol-compass');
|
||||
}
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
|
||||
|
||||
const button = document.createElement('button');
|
||||
button.className = className + '-reset';
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(this.label_);
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
Rotate.prototype.handleClick_, this);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
|
||||
this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.rotation_ = undefined;
|
||||
|
||||
if (this.autoHide_) {
|
||||
this.element.classList.add(CLASS_HIDDEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
if (this.callResetNorth_ !== undefined) {
|
||||
this.callResetNorth_();
|
||||
} else {
|
||||
this.resetNorth_();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
resetNorth_() {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
if (!view) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
if (view.getRotation() !== undefined) {
|
||||
if (this.duration_ > 0) {
|
||||
view.animate({
|
||||
rotation: 0,
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
} else {
|
||||
view.setRotation(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Rotate, Control);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,89 +64,229 @@ const LEADING_DIGITS = [1, 2, 5];
|
||||
* @param {module:ol/control/ScaleLine~Options=} opt_options Scale line options.
|
||||
* @api
|
||||
*/
|
||||
const ScaleLine = function(opt_options) {
|
||||
class ScaleLine {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-scale-line';
|
||||
const className = options.className !== undefined ? options.className : 'ol-scale-line';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.innerElement_ = document.createElement('DIV');
|
||||
this.innerElement_.className = className + '-inner';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.element_ = document.createElement('DIV');
|
||||
this.element_.className = className + ' ' + CLASS_UNSELECTABLE;
|
||||
this.element_.appendChild(this.innerElement_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?module:ol/View~State}
|
||||
*/
|
||||
this.viewState_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.renderedWidth_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = '';
|
||||
|
||||
Control.call(this, {
|
||||
element: this.element_,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
listen(
|
||||
this, getChangeEventType(UNITS_PROP),
|
||||
this.handleUnitsChanged_, this);
|
||||
|
||||
this.setUnits(/** @type {module:ol/control/ScaleLine~Units} */ (options.units) ||
|
||||
Units.METRIC);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the units to use in the scale line.
|
||||
* @return {module:ol/control/ScaleLine~Units|undefined} The units
|
||||
* to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getUnits() {
|
||||
return (
|
||||
/** @type {module:ol/control/ScaleLine~Units|undefined} */ (this.get(UNITS_PROP))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.innerElement_ = document.createElement('DIV');
|
||||
this.innerElement_.className = className + '-inner';
|
||||
handleUnitsChanged_() {
|
||||
this.updateElement_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the units to use in the scale line.
|
||||
* @param {module:ol/control/ScaleLine~Units} units The units to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setUnits(units) {
|
||||
this.set(UNITS_PROP, units);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.element_ = document.createElement('DIV');
|
||||
this.element_.className = className + ' ' + CLASS_UNSELECTABLE;
|
||||
this.element_.appendChild(this.innerElement_);
|
||||
updateElement_() {
|
||||
const viewState = this.viewState_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?module:ol/View~State}
|
||||
*/
|
||||
this.viewState_ = null;
|
||||
if (!viewState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element_.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64;
|
||||
const center = viewState.center;
|
||||
const projection = viewState.projection;
|
||||
const units = this.getUnits();
|
||||
const pointResolutionUnits = units == Units.DEGREES ?
|
||||
ProjUnits.DEGREES :
|
||||
ProjUnits.METERS;
|
||||
let pointResolution =
|
||||
getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);
|
||||
if (projection.getUnits() != ProjUnits.DEGREES && projection.getMetersPerUnit()
|
||||
&& pointResolutionUnits == ProjUnits.METERS) {
|
||||
pointResolution *= projection.getMetersPerUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = false;
|
||||
let nominalCount = this.minWidth_ * pointResolution;
|
||||
let suffix = '';
|
||||
if (units == Units.DEGREES) {
|
||||
const metersPerDegree = METERS_PER_UNIT[ProjUnits.DEGREES];
|
||||
if (projection.getUnits() == ProjUnits.DEGREES) {
|
||||
nominalCount *= metersPerDegree;
|
||||
} else {
|
||||
pointResolution /= metersPerDegree;
|
||||
}
|
||||
if (nominalCount < metersPerDegree / 60) {
|
||||
suffix = '\u2033'; // seconds
|
||||
pointResolution *= 3600;
|
||||
} else if (nominalCount < metersPerDegree) {
|
||||
suffix = '\u2032'; // minutes
|
||||
pointResolution *= 60;
|
||||
} else {
|
||||
suffix = '\u00b0'; // degrees
|
||||
}
|
||||
} else if (units == Units.IMPERIAL) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution /= 0.0254;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.3048;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.344;
|
||||
}
|
||||
} else if (units == Units.NAUTICAL) {
|
||||
pointResolution /= 1852;
|
||||
suffix = 'nm';
|
||||
} else if (units == Units.METRIC) {
|
||||
if (nominalCount < 0.001) {
|
||||
suffix = 'μm';
|
||||
pointResolution *= 1000000;
|
||||
} else if (nominalCount < 1) {
|
||||
suffix = 'mm';
|
||||
pointResolution *= 1000;
|
||||
} else if (nominalCount < 1000) {
|
||||
suffix = 'm';
|
||||
} else {
|
||||
suffix = 'km';
|
||||
pointResolution /= 1000;
|
||||
}
|
||||
} else if (units == Units.US) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution *= 39.37;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.30480061;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.3472;
|
||||
}
|
||||
} else {
|
||||
assert(false, 33); // Invalid units
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.renderedWidth_ = undefined;
|
||||
let i = 3 * Math.floor(
|
||||
Math.log(this.minWidth_ * pointResolution) / Math.log(10));
|
||||
let count, width;
|
||||
while (true) {
|
||||
count = LEADING_DIGITS[((i % 3) + 3) % 3] *
|
||||
Math.pow(10, Math.floor(i / 3));
|
||||
width = Math.round(count / pointResolution);
|
||||
if (isNaN(width)) {
|
||||
this.element_.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
return;
|
||||
} else if (width >= this.minWidth_) {
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = '';
|
||||
const html = count + ' ' + suffix;
|
||||
if (this.renderedHTML_ != html) {
|
||||
this.innerElement_.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
|
||||
Control.call(this, {
|
||||
element: this.element_,
|
||||
render: options.render || render,
|
||||
target: options.target
|
||||
});
|
||||
if (this.renderedWidth_ != width) {
|
||||
this.innerElement_.style.width = width + 'px';
|
||||
this.renderedWidth_ = width;
|
||||
}
|
||||
|
||||
listen(
|
||||
this, getChangeEventType(UNITS_PROP),
|
||||
this.handleUnitsChanged_, this);
|
||||
if (!this.renderedVisible_) {
|
||||
this.element_.style.display = '';
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
this.setUnits(/** @type {module:ol/control/ScaleLine~Units} */ (options.units) ||
|
||||
Units.METRIC);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ScaleLine, Control);
|
||||
|
||||
|
||||
/**
|
||||
* Return the units to use in the scale line.
|
||||
* @return {module:ol/control/ScaleLine~Units|undefined} The units
|
||||
* to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ScaleLine.prototype.getUnits = function() {
|
||||
return (
|
||||
/** @type {module:ol/control/ScaleLine~Units|undefined} */ (this.get(UNITS_PROP))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the scale line element.
|
||||
* @param {module:ol/MapEvent} mapEvent Map event.
|
||||
@@ -164,145 +304,4 @@ export function render(mapEvent) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ScaleLine.prototype.handleUnitsChanged_ = function() {
|
||||
this.updateElement_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the units to use in the scale line.
|
||||
* @param {module:ol/control/ScaleLine~Units} units The units to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ScaleLine.prototype.setUnits = function(units) {
|
||||
this.set(UNITS_PROP, units);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ScaleLine.prototype.updateElement_ = function() {
|
||||
const viewState = this.viewState_;
|
||||
|
||||
if (!viewState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element_.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const center = viewState.center;
|
||||
const projection = viewState.projection;
|
||||
const units = this.getUnits();
|
||||
const pointResolutionUnits = units == Units.DEGREES ?
|
||||
ProjUnits.DEGREES :
|
||||
ProjUnits.METERS;
|
||||
let pointResolution =
|
||||
getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);
|
||||
if (projection.getUnits() != ProjUnits.DEGREES && projection.getMetersPerUnit()
|
||||
&& pointResolutionUnits == ProjUnits.METERS) {
|
||||
pointResolution *= projection.getMetersPerUnit();
|
||||
}
|
||||
|
||||
let nominalCount = this.minWidth_ * pointResolution;
|
||||
let suffix = '';
|
||||
if (units == Units.DEGREES) {
|
||||
const metersPerDegree = METERS_PER_UNIT[ProjUnits.DEGREES];
|
||||
if (projection.getUnits() == ProjUnits.DEGREES) {
|
||||
nominalCount *= metersPerDegree;
|
||||
} else {
|
||||
pointResolution /= metersPerDegree;
|
||||
}
|
||||
if (nominalCount < metersPerDegree / 60) {
|
||||
suffix = '\u2033'; // seconds
|
||||
pointResolution *= 3600;
|
||||
} else if (nominalCount < metersPerDegree) {
|
||||
suffix = '\u2032'; // minutes
|
||||
pointResolution *= 60;
|
||||
} else {
|
||||
suffix = '\u00b0'; // degrees
|
||||
}
|
||||
} else if (units == Units.IMPERIAL) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution /= 0.0254;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.3048;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.344;
|
||||
}
|
||||
} else if (units == Units.NAUTICAL) {
|
||||
pointResolution /= 1852;
|
||||
suffix = 'nm';
|
||||
} else if (units == Units.METRIC) {
|
||||
if (nominalCount < 0.001) {
|
||||
suffix = 'μm';
|
||||
pointResolution *= 1000000;
|
||||
} else if (nominalCount < 1) {
|
||||
suffix = 'mm';
|
||||
pointResolution *= 1000;
|
||||
} else if (nominalCount < 1000) {
|
||||
suffix = 'm';
|
||||
} else {
|
||||
suffix = 'km';
|
||||
pointResolution /= 1000;
|
||||
}
|
||||
} else if (units == Units.US) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution *= 39.37;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.30480061;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.3472;
|
||||
}
|
||||
} else {
|
||||
assert(false, 33); // Invalid units
|
||||
}
|
||||
|
||||
let i = 3 * Math.floor(
|
||||
Math.log(this.minWidth_ * pointResolution) / Math.log(10));
|
||||
let count, width;
|
||||
while (true) {
|
||||
count = LEADING_DIGITS[((i % 3) + 3) % 3] *
|
||||
Math.pow(10, Math.floor(i / 3));
|
||||
width = Math.round(count / pointResolution);
|
||||
if (isNaN(width)) {
|
||||
this.element_.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
return;
|
||||
} else if (width >= this.minWidth_) {
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
const html = count + ' ' + suffix;
|
||||
if (this.renderedHTML_ != html) {
|
||||
this.innerElement_.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
|
||||
if (this.renderedWidth_ != width) {
|
||||
this.innerElement_.style.width = width + 'px';
|
||||
this.renderedWidth_ = width;
|
||||
}
|
||||
|
||||
if (!this.renderedVisible_) {
|
||||
this.element_.style.display = '';
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default ScaleLine;
|
||||
|
||||
@@ -36,104 +36,106 @@ import {easeOut} from '../easing.js';
|
||||
* @param {module:ol/control/Zoom~Options=} opt_options Zoom options.
|
||||
* @api
|
||||
*/
|
||||
const Zoom = function(opt_options) {
|
||||
class Zoom {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-zoom';
|
||||
const className = options.className !== undefined ? options.className : 'ol-zoom';
|
||||
|
||||
const delta = options.delta !== undefined ? options.delta : 1;
|
||||
const delta = options.delta !== undefined ? options.delta : 1;
|
||||
|
||||
const zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
|
||||
const zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212';
|
||||
const zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
|
||||
const zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212';
|
||||
|
||||
const zoomInTipLabel = options.zoomInTipLabel !== undefined ?
|
||||
options.zoomInTipLabel : 'Zoom in';
|
||||
const zoomOutTipLabel = options.zoomOutTipLabel !== undefined ?
|
||||
options.zoomOutTipLabel : 'Zoom out';
|
||||
const zoomInTipLabel = options.zoomInTipLabel !== undefined ?
|
||||
options.zoomInTipLabel : 'Zoom in';
|
||||
const zoomOutTipLabel = options.zoomOutTipLabel !== undefined ?
|
||||
options.zoomOutTipLabel : 'Zoom out';
|
||||
|
||||
const inElement = document.createElement('button');
|
||||
inElement.className = className + '-in';
|
||||
inElement.setAttribute('type', 'button');
|
||||
inElement.title = zoomInTipLabel;
|
||||
inElement.appendChild(
|
||||
typeof zoomInLabel === 'string' ? document.createTextNode(zoomInLabel) : zoomInLabel
|
||||
);
|
||||
const inElement = document.createElement('button');
|
||||
inElement.className = className + '-in';
|
||||
inElement.setAttribute('type', 'button');
|
||||
inElement.title = zoomInTipLabel;
|
||||
inElement.appendChild(
|
||||
typeof zoomInLabel === 'string' ? document.createTextNode(zoomInLabel) : zoomInLabel
|
||||
);
|
||||
|
||||
listen(inElement, EventType.CLICK,
|
||||
Zoom.prototype.handleClick_.bind(this, delta));
|
||||
listen(inElement, EventType.CLICK,
|
||||
Zoom.prototype.handleClick_.bind(this, delta));
|
||||
|
||||
const outElement = document.createElement('button');
|
||||
outElement.className = className + '-out';
|
||||
outElement.setAttribute('type', 'button');
|
||||
outElement.title = zoomOutTipLabel;
|
||||
outElement.appendChild(
|
||||
typeof zoomOutLabel === 'string' ? document.createTextNode(zoomOutLabel) : zoomOutLabel
|
||||
);
|
||||
const outElement = document.createElement('button');
|
||||
outElement.className = className + '-out';
|
||||
outElement.setAttribute('type', 'button');
|
||||
outElement.title = zoomOutTipLabel;
|
||||
outElement.appendChild(
|
||||
typeof zoomOutLabel === 'string' ? document.createTextNode(zoomOutLabel) : zoomOutLabel
|
||||
);
|
||||
|
||||
listen(outElement, EventType.CLICK,
|
||||
Zoom.prototype.handleClick_.bind(this, -delta));
|
||||
listen(outElement, EventType.CLICK,
|
||||
Zoom.prototype.handleClick_.bind(this, -delta));
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(inElement);
|
||||
element.appendChild(outElement);
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(inElement);
|
||||
element.appendChild(outElement);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @param {number} delta Zoom delta.
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||
handleClick_(delta, event) {
|
||||
event.preventDefault();
|
||||
this.zoomByDelta_(delta);
|
||||
}
|
||||
|
||||
};
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @private
|
||||
*/
|
||||
zoomByDelta_(delta) {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
if (!view) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
const currentResolution = view.getResolution();
|
||||
if (currentResolution) {
|
||||
const newResolution = view.constrainResolution(currentResolution, delta);
|
||||
if (this.duration_ > 0) {
|
||||
if (view.getAnimating()) {
|
||||
view.cancelAnimations();
|
||||
}
|
||||
view.animate({
|
||||
resolution: newResolution,
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
} else {
|
||||
view.setResolution(newResolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Zoom, Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
Zoom.prototype.handleClick_ = function(delta, event) {
|
||||
event.preventDefault();
|
||||
this.zoomByDelta_(delta);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @private
|
||||
*/
|
||||
Zoom.prototype.zoomByDelta_ = function(delta) {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
if (!view) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
const currentResolution = view.getResolution();
|
||||
if (currentResolution) {
|
||||
const newResolution = view.constrainResolution(currentResolution, delta);
|
||||
if (this.duration_ > 0) {
|
||||
if (view.getAnimating()) {
|
||||
view.cancelAnimations();
|
||||
}
|
||||
view.animate({
|
||||
resolution: newResolution,
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
} else {
|
||||
view.setResolution(newResolution);
|
||||
}
|
||||
}
|
||||
};
|
||||
export default Zoom;
|
||||
|
||||
@@ -47,164 +47,303 @@ const Direction = {
|
||||
* @param {module:ol/control/ZoomSlider~Options=} opt_options Zoom slider options.
|
||||
* @api
|
||||
*/
|
||||
const ZoomSlider = function(opt_options) {
|
||||
class ZoomSlider {
|
||||
constructor(opt_options) {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* Will hold the current resolution of the view.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.currentResolution_ = undefined;
|
||||
|
||||
/**
|
||||
* The direction of the slider. Will be determined from actual display of the
|
||||
* container and defaults to Direction.VERTICAL.
|
||||
*
|
||||
* @type {Direction}
|
||||
* @private
|
||||
*/
|
||||
this.direction_ = Direction.VERTICAL;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.dragging_;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.heightLimit_ = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.widthLimit_ = 0;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.previousX_;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.previousY_;
|
||||
|
||||
/**
|
||||
* The calculated thumb size (border box plus margins). Set when initSlider_
|
||||
* is called.
|
||||
* @type {module:ol/size~Size}
|
||||
* @private
|
||||
*/
|
||||
this.thumbSize_ = null;
|
||||
|
||||
/**
|
||||
* Whether the slider is initialized.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.sliderInitialized_ = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 200;
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-zoomslider';
|
||||
const thumbElement = document.createElement('button');
|
||||
thumbElement.setAttribute('type', 'button');
|
||||
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
||||
const containerElement = document.createElement('div');
|
||||
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
containerElement.appendChild(thumbElement);
|
||||
/**
|
||||
* @type {module:ol/pointer/PointerEventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.dragger_ = new PointerEventHandler(containerElement);
|
||||
|
||||
listen(this.dragger_, PointerEventType.POINTERDOWN,
|
||||
this.handleDraggerStart_, this);
|
||||
listen(this.dragger_, PointerEventType.POINTERMOVE,
|
||||
this.handleDraggerDrag_, this);
|
||||
listen(this.dragger_, PointerEventType.POINTERUP,
|
||||
this.handleDraggerEnd_, this);
|
||||
|
||||
listen(containerElement, EventType.CLICK, this.handleContainerClick_, this);
|
||||
listen(thumbElement, EventType.CLICK, stopPropagation);
|
||||
|
||||
Control.call(this, {
|
||||
element: containerElement,
|
||||
render: options.render || render
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Will hold the current resolution of the view.
|
||||
* @inheritDoc
|
||||
*/
|
||||
disposeInternal() {
|
||||
this.dragger_.dispose();
|
||||
Control.prototype.disposeInternal.call(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setMap(map) {
|
||||
Control.prototype.setMap.call(this, map);
|
||||
if (map) {
|
||||
map.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the slider element. This will determine and set this controls
|
||||
* direction_ and also constrain the dragging of the thumb to always be within
|
||||
* the bounds of the container.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.currentResolution_ = undefined;
|
||||
initSlider_() {
|
||||
const container = this.element;
|
||||
const containerSize = {
|
||||
width: container.offsetWidth, height: container.offsetHeight
|
||||
};
|
||||
|
||||
const thumb = container.firstElementChild;
|
||||
const computedStyle = getComputedStyle(thumb);
|
||||
const thumbWidth = thumb.offsetWidth +
|
||||
parseFloat(computedStyle['marginRight']) +
|
||||
parseFloat(computedStyle['marginLeft']);
|
||||
const thumbHeight = thumb.offsetHeight +
|
||||
parseFloat(computedStyle['marginTop']) +
|
||||
parseFloat(computedStyle['marginBottom']);
|
||||
this.thumbSize_ = [thumbWidth, thumbHeight];
|
||||
|
||||
if (containerSize.width > containerSize.height) {
|
||||
this.direction_ = Direction.HORIZONTAL;
|
||||
this.widthLimit_ = containerSize.width - thumbWidth;
|
||||
} else {
|
||||
this.direction_ = Direction.VERTICAL;
|
||||
this.heightLimit_ = containerSize.height - thumbHeight;
|
||||
}
|
||||
this.sliderInitialized_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The direction of the slider. Will be determined from actual display of the
|
||||
* container and defaults to Direction.VERTICAL.
|
||||
* @param {MouseEvent} event The browser event to handle.
|
||||
* @private
|
||||
*/
|
||||
handleContainerClick_(event) {
|
||||
const view = this.getMap().getView();
|
||||
|
||||
const relativePosition = this.getRelativePosition_(
|
||||
event.offsetX - this.thumbSize_[0] / 2,
|
||||
event.offsetY - this.thumbSize_[1] / 2);
|
||||
|
||||
const resolution = this.getResolutionForPosition_(relativePosition);
|
||||
|
||||
view.animate({
|
||||
resolution: view.constrainResolution(resolution),
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dragger start events.
|
||||
* @param {module:ol/pointer/PointerEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
handleDraggerStart_(event) {
|
||||
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
|
||||
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
|
||||
this.previousX_ = event.clientX;
|
||||
this.previousY_ = event.clientY;
|
||||
this.dragging_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dragger drag events.
|
||||
*
|
||||
* @type {Direction}
|
||||
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
this.direction_ = Direction.VERTICAL;
|
||||
handleDraggerDrag_(event) {
|
||||
if (this.dragging_) {
|
||||
const element = this.element.firstElementChild;
|
||||
const deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
|
||||
const deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
|
||||
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
||||
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
||||
this.getMap().getView().setResolution(this.currentResolution_);
|
||||
this.setThumbPosition_(this.currentResolution_);
|
||||
this.previousX_ = event.clientX;
|
||||
this.previousY_ = event.clientY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* Handle dragger end events.
|
||||
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
this.dragging_;
|
||||
handleDraggerEnd_(event) {
|
||||
if (this.dragging_) {
|
||||
const view = this.getMap().getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
|
||||
view.animate({
|
||||
resolution: view.constrainResolution(this.currentResolution_),
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
|
||||
this.dragging_ = false;
|
||||
this.previousX_ = undefined;
|
||||
this.previousY_ = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* Positions the thumb inside its container according to the given resolution.
|
||||
*
|
||||
* @param {number} res The res.
|
||||
* @private
|
||||
*/
|
||||
this.heightLimit_ = 0;
|
||||
setThumbPosition_(res) {
|
||||
const position = this.getPositionForResolution_(res);
|
||||
const thumb = this.element.firstElementChild;
|
||||
|
||||
if (this.direction_ == Direction.HORIZONTAL) {
|
||||
thumb.style.left = this.widthLimit_ * position + 'px';
|
||||
} else {
|
||||
thumb.style.top = this.heightLimit_ * position + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* Calculates the relative position of the thumb given x and y offsets. The
|
||||
* relative position scales from 0 to 1. The x and y offsets are assumed to be
|
||||
* in pixel units within the dragger limits.
|
||||
*
|
||||
* @param {number} x Pixel position relative to the left of the slider.
|
||||
* @param {number} y Pixel position relative to the top of the slider.
|
||||
* @return {number} The relative position of the thumb.
|
||||
* @private
|
||||
*/
|
||||
this.widthLimit_ = 0;
|
||||
getRelativePosition_(x, y) {
|
||||
let amount;
|
||||
if (this.direction_ === Direction.HORIZONTAL) {
|
||||
amount = x / this.widthLimit_;
|
||||
} else {
|
||||
amount = y / this.heightLimit_;
|
||||
}
|
||||
return clamp(amount, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* Calculates the corresponding resolution of the thumb given its relative
|
||||
* position (where 0 is the minimum and 1 is the maximum).
|
||||
*
|
||||
* @param {number} position The relative position of the thumb.
|
||||
* @return {number} The corresponding resolution.
|
||||
* @private
|
||||
*/
|
||||
this.previousX_;
|
||||
getResolutionForPosition_(position) {
|
||||
const fn = this.getMap().getView().getResolutionForValueFunction();
|
||||
return fn(1 - position);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* Determines the relative position of the slider for the given resolution. A
|
||||
* relative position of 0 corresponds to the minimum view resolution. A
|
||||
* relative position of 1 corresponds to the maximum view resolution.
|
||||
*
|
||||
* @param {number} res The resolution.
|
||||
* @return {number} The relative position value (between 0 and 1).
|
||||
* @private
|
||||
*/
|
||||
this.previousY_;
|
||||
|
||||
/**
|
||||
* The calculated thumb size (border box plus margins). Set when initSlider_
|
||||
* is called.
|
||||
* @type {module:ol/size~Size}
|
||||
* @private
|
||||
*/
|
||||
this.thumbSize_ = null;
|
||||
|
||||
/**
|
||||
* Whether the slider is initialized.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.sliderInitialized_ = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 200;
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-zoomslider';
|
||||
const thumbElement = document.createElement('button');
|
||||
thumbElement.setAttribute('type', 'button');
|
||||
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
||||
const containerElement = document.createElement('div');
|
||||
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
containerElement.appendChild(thumbElement);
|
||||
/**
|
||||
* @type {module:ol/pointer/PointerEventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.dragger_ = new PointerEventHandler(containerElement);
|
||||
|
||||
listen(this.dragger_, PointerEventType.POINTERDOWN,
|
||||
this.handleDraggerStart_, this);
|
||||
listen(this.dragger_, PointerEventType.POINTERMOVE,
|
||||
this.handleDraggerDrag_, this);
|
||||
listen(this.dragger_, PointerEventType.POINTERUP,
|
||||
this.handleDraggerEnd_, this);
|
||||
|
||||
listen(containerElement, EventType.CLICK, this.handleContainerClick_, this);
|
||||
listen(thumbElement, EventType.CLICK, stopPropagation);
|
||||
|
||||
Control.call(this, {
|
||||
element: containerElement,
|
||||
render: options.render || render
|
||||
});
|
||||
};
|
||||
getPositionForResolution_(res) {
|
||||
const fn = this.getMap().getView().getValueForResolutionFunction();
|
||||
return 1 - fn(res);
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ZoomSlider, Control);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ZoomSlider.prototype.disposeInternal = function() {
|
||||
this.dragger_.dispose();
|
||||
Control.prototype.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ZoomSlider.prototype.setMap = function(map) {
|
||||
Control.prototype.setMap.call(this, map);
|
||||
if (map) {
|
||||
map.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the slider element. This will determine and set this controls
|
||||
* direction_ and also constrain the dragging of the thumb to always be within
|
||||
* the bounds of the container.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.initSlider_ = function() {
|
||||
const container = this.element;
|
||||
const containerSize = {
|
||||
width: container.offsetWidth, height: container.offsetHeight
|
||||
};
|
||||
|
||||
const thumb = container.firstElementChild;
|
||||
const computedStyle = getComputedStyle(thumb);
|
||||
const thumbWidth = thumb.offsetWidth +
|
||||
parseFloat(computedStyle['marginRight']) +
|
||||
parseFloat(computedStyle['marginLeft']);
|
||||
const thumbHeight = thumb.offsetHeight +
|
||||
parseFloat(computedStyle['marginTop']) +
|
||||
parseFloat(computedStyle['marginBottom']);
|
||||
this.thumbSize_ = [thumbWidth, thumbHeight];
|
||||
|
||||
if (containerSize.width > containerSize.height) {
|
||||
this.direction_ = Direction.HORIZONTAL;
|
||||
this.widthLimit_ = containerSize.width - thumbWidth;
|
||||
} else {
|
||||
this.direction_ = Direction.VERTICAL;
|
||||
this.heightLimit_ = containerSize.height - thumbHeight;
|
||||
}
|
||||
this.sliderInitialized_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the zoomslider element.
|
||||
* @param {module:ol/MapEvent} mapEvent Map event.
|
||||
@@ -226,151 +365,4 @@ export function render(mapEvent) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The browser event to handle.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.handleContainerClick_ = function(event) {
|
||||
const view = this.getMap().getView();
|
||||
|
||||
const relativePosition = this.getRelativePosition_(
|
||||
event.offsetX - this.thumbSize_[0] / 2,
|
||||
event.offsetY - this.thumbSize_[1] / 2);
|
||||
|
||||
const resolution = this.getResolutionForPosition_(relativePosition);
|
||||
|
||||
view.animate({
|
||||
resolution: view.constrainResolution(resolution),
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle dragger start events.
|
||||
* @param {module:ol/pointer/PointerEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.handleDraggerStart_ = function(event) {
|
||||
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
|
||||
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
|
||||
this.previousX_ = event.clientX;
|
||||
this.previousY_ = event.clientY;
|
||||
this.dragging_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle dragger drag events.
|
||||
*
|
||||
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
|
||||
if (this.dragging_) {
|
||||
const element = this.element.firstElementChild;
|
||||
const deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
|
||||
const deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
|
||||
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
||||
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
||||
this.getMap().getView().setResolution(this.currentResolution_);
|
||||
this.setThumbPosition_(this.currentResolution_);
|
||||
this.previousX_ = event.clientX;
|
||||
this.previousY_ = event.clientY;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle dragger end events.
|
||||
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
|
||||
if (this.dragging_) {
|
||||
const view = this.getMap().getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
|
||||
view.animate({
|
||||
resolution: view.constrainResolution(this.currentResolution_),
|
||||
duration: this.duration_,
|
||||
easing: easeOut
|
||||
});
|
||||
|
||||
this.dragging_ = false;
|
||||
this.previousX_ = undefined;
|
||||
this.previousY_ = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Positions the thumb inside its container according to the given resolution.
|
||||
*
|
||||
* @param {number} res The res.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.setThumbPosition_ = function(res) {
|
||||
const position = this.getPositionForResolution_(res);
|
||||
const thumb = this.element.firstElementChild;
|
||||
|
||||
if (this.direction_ == Direction.HORIZONTAL) {
|
||||
thumb.style.left = this.widthLimit_ * position + 'px';
|
||||
} else {
|
||||
thumb.style.top = this.heightLimit_ * position + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the relative position of the thumb given x and y offsets. The
|
||||
* relative position scales from 0 to 1. The x and y offsets are assumed to be
|
||||
* in pixel units within the dragger limits.
|
||||
*
|
||||
* @param {number} x Pixel position relative to the left of the slider.
|
||||
* @param {number} y Pixel position relative to the top of the slider.
|
||||
* @return {number} The relative position of the thumb.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.getRelativePosition_ = function(x, y) {
|
||||
let amount;
|
||||
if (this.direction_ === Direction.HORIZONTAL) {
|
||||
amount = x / this.widthLimit_;
|
||||
} else {
|
||||
amount = y / this.heightLimit_;
|
||||
}
|
||||
return clamp(amount, 0, 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the corresponding resolution of the thumb given its relative
|
||||
* position (where 0 is the minimum and 1 is the maximum).
|
||||
*
|
||||
* @param {number} position The relative position of the thumb.
|
||||
* @return {number} The corresponding resolution.
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.getResolutionForPosition_ = function(position) {
|
||||
const fn = this.getMap().getView().getResolutionForValueFunction();
|
||||
return fn(1 - position);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines the relative position of the slider for the given resolution. A
|
||||
* relative position of 0 corresponds to the minimum view resolution. A
|
||||
* relative position of 1 corresponds to the maximum view resolution.
|
||||
*
|
||||
* @param {number} res The resolution.
|
||||
* @return {number} The relative position value (between 0 and 1).
|
||||
* @private
|
||||
*/
|
||||
ZoomSlider.prototype.getPositionForResolution_ = function(res) {
|
||||
const fn = this.getMap().getView().getValueForResolutionFunction();
|
||||
return 1 - fn(res);
|
||||
};
|
||||
|
||||
export default ZoomSlider;
|
||||
|
||||
@@ -31,59 +31,61 @@ import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
* @param {module:ol/control/ZoomToExtent~Options=} opt_options Options.
|
||||
* @api
|
||||
*/
|
||||
const ZoomToExtent = function(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
class ZoomToExtent {
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {module:ol/extent~Extent}
|
||||
* @protected
|
||||
*/
|
||||
this.extent = options.extent ? options.extent : null;
|
||||
/**
|
||||
* @type {module:ol/extent~Extent}
|
||||
* @protected
|
||||
*/
|
||||
this.extent = options.extent ? options.extent : null;
|
||||
|
||||
const className = options.className !== undefined ? options.className : 'ol-zoom-extent';
|
||||
const className = options.className !== undefined ? options.className : 'ol-zoom-extent';
|
||||
|
||||
const label = options.label !== undefined ? options.label : 'E';
|
||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Fit to extent';
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(
|
||||
typeof label === 'string' ? document.createTextNode(label) : label
|
||||
);
|
||||
const label = options.label !== undefined ? options.label : 'E';
|
||||
const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Fit to extent';
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(
|
||||
typeof label === 'string' ? document.createTextNode(label) : label
|
||||
);
|
||||
|
||||
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||
listen(button, EventType.CLICK, this.handleClick_, this);
|
||||
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
const cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = document.createElement('div');
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
};
|
||||
Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleZoomToExtent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handleZoomToExtent() {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
const extent = !this.extent ? view.getProjection().getExtent() : this.extent;
|
||||
view.fit(extent);
|
||||
}
|
||||
}
|
||||
|
||||
inherits(ZoomToExtent, Control);
|
||||
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
ZoomToExtent.prototype.handleClick_ = function(event) {
|
||||
event.preventDefault();
|
||||
this.handleZoomToExtent();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ZoomToExtent.prototype.handleZoomToExtent = function() {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
const extent = !this.extent ? view.getProjection().getExtent() : this.extent;
|
||||
view.fit(extent);
|
||||
};
|
||||
export default ZoomToExtent;
|
||||
|
||||
Reference in New Issue
Block a user