OpenLayers源码解析2 View.js
View.js
父类
ol/Object-BaseObject
主要功能
展示地图的2D视图。
更改地图中心,分辨率,旋转角度。
视图的投影坐标系决定了显示的分辨率单位,默认的投影坐标系为球形墨卡托(EPSG:3857)。
视图状态
视图由三种状态决定:中心(center),分辨率(resolution),角度(rotation)。
每个状态都有对应的getter和setter。
center:getCenter和setCenter
resolution:状态实际上并无zoom状态,都是通过resolution状态来设置,但是setZoom,getZoom,setResolution,getResolution,getResolutionForZoom,getZoomForResolution都可以使用。
限制因素
resolution:resolutions,maxResolution,maxZoom,zoomFactor。如果resolutions被设置了其他三个将被忽视。
rotation:enableRotation,constrainRotation。
center:extent
改变状态
adjustCenter,adjustRotation,adjustZoom,adjustResolution
opt_anchor
参数:View({})
参数 | 类型 | 说明 |
---|---|---|
center * | module:ol/coordinate~Coordinate | 地图的初始中心。可以用setCenter指定。 |
zoom * | number | 只有在resolution未设定的时候才有用,zoom用于计算resolution。 |
constrainRotation | boolean (defaults to true) number | true地图会在0度附近自动还原到0度,false不会。 number代表360等分,只能旋转等分的倍数。 |
enableRotation | boolean (defaults to true) | 是否可旋转。false表示不能旋转,且constrainRotation参数无效。 |
projection | module:ol/proj~ProjectionLike (defaults to ‘EPSG:3857’) | 坐标系。默认值为球形墨卡托投影EPSG:3857。 |
方法
函数名 | 参数 | 源码 | 返回值类型 | 功能 |
---|---|---|---|---|
getZoom() | 无 | View.js, line 1226 | {number | undefined} |
setCenter(center) | center module:ol/coordinate~Coordinate 或undefined 视图中心 | View.js, line 1602 | 无 | 设定视图中心 |
setZoom(zoom) | zoom number 缩放等级 | View.js, line 1653 | 无 | 缩放到特点缩放等级 |
/*** @module ol/View*/
import BaseObject from './Object.js';
import GeometryType from './geom/GeometryType.js';
import Units from './proj/Units.js';
import ViewHint from './ViewHint.js';
import ViewProperty from './ViewProperty.js';
import {DEFAULT_TILE_SIZE} from './tilegrid/common.js';
import {METERS_PER_UNIT,createProjection,fromUserCoordinate,fromUserExtent,getUserProjection,toUserCoordinate,toUserExtent,
} from './proj.js';
import {VOID} from './functions.js';
import {add as addCoordinate,equals as coordinatesEqual,rotate as rotateCoordinate,
} from './coordinate.js';
import {assert} from './asserts.js';
import {assign} from './obj.js';
import {none as centerNone, createExtent} from './centerconstraint.js';
import {clamp, modulo} from './math.js';
import {createMinMaxResolution} from './resolutionconstraint.js';
import {createSnapToN,createSnapToZero,disable,none as rotationNone,
} from './rotationconstraint.js';
import {createSnapToPower,createSnapToResolutions,
} from './resolutionconstraint.js';
import {easeOut} from './easing.js';
import {equals} from './coordinate.js';
import {getCenter,getForViewAndSize,getHeight,getWidth,isEmpty,
} from './extent.js';
import {inAndOut} from './easing.js';
import {linearFindNearest} from './array.js';
import {fromExtent as polygonFromExtent} from './geom/Polygon.js';/*** An animation configuration** @typedef {Object} Animation* @property {import("./coordinate.js").Coordinate} [sourceCenter] Source center.* @property {import("./coordinate.js").Coordinate} [targetCenter] Target center.* @property {number} [sourceResolution] Source resolution.* @property {number} [targetResolution] Target resolution.* @property {number} [sourceRotation] Source rotation.* @property {number} [targetRotation] Target rotation.* @property {import("./coordinate.js").Coordinate} [anchor] Anchor.* @property {number} start Start.* @property {number} duration Duration.* @property {boolean} complete Complete.* @property {function(number):number} easing Easing.* @property {function(boolean):void} callback Callback.*//*** @typedef {Object} Constraints* @property {import("./centerconstraint.js").Type} center Center.* @property {import("./resolutionconstraint.js").Type} resolution Resolution.* @property {import("./rotationconstraint.js").Type} rotation Rotation.*//*** @typedef {Object} FitOptions* @property {import("./size.js").Size} [size] The size in pixels of the box to fit* the extent into. Default is the current size of the first map in the DOM that* uses this view, or `[100, 100]` if no such map is found.* @property {!Array<number>} [padding=[0, 0, 0, 0]] Padding (in pixels) to be* cleared inside the view. Values in the array are top, right, bottom and left* padding.* @property {boolean} [nearest=false] If the view `constrainResolution` option is `true`,* get the nearest extent instead of the closest that actually fits the view.* @property {number} [minResolution=0] Minimum resolution that we zoom to.* @property {number} [maxZoom] Maximum zoom level that we zoom to. If* `minResolution` is given, this property is ignored.* @property {number} [duration] The duration of the animation in milliseconds.* By default, there is no animation to the target extent.* @property {function(number):number} [easing] The easing function used during* the animation (defaults to {@link module:ol/easing.inAndOut}).* The function will be called for each frame with a number representing a* fraction of the animation's duration. The function should return a number* between 0 and 1 representing the progress toward the destination state.* @property {function(boolean):void} [callback] Function called when the view is in* its final position. The callback will be called with `true` if the animation* series completed on its own or `false` if it was cancelled.*//*** @typedef {Object} ViewOptions* @property {import("./coordinate.js").Coordinate} [center] The initial center for* the view. If a user projection is not set, the coordinate system for the center is* specified with the `projection` option. Layer sources will not be fetched if this* is not set, but the center can be set later with {@link #setCenter}.* @property {boolean|number} [constrainRotation=true] Rotation constraint.* `false` means no constraint. `true` means no constraint, but snap to zero* near zero. A number constrains the rotation to that number of values. For* example, `4` will constrain the rotation to 0, 90, 180, and 270 degrees.* @property {boolean} [enableRotation=true] Enable rotation.* If `false`, a rotation constraint that always sets the rotation to zero is* used. The `constrainRotation` option has no effect if `enableRotation` is* `false`.* @property {import("./extent.js").Extent} [extent] The extent that constrains the* view, in other words, nothing outside of this extent can be visible on the map.* @property {boolean} [constrainOnlyCenter=false] If true, the extent* constraint will only apply to the view center and not the whole extent.* @property {boolean} [smoothExtentConstraint=true] If true, the extent* constraint will be applied smoothly, i.e. allow the view to go slightly outside* of the given `extent`.* @property {number} [maxResolution] The maximum resolution used to determine* the resolution constraint. It is used together with `minResolution` (or* `maxZoom`) and `zoomFactor`. If unspecified it is calculated in such a way* that the projection's validity extent fits in a 256x256 px tile. If the* projection is Spherical Mercator (the default) then `maxResolution` defaults* to `40075016.68557849 / 256 = 156543.03392804097`.* @property {number} [minResolution] The minimum resolution used to determine* the resolution constraint. It is used together with `maxResolution` (or* `minZoom`) and `zoomFactor`. If unspecified it is calculated assuming 29* zoom levels (with a factor of 2). If the projection is Spherical Mercator* (the default) then `minResolution` defaults to* `40075016.68557849 / 256 / Math.pow(2, 28) = 0.0005831682455839253`.* @property {number} [maxZoom=28] The maximum zoom level used to determine the* resolution constraint. It is used together with `minZoom` (or* `maxResolution`) and `zoomFactor`. Note that if `minResolution` is also* provided, it is given precedence over `maxZoom`.* @property {number} [minZoom=0] The minimum zoom level used to determine the* resolution constraint. It is used together with `maxZoom` (or* `minResolution`) and `zoomFactor`. Note that if `maxResolution` is also* provided, it is given precedence over `minZoom`.* @property {boolean} [multiWorld=false] If `false` the view is constrained so* only one world is visible, and you cannot pan off the edge. If `true` the map* may show multiple worlds at low zoom levels. Only used if the `projection` is* global. Note that if `extent` is also provided it is given precedence.* @property {boolean} [constrainResolution=false] If true, the view will always* animate to the closest zoom level after an interaction; false means* intermediary zoom levels are allowed.* @property {boolean} [smoothResolutionConstraint=true] If true, the resolution* min/max values will be applied smoothly, i. e. allow the view to exceed slightly* the given resolution or zoom bounds.* @property {boolean} [showFullExtent=false] Allow the view to be zoomed out to* show the full configured extent. By default, when a view is configured with an* extent, users will not be able to zoom out so the viewport exceeds the extent in* either dimension. This means the full extent may not be visible if the viewport* is taller or wider than the aspect ratio of the configured extent. If* showFullExtent is true, the user will be able to zoom out so that the viewport* exceeds the height or width of the configured extent, but not both, allowing the* full extent to be shown.* @property {import("./proj.js").ProjectionLike} [projection='EPSG:3857'] The* projection. The default is Spherical Mercator.* @property {number} [resolution] The initial resolution for the view. The* units are `projection` units per pixel (e.g. meters per pixel). An* alternative to setting this is to set `zoom`. Layer sources will not be* fetched if neither this nor `zoom` are defined, but they can be set later* with {@link #setZoom} or {@link #setResolution}.* @property {Array<number>} [resolutions] Resolutions that determine the* zoom levels if specified. The index in the array corresponds to the zoom level,* therefore the resolution values have to be in descending order. It also constrains* the resolution by the minimum and maximum value. If set the `maxResolution`,* `minResolution`, `minZoom`, `maxZoom`, and `zoomFactor` options are ignored.* @property {number} [rotation=0] The initial rotation for the view in radians* (positive rotation clockwise, 0 means North).* @property {number} [zoom] Only used if `resolution` is not defined. Zoom* level used to calculate the initial resolution for the view.* @property {number} [zoomFactor=2] The zoom factor used to compute the* corresponding resolution.* @property {!Array<number>} [padding=[0, 0, 0, 0]] Padding (in css pixels).* If the map viewport is partially covered with other content (overlays) along* its edges, this setting allows to shift the center of the viewport away from* that content. The order of the values is top, right, bottom, left.*//*** @typedef {Object} AnimationOptions* @property {import("./coordinate.js").Coordinate} [center] The center of the view at the end of* the animation.* @property {number} [zoom] The zoom level of the view at the end of the* animation. This takes precedence over `resolution`.* @property {number} [resolution] The resolution of the view at the end* of the animation. If `zoom` is also provided, this option will be ignored.* @property {number} [rotation] The rotation of the view at the end of* the animation.* @property {import("./coordinate.js").Coordinate} [anchor] Optional anchor to remain fixed* during a rotation or resolution animation.* @property {number} [duration=1000] The duration of the animation in milliseconds.* @property {function(number):number} [easing] The easing function used* during the animation (defaults to {@link module:ol/easing.inAndOut}).* The function will be called for each frame with a number representing a* fraction of the animation's duration. The function should return a number* between 0 and 1 representing the progress toward the destination state.*//*** @typedef {Object} State* @property {import("./coordinate.js").Coordinate} center Center.* @property {import("./proj/Projection.js").default} projection Projection.* @property {number} resolution Resolution.* @property {number} rotation Rotation.* @property {number} zoom Zoom.*//*** Default min zoom level for the map view.* @type {number}*/
const DEFAULT_MIN_ZOOM = 0;/*** @typedef {import("./ObjectEventType").Types|'change:center'|'change:resolution'|'change:rotation'} ViewObjectEventTypes*//**** @template Return* @typedef {import("./Observable").OnSignature<import("./Observable").EventTypes, import("./events/Event.js").default, Return> &* import("./Observable").OnSignature<ViewObjectEventTypes, import("./Object").ObjectEvent, Return> &* import("./Observable").CombinedOnSignature<import("./Observable").EventTypes|ViewObjectEventTypes, Return>} ViewOnSignature*//*** @classdesc* A View object represents a simple 2D view of the map.** This is the object to act upon to change the center, resolution,* and rotation of the map.** A View has a `projection`. The projection determines the* coordinate system of the center, and its units determine the units of the* resolution (projection units per pixel). The default projection is* Spherical Mercator (EPSG:3857).** ### The view states** A View is determined by three states: `center`, `resolution`,* and `rotation`. Each state has a corresponding getter and setter, e.g.* `getCenter` and `setCenter` for the `center` state.** The `zoom` state is actually not saved on the view: all computations* internally use the `resolution` state. Still, the `setZoom` and `getZoom`* methods are available, as well as `getResolutionForZoom` and* `getZoomForResolution` to switch from one system to the other.** ### The constraints** `setCenter`, `setResolution` and `setRotation` can be used to change the* states of the view, but any constraint defined in the constructor will* be applied along the way.** A View object can have a *resolution constraint*, a *rotation constraint** and a *center constraint*.** The *resolution constraint* typically restricts min/max values and* snaps to specific resolutions. It is determined by the following* options: `resolutions`, `maxResolution`, `maxZoom` and `zoomFactor`.* If `resolutions` is set, the other three options are ignored. See* documentation for each option for more information. By default, the view* only has a min/max restriction and allow intermediary zoom levels when* pinch-zooming for example.** The *rotation constraint* snaps to specific angles. It is determined* by the following options: `enableRotation` and `constrainRotation`.* By default rotation is allowed and its value is snapped to zero when approaching the* horizontal.** The *center constraint* is determined by the `extent` option. By* default the view center is not constrained at all.** ### Changing the view state** It is important to note that `setZoom`, `setResolution`, `setCenter` and* `setRotation` are subject to the above mentioned constraints. As such, it* may sometimes not be possible to know in advance the resulting state of the* View. For example, calling `setResolution(10)` does not guarantee that* `getResolution()` will return `10`.** A consequence of this is that, when applying a delta on the view state, one* should use `adjustCenter`, `adjustRotation`, `adjustZoom` and `adjustResolution`* rather than the corresponding setters. This will let view do its internal* computations. Besides, the `adjust*` methods also take an `opt_anchor`* argument which allows specifying an origin for the transformation.** ### Interacting with the view** View constraints are usually only applied when the view is *at rest*, meaning that* no interaction or animation is ongoing. As such, if the user puts the view in a* state that is not equivalent to a constrained one (e.g. rotating the view when* the snap angle is 0), an animation will be triggered at the interaction end to* put back the view to a stable state;** @api*/
class View extends BaseObject {/*** @param {ViewOptions} [opt_options] View options.*/constructor(opt_options) {super();/**** @type {ViewOnSignature<import("./Observable.js").OnReturn>}*/this.on;/**** @type {ViewOnSignature<import("./Observable.js").OnReturn>}*/this.once;/**** @type {ViewOnSignature<void>}*/this.un;const options = assign({}, opt_options);/*** @private* @type {Array<number>}*/this.hints_ = [0, 0];/*** @private* @type {Array<Array<Animation>>}*/this.animations_ = [];/*** @private* @type {number|undefined}*/this.updateAnimationKey_;/*** @private* @const* @type {import("./proj/Projection.js").default}*/this.projection_ = createProjection(options.projection, 'EPSG:3857');/*** @private* @type {import("./size.js").Size}*/this.viewportSize_ = [100, 100];/*** @private* @type {import("./coordinate.js").Coordinate|undefined}*/this.targetCenter_ = null;/*** @private* @type {number|undefined}*/this.targetResolution_;/*** @private* @type {number|undefined}*/this.targetRotation_;/*** @private* @type {import("./coordinate.js").Coordinate|undefined}*/this.cancelAnchor_ = undefined;if (options.center) {options.center = fromUserCoordinate(options.center, this.projection_);}if (options.extent) {options.extent = fromUserExtent(options.extent, this.projection_);}this.applyOptions_(options);}/*** Set up the view with the given options.* @param {ViewOptions} options View options.*/applyOptions_(options) {/*** @type {Object<string, *>}*/const properties = {};const resolutionConstraintInfo = createResolutionConstraint(options);/*** @private* @type {number}*/this.maxResolution_ = resolutionConstraintInfo.maxResolution;/*** @private* @type {number}*/this.minResolution_ = resolutionConstraintInfo.minResolution;/*** @private* @type {number}*/this.zoomFactor_ = resolutionConstraintInfo.zoomFactor;/*** @private* @type {Array<number>|undefined}*/this.resolutions_ = options.resolutions;/*** @type {Array<number>|undefined}* @private*/this.padding_ = options.padding;/*** @private* @type {number}*/this.minZoom_ = resolutionConstraintInfo.minZoom;const centerConstraint = createCenterConstraint(options);const resolutionConstraint = resolutionConstraintInfo.constraint;const rotationConstraint = createRotationConstraint(options);/*** @private* @type {Constraints}*/this.constraints_ = {center: centerConstraint,resolution: resolutionConstraint,rotation: rotationConstraint,};this.setRotation(options.rotation !== undefined ? options.rotation : 0);this.setCenterInternal(options.center !== undefined ? options.center : null);if (options.resolution !== undefined) {this.setResolution(options.resolution);} else if (options.zoom !== undefined) {this.setZoom(options.zoom);}this.setProperties(properties);/*** @private* @type {ViewOptions}*/this.options_ = options;}/*** Padding (in css pixels).* If the map viewport is partially covered with other content (overlays) along* its edges, this setting allows to shift the center of the viewport away from that* content. The order of the values in the array is top, right, bottom, left.* The default is no padding, which is equivalent to `[0, 0, 0, 0]`.* @type {Array<number>|undefined}* @api*/get padding() {return this.padding_;}set padding(padding) {let oldPadding = this.padding_;this.padding_ = padding;const center = this.getCenter();if (center) {const newPadding = padding || [0, 0, 0, 0];oldPadding = oldPadding || [0, 0, 0, 0];const resolution = this.getResolution();const offsetX =(resolution / 2) *(newPadding[3] - oldPadding[3] + oldPadding[1] - newPadding[1]);const offsetY =(resolution / 2) *(newPadding[0] - oldPadding[0] + oldPadding[2] - newPadding[2]);this.setCenterInternal([center[0] + offsetX, center[1] - offsetY]);}}/*** Get an updated version of the view options used to construct the view. The* current resolution (or zoom), center, and rotation are applied to any stored* options. The provided options can be used to apply new min/max zoom or* resolution limits.* @param {ViewOptions} newOptions New options to be applied.* @return {ViewOptions} New options updated with the current view state.*/getUpdatedOptions_(newOptions) {const options = assign({}, this.options_);// preserve resolution (or zoom)if (options.resolution !== undefined) {options.resolution = this.getResolution();} else {options.zoom = this.getZoom();}// preserve centeroptions.center = this.getCenterInternal();// preserve rotationoptions.rotation = this.getRotation();return assign({}, options, newOptions);}/*** Animate the view. The view's center, zoom (or resolution), and rotation* can be animated for smooth transitions between view states. For example,* to animate the view to a new zoom level:** view.animate({zoom: view.getZoom() + 1});** By default, the animation lasts one second and uses in-and-out easing. You* can customize this behavior by including `duration` (in milliseconds) and* `easing` options (see {@link module:ol/easing}).** To chain together multiple animations, call the method with multiple* animation objects. For example, to first zoom and then pan:** view.animate({zoom: 10}, {center: [0, 0]});** If you provide a function as the last argument to the animate method, it* will get called at the end of an animation series. The callback will be* called with `true` if the animation series completed on its own or `false`* if it was cancelled.** Animations are cancelled by user interactions (e.g. dragging the map) or by* calling `view.setCenter()`, `view.setResolution()`, or `view.setRotation()`* (or another method that calls one of these).** @param {...(AnimationOptions|function(boolean): void)} var_args Animation* options. Multiple animations can be run in series by passing multiple* options objects. To run multiple animations in parallel, call the method* multiple times. An optional callback can be provided as a final* argument. The callback will be called with a boolean indicating whether* the animation completed without being cancelled.* @api*/animate(var_args) {if (this.isDef() && !this.getAnimating()) {this.resolveConstraints(0);}const args = new Array(arguments.length);for (let i = 0; i < args.length; ++i) {let options = arguments[i];if (options.center) {options = assign({}, options);options.center = fromUserCoordinate(options.center,this.getProjection());}if (options.anchor) {options = assign({}, options);options.anchor = fromUserCoordinate(options.anchor,this.getProjection());}args[i] = options;}this.animateInternal.apply(this, args);}/*** @param {...(AnimationOptions|function(boolean): void)} var_args Animation options.*/