源码分析之Openlayers中MousePosition鼠标位置控件

概述

本文主要介绍 Openlayers 中的MousePosition鼠标位置控件,该控件会创建一个元素在页面的右上方用来实时显示鼠标光标的位置坐标。该控件在实际应用很有效,可以实时获取鼠标位置,但是一般控件元素都会自定义。

源码分析

MousePosition类是继承于Control类,关于Control类,可以参考这篇文章源码分析之Openlayers中的控件篇Control基类介绍

MousePosition类实现如下:

js 复制代码
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设置了,还会注册viewportpointeroutthis.handleMouseOut事件。

总结

本文主要介绍了 Openlayers 中MousePosition鼠标位置控件的源码实现,核心就是注册viewport对象上pointermove类型的监听事件获取屏幕坐标,然后调用内部方法map.getCoordinateFromPixelInternal将屏幕坐标转化为实际的地理位置坐标。

相关推荐
Jinuss4 小时前
源码分析之Openlayers中ZoomSlider滑块缩放控件
openlayers
小彭努力中10 小时前
38.在 Vue 3 中使用 OpenLayers 导出地图为 PDF
前端·javascript·vue.js·深度学习·pdf·openlayers
小彭努力中2 天前
32.在 Vue 3 中上传 KML 文件并在地图上显示
前端·javascript·vue.js·深度学习·openlayers
小彭努力中5 天前
29.在Vue 3中使用OpenLayers读取WKB数据并显示图形
前端·javascript·vue.js·深度学习·openlayers
Jinuss6 天前
源码分析之Openlayers中的Zoom缩放控件
openlayers
小彭努力中7 天前
26.使用 Vue 3 + OpenLayers 加载远程 Shapefile 数据并显示图形
前端·javascript·vue.js·arcgis·openlayers
小彭努力中12 天前
16.在 Vue 3 中使用 OpenLayers 实现自定义地图缩放控件
前端·javascript·vue.js·arcgis·openlayers
小彭努力中12 天前
13.在 Vue 3 中使用OpenLayers加载鹰眼控件示例教程
前端·javascript·vue.js·arcgis·openlayers
Jinuss12 天前
源码分析之Openlayers图层基类BaseLayer介绍
openlayers