源码分析之Openlayers中的Zoom缩放控件

概述

放大或缩小是地图中最基本的功能,本文主要介绍分析 Openlayers 中Zoom缩放控件的源码实现。

源码分析

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

如果直接实例化Zoom类,页面上显示的是 Openlayers 中原生的样式,无论是控件的标签页还是样式,我们都可以通过传参进行定制。本文只讨论默认情况,不传参的情况。

源码如下:

js 复制代码
class Zoom extends Control {
  constructor(options) {
    options = options ? options : {};

    super({
      element: document.createElement("div"),
      target: options.target,
    });

    const className =
      options.className !== undefined ? options.className : "ol-zoom";

    const delta = options.delta !== undefined ? options.delta : 1;

    const zoomInClassName =
      options.zoomInClassName !== undefined
        ? options.zoomInClassName
        : className + "-in";

    const zoomOutClassName =
      options.zoomOutClassName !== undefined
        ? options.zoomOutClassName
        : className + "-out";

    const zoomInLabel =
      options.zoomInLabel !== undefined ? options.zoomInLabel : "+";
    const zoomOutLabel =
      options.zoomOutLabel !== undefined ? options.zoomOutLabel : "\u2013";

    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 = zoomInClassName;
    inElement.setAttribute("type", "button");
    inElement.title = zoomInTipLabel;
    inElement.appendChild(
      typeof zoomInLabel === "string"
        ? document.createTextNode(zoomInLabel)
        : zoomInLabel
    );

    inElement.addEventListener(
      EventType.CLICK,
      this.handleClick_.bind(this, delta),
      false
    );

    const outElement = document.createElement("button");
    outElement.className = zoomOutClassName;
    outElement.setAttribute("type", "button");
    outElement.title = zoomOutTipLabel;
    outElement.appendChild(
      typeof zoomOutLabel === "string"
        ? document.createTextNode(zoomOutLabel)
        : zoomOutLabel
    );

    outElement.addEventListener(
      EventType.CLICK,
      this.handleClick_.bind(this, -delta),
      false
    );

    const cssClasses =
      className + " " + CLASS_UNSELECTABLE + " " + CLASS_CONTROL;
    const element = this.element;
    element.className = cssClasses;
    element.appendChild(inElement);
    element.appendChild(outElement);

    this.duration_ = options.duration !== undefined ? options.duration : 250;
  }
  handleClick_(delta, event) {
    event.preventDefault();
    this.zoomByDelta_(delta);
  }
  zoomByDelta_(delta) {}
}

Zoom控件参数

Zoom类中的构造函数接受一个参数options,若它为空或者不传,则 Openlayers 将采用默认样式。options对象可以有如下属性:

  • className:Zoom类名,默认为ol-zoom
  • delta:缩放地图的变化量,默认为1
  • zoomInClassName:放大控件的类名,默认为ol-zoom-in
  • zoomOutClassName:缩小控件的类名,默认为ol-zoom-out
  • zoomInLabel:放大控件图标,默认为+
  • zoomOutLabel:缩小控件图标,默认为\u2013(即-
  • zoomInTipLabel:放大控件hover时的提示,默认为Zoom in
  • zoomOutTipLabel:缩小控件hover时的提示,默认为Zoom out

Zoom类构造函数

Zoom类的构造函数除了根据参数options定义上述变量外,还调用super({element:document.createElement('div'),target:options.target})elementtarget传给父类Control,默认情况下options.targetundefined,因此这个传值就是设置了this.element=document.createElement('div');然后就是创建放大和缩小控件的DOM元素,设置属性,并将它们插入到this.element。期间还会注册放大按钮和缩小按钮的两个事件,事件名为handleClick,不同的是delta传参不同。最后设置了this.duration_,若参数options中定义了duration属性和值,则赋给this.duration_,否则默认为250,表示是250 毫秒

Zoom类方法介绍

Zoom类中定义了两个方法handleClick_zoomByDelta_handleClick_就是后者的一个调用,核心方法就是zoomByDelta_

  • zoomByDelta_方法

zoomByDelta方法如下

js 复制代码
zoomByDelta_(delta) {
    const map = this.getMap();
    const view = map.getView();
    if (!view) {
      return;
    }
    const currentZoom = view.getZoom();
    if (currentZoom !== undefined) {
      const newZoom = view.getConstrainedZoom(currentZoom + delta); //返回被限制的级别,不超出范围
      if (this.duration_ > 0) {
        if (view.getAnimating()) { // 若有动画正在进行,则取消动画
          view.cancelAnimations();
        }
        view.animate({
          zoom: newZoom,
          duration: this.duration_,
          easing: easeOut,
        });
      } else {
        view.setZoom(newZoom);
      }
    }
}

在上面代码中this.getMap()实际上就是调用父类ControlgetMap方法中,在Map类中实例化时,会遍历this.controls,调用setMap方法;或者在const map=new Map(...)后,用map.addControl添加控件时,会触发this.controls.addEventListener(CollectionEventType.ADD,(event) => {event.element.setMap(this);},);同样地会设置setMap,因此Zoom缩放控件被点击时触发zoomByDelta_,调用this.getMap是可以取到map对象,然后通过map.getView获取当前视图view,继而获取当前地图的级别currentZoom,进行边界判断,然后放大调用view.animate,缩小调用view.setZoom

总结

本文主要介绍了Openlayers中Zoom缩放控件的源码实现,讲解了缩放的核心知识。

相关推荐
小彭努力中1 天前
26.使用 Vue 3 + OpenLayers 加载远程 Shapefile 数据并显示图形
前端·javascript·vue.js·arcgis·openlayers
小彭努力中6 天前
16.在 Vue 3 中使用 OpenLayers 实现自定义地图缩放控件
前端·javascript·vue.js·arcgis·openlayers
小彭努力中6 天前
13.在 Vue 3 中使用OpenLayers加载鹰眼控件示例教程
前端·javascript·vue.js·arcgis·openlayers
Jinuss6 天前
源码分析之Openlayers图层基类BaseLayer介绍
openlayers
ANNENBERG7 天前
openlayers地图事件
openlayers
ANNENBERG7 天前
openlayers地图缓存添加
缓存·openlayers
duansamve23 天前
WebGIS地图框架有哪些?
javascript·gis·openlayers·cesium·mapbox·leaflet·webgis
ReBeX1 个月前
【GeoJSON在线编辑平台】(1)创建地图+要素绘制+折点编辑+拖拽移动
前端·javascript·gis·openlayers·webgis
zj靖4 个月前
Openlayers6之地图覆盖物Overlay详解及使用,地图标注及弹窗查看详情(结合React)
前端·react.js·openlayers