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

发布于:2024-12-20 ⋅ 阅读:(12) ⋅ 点赞:(0)

概述

本文主要介绍 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设置了,还会注册viewportpointeroutthis.handleMouseOut事件。

总结

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