分析 Earthquake Clusters 这个 demo,官网介绍是:
This example parses a KML file and renders the features as clusters on a vector layer. The styling in this example is quite involved. Single earthquake locations (rendered as stars) have a size relative to their magnitude. Clusters have an opacity relative to the number of features in the cluster, and a size that represents the extent of the features that make up the cluster. When clicking or hovering on a cluster, the individual features that make up the cluster will be shown.
To achieve this, we make heavy use of style functions.
本示例将解析 KML 文件并在矢量图层上将要素渲染成聚合点。在这个示例中的样式非常复杂。单个的地震点(被渲染成了星状)的大小与震级相关。聚合点的透明度与聚合点内要素的数量相关,并且聚合点的大小也代表着聚合点内要素的四至。当在聚合点上点击或者悬浮时,组成聚合点的各个要素就会被展示。
由于上述原因,我们大量使用了样式函数。
官网实例:Earthquake Clusters
跟我学 OpenLayers——基础实例讲解:6 要素 ol.feature 的使用 > 实例 33.地震信息的要素聚合
定义基本结构
地图的基本结构如下所示,raster
图层使用的是普通的 toner
碳粉地图,不一样的地方是 vector
矢量图层的定义。在 source
中使用了ol.source.Cluster,这个就是 OpenLayers 官方的点聚合源,distance
属性判定两个聚合点之间最小像素距离。在source
中的 source
属性里,ol.source.Vector中 url
属性是数据源的链接,format
属性是根据数据源格式来设定。
这里最关键的是 vector
中 style
属性,样式是从 styleFunction
函数中返回的,这是整个地震点聚合的核心。
1 |
|
地图中还有一个不一样的地方是,数据源使用 KML 格式。KML 格式属于 XML 规范,文件里面是各种标签,笼统地说,在解析的时候标签名就是键名,标签里面的内容就是键值,如下所示,name
标签中存放就是地震震级、时间、地理位置等信息,Point
下的 coordinates
存放的是经纬度信息。
1 |
|
普通地震点样式
未聚合的普通地震点是一个五角星,五角星的尺寸与该点的地震震级大小正相关,如图所示。
具体实现时,是先创建好地震点的 fill
和 stroke
样式,再给每个点使用一个 createEarthquakeStyle
样式函数返回 style
。通过裁剪字符串取到了地震震级后转换为 radius
,震级越大,radius
越大。
最后返回ol.style.Style的时候,geometry中存放位置信息,image中存放一个ol.style.RegularShape对象。这个 RegularShape
对象是 OpenLayers 为了便于快速绘制规则图形而加入的,把 radius
、earthquakeFill
、earthquakeStroke
传进去后就能返回一个完备的五角星 style
对象。
1 | // 地震点fill样式 |
计算地震点聚合信息
先声明一个 maxFeatureCount
存放最多的聚合 cluster
中聚合地震点的数目,主要目的是用后后面计算聚合圆圈的透明度。获取到图层的的聚合点要素数组以后,迭代并在每个聚合点要素中获取原始的要素信息。
原始的要素信息主要有两个作用,一个是计算最大的聚合点中的原始要素数目,这个数目跟聚合点的透明度有关系,第二个是计算每个聚合点的四至,利用这个四至和 resolution
(每个像素代表多少米),就能计算聚合点的半径大小。
1 | // 最多的聚合数,便于计算聚合圆圈的透明度 |
四至
四至是地理学的名词,笼统说就是包含一个要素的最小矩形范围,可以用一个数组来表示[minx, miny, maxx, maxy]
。
在迭代计算聚合点的四至时,是先ol.extent.createEmpty()创建了一个空的四至,再使用ol.extent.extend()使范围不断扩大,最终使 extent
中包含整个聚合点所有原始要素的四至。最后在计算半径的时候,获取 extent
的长度和宽度,除以 resolution
就能转变为像素数,就可以计算出像素半径。
styleFunction 与 selectStyleFunction
styleFunction
做好了前文的各项准备之后,就能构造矢量图层的样式返回函数 styleFunction
,这个函数可以获取到两个入参 feature
和 resolution
。
resolution 使用的时候首先判断和之前保存的 currentResolution
是否一致,也就是判断有没有缩小或者放大地图。如果不一致需要调用 calculateClusterInfo
函数。重新来计算聚合点的原始要素数目和四至,也就是聚合点的透明度和半径大小。
feature 使用的时候首先要判断聚合点要素的原始要素数目。如果等于 1 就代表只有一个原始要素,就正常返回 createEarthquakeStyle(originalFeature)
,也就是在地图上直接绘制一个五角星。
如果大于 1,就需要返回聚合点要素的样式,看代码可以发现,聚合点样式是使用image
和 text
来构造。image
构造出了一个圆圈,半径直接取 calculateClusterInfo
函数设置给要素的 radius
,rgba
颜色中的透明度是使用 maxFeatureCount
计算得出。text
是圆圈上的文字,文字内容是每个聚合点要素的原始要素数目。
1 | // 文本fill样式 |
selectStyleFunction
这个 selectStyleFunction
样式函数中返回的是当鼠标悬浮或者单击聚合点时的样式。在 invisibleFill
能够发现其实是把聚合点圆圈和文本的透明度设置成了 0.01
,接近透明。
聚合点中原始要素的显示,是迭代每一个原始要素,使用 createEarthquakeStyle
函数 push
出一个 style
数组并返回,就能把聚合点中包含的所有五角星全都显示出来。
1 | // 隐藏状态时的fill样式 |
全部代码
最后贴存出全部代码:
1 |
|