概述
本文主要介绍 Openlayers 中的MousePosition
鼠标位置控件,该控件会创建一个元素在页面的右上方用来实时显示鼠标光标的位置坐标。该控件在实际应用很有效,可以实时获取鼠标位置,但是一般控件元素都会自定义。
源码分析
MousePosition
类是继承于Control
类,关于Control
类,可以参考这篇文章源码分析之Openlayers中的控件篇Control基类介绍。
MousePosition
类实现如下:
class MousePosition extends Control {
constructor(options) {
options = options ? options : {};
const element = document.createElement("div");
element.className =
options.className !== undefined ? options.className : "ol-mouse-position";
super({
element: element,
render: options.render,
target: options.target,
});
this.on;
this.once;
this.un;
this.addChangeListener(PROJECTION, this.handleProjectionChanged_);
if (options.coordinateFormat) {
this.setCoordinateFormat(options.coordinateFormat);
}
if (options.projection) {
this.setProjection(options.projection);
}
this.renderOnMouseOut_ = options.placeholder !== undefined;
this.placeholder_ = this.renderOnMouseOut_ ? options.placeholder : " ";
this.renderedHTML_ = element.innerHTML;
this.mapProjection_ = null;
this.transform_ = null;
this.wrapX_ = options.wrapX === false ? false : true;
}
handleProjectionChanged_() {
this.transform_ = null;
}
getCoordinateFormat() {
return this.get(COORDINATE_FORMAT);
}
handleMouseOut(event) {
this.updateHTML_(null);
}
getProjection() {
return this.get(PROJECTION);
}
handleMouseMove(event) {
const map = this.getMap();
this.updateHTML_(map.getEventPixel(event));
}
setMap(map) {
super.setMap(map);
if (map) {
const viewport = map.getViewport();
this.listenerKeys.push(
listen(viewport, EventType.POINTERMOVE, this.handleMouseMove, this)
);
if (this.renderOnMouseOut_) {
this.listenerKeys.push(
listen(viewport, EventType.POINTEROUT, this.handleMouseOut, this)
);
}
this.updateHTML_(null);
}
}
setCoordinateFormat(format) {
this.set(COORDINATE_FORMAT, format);
}
setProjection(projection) {
this.set(PROJECTION, getProjection(projection));
}
updateHTML_(pixel) {
let html = this.placeholder_;
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.getCoordinateFromPixelInternal(pixel);
if (coordinate) {
const userProjection = getUserProjection();
if (userProjection) {
this.transform_ = getTransformFromProjections(
this.mapProjection_,
userProjection
);
}
this.transform_(coordinate, coordinate);
if (this.wrapX_) {
const projection =
userProjection || this.getProjection() || this.mapProjection_;
wrapX(coordinate, projection);
}
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;
}
}
render(mapEvent) {
const frameState = mapEvent.frameState;
if (!frameState) {
this.mapProjection_ = null;
} else {
if (this.mapProjection_ != frameState.viewState.projection) {
this.mapProjection_ = frameState.viewState.projection;
this.transform_ = null;
}
}
}
}
MousePosition
类构造函数
MousePosition
类构造函数接受一个参数对象options
,该参数可以包含如下属性:
className
:控件类名,默认为ol-mouse-position
render
:自定义render
方法,默认undefined
target
:控件容器,默认undefined
coordinateFormat
:坐标格式化,默认undefined
projection
:分辨率,默认undefined
placeholder
:提示填充字符wrapX
:是否水平方向重复延申
构造函数首先会先注册projection
的监听事件this.handleProjectionChanged_
,若该值发生变化,则将this.transform_
置null
;然后判断,若options.coordinateFormat
存在,则调用this.setCoordinateFormat
方法;若options.projection
存在,则调用this.setProjection
方法;
MousePosition
类中的方法
getCoordinateFormat
方法:获取坐标格式化getProjection
方法:获取投影handleMouseMove
方法:接受一个参数event
,该方法是鼠标在地图上移动时调用,会更新控件的内容坐标的值,getEventPixel
就是根据参数event
获取鼠标的位置以及viewport
的某些属性,然后计算屏幕坐标handleMouseOut
方法:鼠标移除地图时调用setCoordinateFormat
方法:设置坐标格式化setProjection
方法:设置投影updateHTML_
方法:根据屏幕坐标获取地理坐标render
方法:在调用父类的setMap
方法时会调用,主要用于设置this.mapProject_
setMap
方法:sepMap
方法会在Map
类中调用,内部首先会调用父类的setMap
方法,然后判断参数map
是否存在,若存在,则注册viewport
视口对象pointermove
类型的监听,事件为this.handleMouseMove
;若构造函数参数options.placeholder
设置了,还会注册viewport
的pointerout
的this.handleMouseOut
事件。
总结
本文主要介绍了 Openlayers 中MousePosition
鼠标位置控件的源码实现,核心就是注册viewport
对象上pointermove
类型的监听事件获取屏幕坐标,然后调用内部方法map.getCoordinateFromPixelInternal
将屏幕坐标转化为实际的地理位置坐标。