3-Openlayers源码学习-Map

393 阅读3分钟

Map类可以说是所有前端地图库的核心,是地图开发中最基本的类。包括常用地图框架入口都是它:

  • Leaflet:L.Map
  • MapboxGL: mapboxgl.Map
  • ArcGIS JS API: esri/Map & esri/MapView
  • Openlayers: ol.Map

不同的框架Map的用途会有不同特色,但都和地图DOM挂载初始化,图层操作,地图视图操作,地图事件相关。

回到Openlayers,分析它的Map的有哪些内容: Map

从 API上可以看到,ol.Map 主要是几大功能:

  • 挂载地图容器Dom节点,获取Dom节点,设置Dom节点。
  • view,layers,control,interaction,overlay相关设置或移除。
  • 渲染方法。
  • 地图的事件。

Map的继承关系

ol 7 的继承链是 Map => BaseObject => Observable => EventTarget,对比 ol6 已将 PluggableMap类合并到Map类中。

之前也提过,继承自EventTarget,就比较方便对地图的事件进行处理和暴露了。

Map的构造函数做了啥

在 进行 new Map()的时候,主要做了以下事情:

  • 事件处理程序初始化,on、once、un
  • 一些私有属性
  • 创建切片的队列类
  • viewport、overlayContainer dom节点创建
  • 构造时传入的Options关键参数处理:主要是createOptionsInternal 函数的执行,返回了如下内容:
  const values = {};
  
  values[MapProperty.LAYERGROUP] = layerGroup;

  values[MapProperty.TARGET] = options.target;

  values[MapProperty.VIEW] = options.view instanceof View ? options.view : new View();
  
  ......
  
  return {
    controls: controls,
    interactions: interactions,
    keyboardEventTarget: keyboardEventTarget,
    overlays: overlays,
    values: values,
  };

把主要的layerGroup、interactions、controls、overlays、view对象和collection对象创建。

  • layerGroup, view, size, target的change事件注册
    this.addChangeListener(MapProperty.LAYERGROUP,this.handleLayerGroupChanged_);
    this.addChangeListener(MapProperty.VIEW, this.handleViewChanged_);
    this.addChangeListener(MapProperty.SIZE, this.handleSizeChanged_);
    this.addChangeListener(MapProperty.TARGET, this.handleTargetChanged_);
  • controls, interactions, overlays 集合的 add、remove事件注册
  • controls,interactions, overlays 挂载map对象(setMap调用)

Map的渲染触发和流程

考虑到Map 继承自 BaseObject,在构造函数中,进行setProperties操作,会触发之前注册的Layer, view, size, target change方法。

  1. 首先看handleLayerGroupChanged_,此回调函数除了会初始化layergroup 的 add, remove事件注册。最后调用了this.render()
  2. render方法会判断this.renderer_是否存在,若存在,判断animationDelayKey_(下一帧动画回调函数标识)是否未定义,则创建一个重绘前的回调。则但此时this.renderer_是不存在的,于是函数退出。
  3. 接着是handleTargetChanged_回调函数,往目标的dom挂载地图容器的viewport_ dom节点,并开始创建地图渲染器类的实例(CompositeMapRenderer)给this.renderer_,调用updateSize()方法,触发setSize()。
  4. 接着触发handleViewChanged_回调函数,调用render方法,创建一个重绘前的回调函数:animationDelay_()。
  5. animationDelay_()回调函数内:传入当前时间戳执行renderFrame_()
  6. 最后是handleViewChanged_回调函数,同样调用this.render(),此时animationDelayKey_已存在,跳出函数。

总体来说,渲染触发流程如上步骤所述,重点在于 CompositeMapRender 和 renderFrame_,后面再重点研究这块。

Map的事件

地图的事件包括浏览器事件,渲染的事件,属性变化的事件等,这里以地图浏览器事件的处理为例,涉及到MapBrowserEventHandler,MapBrowserEvent类。MapBrowserEventHandler的作用是dom事件和地图结合的处理中心,创建dom事件的监听,经过MapBrowserEvent类的包装,最后通过dispatch进行事件的派发操作。

如下图,简单描述了map.on,map.once去使用地图的浏览器事件的一个机制

未命名绘图.png

其他

layerGroup、interactions、controls、overlays 在构造函数中已创建相应的collection对象实例,其实可以看到相应的get方法实际上是返回相应的collection对象。 如:

image.png 同理,add方法是往相应的collection().push() 同类型的实例。remove的方法是往相应的collection().remove()同类型的实例