在网上可以做宣传的有那些网站,怎么自己建设一个网站,wordpress接入安卓,thinkphp做的教育网站Openlayer【二】—— 绘制不同的点、线以及给其添加监听事件
接上篇#xff1a;OpenLayer初始化
在openlayer当中#xff0c;图层Layer与地图源Source是一对一的关系。当创建了一个图层Layer#xff0c;相应的需要给图层添加地图源Source#xff0c;然后将图层Layer添加到…Openlayer【二】—— 绘制不同的点、线以及给其添加监听事件
接上篇OpenLayer初始化
在openlayer当中图层Layer与地图源Source是一对一的关系。当创建了一个图层Layer相应的需要给图层添加地图源Source然后将图层Layer添加到地图Map上就可以得到我们想要的地图了
在Source当中主要包含以下三种Tile、Image、Vector
ol.source.Tile对应的是瓦片数据源现在网页地图服务中绝大多数都是使用的瓦片地图而OpenLayers 作为一个WebGIS引擎理所当然应该支持瓦片。ol.source.Image对应的是一整张图而不像瓦片那样很多张图从而无需切片也可以加载一些地图适用于一些小场景地图。ol.source.Vector对应的是矢量地图源点线面等等常用的地图元素(Feature)就囊括到这里面了。
1、绘制点
1.1、绘制单个默认点
所以在这一步我们首先需要创建一个Layer和Source对象并且把layer加到地图上最后再往source对象当中添加对应点对象就完成了点的绘制这里的点Point对象需要添加给到source.Vector的Feature元素当中
import VectorLayer from ol/layer/Vector;
import VectorSource from ol/source/Vector;const vectorSource new VectorSource();
const vectorLayer new VectorLayer({source: vectorSource
});
this.map.addLayer(vectorLayer);const marker new Feature({geometry: new Point([120, 20])
});
vectorSource.addFeature(marker);如上代码就添加了一个点到地图上了在官网可以看到new Point()构造需要传递两个参数一个是点的位置一个是对象的布局其是一个可选参数默认参数是ol.geom.GeometryLayout.XY还可以设置为ol.geom.GeometryLayout.XYZ、ol.geom.GeometryLayout.XYM 或 ol.geom.GeometryLayout.XYZM可以通过以下代码进行调整对象的布局
import { GeometryLayout } from ol/geom/Geometry;var point new Point([10, 20, 100]);
point.setLayout(GeometryLayout.XYZ);1.2、绘制颜色填充的点
在Feature对象当中可以给整个对象统一设置样式通过setStyle()首先我们给点设置为圆形红色并且半径为6 单位米并且给圆的外面加上一个绿色宽度为3的边
marker.setStyle(new Style({image: new Circle({radius: 6,fill: new Fill({ color: red }),stroke: new Stroke({color: green,width: 3})})})
);1.3、绘制多个点
只需要循环创建圆点之后将圆通过addFeature方法添加进去即可
const vectorSource new VectorSource();
const vectorLayer new VectorLayer({source: vectorSource
});
this.map.addLayer(vectorLayer);for (let i 0; i 500; i) {const marker new Feature({geometry: new Point(this.getRandomCoordinate())});marker.setStyle(new Style({image: new Circle({radius: 6,fill: new Fill({ color: red }),stroke: new Stroke({color: green,width: 3})})}));vectorSource.addFeature(marker);
}/**
* 随机生成经纬度
*/
getRandomCoordinate() {const minLon -180; // 最小经度const maxLon 180; // 最大经度const minLat -90; // 最小纬度const maxLat 90; // 最大纬度const lon Math.random() * (maxLon - minLon) minLon;const lat Math.random() * (maxLat - minLat) minLat;return [lon, lat];
}1.4、绘制图标点
绘制图标点只需要给style加上image的相关图标配置即可绘制图标到地图上如下这里的anchor表示图标的锚点图标的中心位置、opacity表示透明度、scale表示放大缩小层级src指向对应的图标文件的位置、color表示图标的颜色对图标进行着色
marker.setStyle(new Style({image: new Icon({anchor: [0.5, 1],opacity: 1,scale: 1,src: require(./icon/point.png),color: green})})
);其中对Icon的属性可以参考官方文档OpenLayers v8.2.0 API - 类图标
1.5、给图标点加上文字
给图标加文字和前面设置图标一样都是直接给style当中添加属性即可这里添加的是text属性。这里的fill的color表示文字的填充颜色为白色、font属性可以设置文字大小和字体类型、text表示展示的文字内容、scale是一个数组表示横向(x)和纵向(y)的放大缩小层级、offsetX和offsetY分别表示文本在水平和垂直上的偏移量、最后的storke表示文字的描边
feature.setStyle(new Style({image: new Icon({anchor: [0.5, 1],opacity: 1,scale: 1,src: require(./icon/point.png),color: green}),text: new Text({fill: new Fill({color: rgba(255,255,255,0.9)}),font: 16px monospace,text: 文字,scale: [1, 1],offsetY: -30,stroke: new Stroke({ color: rgba(0,0,0,0.9), width: 2 })})})
);这里对Text的属性可以参考官方文档OpenLayers v8.2.0 API - 类文本
1.6、鼠标移入和鼠标移出点事件监听
1.6.1、实现事件监听
在这里可以在给每一个Feature初始化好了之后通过map的pointermove事件当鼠标在地图上进行移动时触发事件用来监听并且获取当前鼠标移动的位置是否包含了这个Feature对象之后通过目标的featureTarget地图监听得到的和最开始初始化得到的进行对比如果相同则表示鼠标移入到了当前图标获取对应的样式scale放大缩小的层级设置为2即为放大一倍不相同表示移出设置会成原来的样式
当然同理这里我简化了样式的设置如果给图标设置了文字的属性可以通过originalStyle.getText().setScale([2, 2])把字体也给放大一倍其余的样式也同理如此进行设置即可。这样就给页面添加了一些交互事件使得页面看起来更加活泼一点。
let source new VectorSource();
for (let i 0; i 10; i) {let feature new Feature({id: ddss,geometry: new Point(this.getRandomCoordinate())});feature.setStyle(new Style({image: new Icon({scale: 1,src: require(./icon/point.png)})}));this.map.on(pointermove, function(event) {const featureTarget this.forEachFeatureAtPixel(event.pixel, function(feature) {return feature;});if (feature featureTarget) {// 鼠标进入const originalStyle feature.getStyle();originalStyle.getImage().setScale(2);feature.setStyle(originalStyle);} else {// 鼠标移出const originalStyle feature.getStyle();originalStyle.getImage().setScale(1);feature.setStyle(originalStyle);}});source.addFeature(feature);
}
let layer new VectorLayer({opacity: 1
});
layer.setSource(source);
this.map.addLayer(layer);1.6.2、上述实现存在的问题 —— n次监听
在这里其实乍一看这样子用来实现事件监听没什么问题每一个点都给加上了监听事件而且去页面上测试一下当鼠标移入移出图标的大小确实会发生变化。那问题究竟在哪呢
大数据量的情况
在上面只初始化了10个点到页面上当初始化100个点呢1000个点呢10000个点呢在里面是循环加上的监听事件而这个监听事件是很消耗性能的10个点100个点看起来还不卡但是1000个点就明显会有卡顿了当鼠标移入后要两三秒后才回放大当10000个点整上去之后整个页面直接卡死了这个时候就需要给这段代码进行优化了如何优化这个呢很显然只需要把监听事件挪出来由10000次监听变成1次监听就好了后面监听完之后再去判断给哪个图标去放大缩小也就只有n次循环的事了。用循环n次1次监听来替换掉n次监听性能消耗一下子就被降下去了。
1.6.3、解决方案 —— 一次监听n次循环
在前面去掉那个事件监听在把图层Layer添加进去之后再进行监听实现如下在移动的时候进行监听在监听的时候获取到feature对象也就是单个点对象之后遍历地图层级上所有的点进行相等匹配如果满足条件则修改其大小、文字反之还原成原始样式。
this.map.addLayer(layer);this.map.on(pointermove, event {const featureTarget this.map.forEachFeatureAtPixel(event.pixel, feature {return feature;});source.getFeatures().forEach(feature {const originalStyle feature.getStyle();if (feature featureTarget) {originalStyle.getImage().setScale(2);originalStyle.getText().setScale([1, 1]);featureTarget.setStyle(originalStyle);} else {console.log(鼠标移出);originalStyle.getImage().setScale(1);originalStyle.getText().setScale([0, 0]);feature.setStyle(originalStyle);}});
});2、绘制线
2.1、绘制单个默认线
绘制线和绘制点是一样一样的就是将点对象换成线对象即可。这里的LineString就是线对象。实例化线对象和点对象也是一样入参分别是一个坐标和一个布局。之后就是创建一个Source把线的Feature添加进去再创建一个Layer添加到Source里面最后将Layer线图层添加给到Map即可。这个的LineString对象的坐标可以添加多个表示多个点连成的线。
let featureLine new Feature({geometry: new LineString([[120,20],[130,22],[135,26]])
});
let source new VectorSource();
source.addFeature(featureLine);
let layer new VectorLayer({ opacity: 1 });
layer.setSource(source);
this.map.addLayer(layer);2.2、添加样式线
和前面给点添加样式一样这里只需要给线加上Style也就是给线加上了样式这里还可以直接把style加给Layer图层那么这个图层下所有的线都会应用这个样式。
const vectorLayer new VectorLayer({source: new VectorSource(),style: new Style({stroke: new Stroke({color: red,width: 2})})
});这里的stroke对象可以参考官网OpenLayers v8.2.0 API - 类Stroke
2.3、给线添加文字
同2.2一样把text属性添加到Style当中去但是这里设置的样式是layer的所以字是在图层上的如果你需要吧字添加到线上面去就需要在得到线的Feature对象featureLine给他重新设置样式
text: new Text({// 这里就省略了和给点加的text属性一致
});lineFeature.setStyle(new Style({stroke: new Stroke({...省略}),text: new Text({fill: new Fill({...省略})})
);2.4、选中线
在进行选中线的操作和上面选中点是一样的可以直接沿用前面的方法进行操作。但是这里还可以通过Select对象用来判断线是否被选中的事件
import { Select } from ol/interaction
import { pointerMove } from ol/events/condition;const interaction new Select({condition: pointerMove, // 设置条件为鼠标移动layers: [vectorLayer], // 设置监听的图层style: function() {const style lineFeature.getStyle();// 修改线的样式const stroke style.getStroke();stroke.setWidth(5);// 修改文字样式const text style.getText();text.setScale([1, 1]);// 返回新的样式return new Style({stroke,text});}
});// 将交互对象添加到地图上
this.map.addInteraction(interaction);这里的Select对象用于选择矢量特征的交互。默认情况下所选功能包括 样式不同因此这种交互可用于视觉突出显示 以及为其他操作选择功能。同样的在这里对于上面鼠标移入点事件也可以通过该方法进行实现这里就不做说明了。
属性说明condition设置监听事件默认是singleClick单击事件还可以设置以下事件pointerMove鼠标移动时触发事件。 singleClick鼠标单击时触发事件。 dblclick鼠标双击时触发事件。 pointerDown鼠标按下时触发事件。 pointerUp鼠标释放时触发事件。 pointerEnter鼠标进入图层时触发事件。 pointerLeave鼠标离开图层时触发事件。 pointerDrag鼠标拖动时触发事件。layers从中选择要素的图层列表style所选要素的样式未设置则使用默认样式
这里的Select对象可以参考官网OpenLayers v8.2.0 API - 类Select