技术栈:
因为是旧项目的优化功能,这里主要介绍实现思路。技术栈:openlayer 6.5^、jquery、layui组件。
背景:
在创建一个地图对象后,如何创建此处省略。这里主要讲解如何根据接口的数据来把水深测量时间的图层根据不同的条件(测量时间差)渲染成不同颜色。包括:一年以内【绿色】、1~2年【黄色】、2~3年【橘色】、3年以上【红色】
实现效果:
主要实现思路:
1.测量时间图层的初始化绘制就需要根据不同时间差,绘制不同的featrue。然后,layer.getSource().addFeature(feature)添加到此图层。
2.图层控件的颜色,要跟图层绘制的颜色保持一致。
3.图层控件能够控制相应图层的开关。
一、初始化测量时间的图层
(1).根据接口绘制图层
核心思路:
写在前面,因为这是优化功能,之前的接口设计没有设计成根据不同的时间差返回对应的数据,接口不接受参数,接口返回的结果也没有按照时间差进行分组。而是一股脑的返回所有查询到的结果数组resData。
前端需要做的工作,
1.根据接口返回的数据,计算时间差,根据不同时间差给结果数组resData的每一个对象新增字段color、minVal、maxVal、isBoolean = true(默认渲染);
2.根据4种颜色分组,并分别添加上同组的索引值,之后会用到这个索引值,(会根据这个索引值查找到同组的所有对象,将其isBoolean更改为false,意为这组颜色的要素不渲染)
3.使用一个全局变量来存储这个originalData未筛选的数据,之后图层控件控制图层开关的时候会用带这个originalData,(会根据这个值,保证图层控件的开关更改的都是未筛选的初始化数据originalData)
封装方法:
/**
* 1.创建图层,根据不同时间差
* 测量时间面
*/
InitMeasuringTimePlane: function () {
$.post('enavapi/data/basedata/getWaterDepthMeasurementLayer',{}, function (data) {
if (data.code == 200 && data.data.length > 0) {
var data = data.data
var rootLayer = MAPutils.getLayerByTitle("测量时间");
//计算时间差
// 格式化当前日期
let formattedDate = moment().format('YYYY-MM-DD HH:mm:ss');
rootLayer.getSource().clear();
$.each(data, function (i, v) {
var color = MAPutils.getFormatColor(v.surend,formattedDate).color;
var minVal = MAPutils.getFormatColor(v.surend,formattedDate).minVal;
var maxVal = MAPutils.getFormatColor(v.surend,formattedDate).maxVal;
v.color = color
v.minVal = minVal
v.maxVal = maxVal
v.isBoolean = true
MAPutils.drawVectorFeature(rootLayer, {
geom: v.geom,
id: v.guid,
kv: {
// markType: "shoalWaterLayer",
data: v,
layerType: 'MeasuringTimePlaneLayer'
},
style: new ol.style.Style({
fill: new ol.style.Fill({
color: [200, 200, 200,0.4]
}),
stroke: new ol.style.Stroke({
color: color,
width:3
}),
}),
});
});
let groupedData = _.groupBy(data, 'color')
let index = 0;
// 遍历每个分组并添加索引值
for (let groupKey in groupedData) {
let group = groupedData[groupKey];
for (let i = 0; i < group.length; i++) {
group[i].index = index;
}
index++;
}
let originalData = _.flatMap(groupedData, group => group);
MAPutils.measureTimeAllData = originalData//未筛选的图层数据;用一个全局变量存储
}
});
},
其它,
使用到封装好的图层绘制方法,如下:
/**
* 绘制图层
* @param _title 图层title
* @param object 必须包含geom字段
* 达到效果:给对应的layer图层添加上featrue要素,已达到绘制图层的效果
*/
drawVectorFeature: function (layer, object) {
var geom = new ol.format.WKT().readGeometry(object.geom, {
dataProjection: 'EPSG:4326', // 设定数据使用的坐标系
featureProjection: 'EPSG:3857' // 设定当前地图使用的feature的坐标系
});
var feature = new ol.Feature({
geometry: geom
});
object.id && feature.setId(object.id);
object.style && feature.setStyle(object.style);
// kv值,调用set方法
var obj = object.kv;
if (obj) {
Object.getOwnPropertyNames(obj).forEach(function (key) {
feature.set(key, obj[key]);
});
}
layer.getSource().addFeature(feature);
return feature;
},
二、图层控件的静态布局
(1).根据已封装好的图层控制文件LayerControl.js文件,绘制图层控制组件。(定制化)
layerControl.js如下:
图层控件的渲染:
jqury创建标签元素并设置选中样式,默认:初始化图层都渲染,初始化图层控件都选中,通过点击图层控件控制对应图层的关闭或者打开。
三、图层控件控制图层的开关
核心思路:
在上面我们有说到一个变量isBoolean值,这里有用到。我们说的图层控件控制图层的开关,简单一点可以通过发起带参数的网络请求,根据接口的返回结果进行图层的重新绘制(但是因为这次是项目优化,接口没有变,所以前端需要多做功夫,这就用到了第2种解决方式)。
第2种解决方式:根据初始化创建图层的时候,我们对接口返回的数据进行添加字段的处理,我们添加的字段包括:color、minVal、maxVal、isBoolean = true(默认渲染)。并且把处理后的数据用一个originalData全局变量保存了起来,这里有用到。
封装方法:
// 测量时间的点击事件
_getSelectMeasureTime: function () {
$('body').on('click', '.mt-sub-level2-group .' + MultiMarkShip.SUB_LEVEL2_SWITCHER, function () {
// 切换样式
var $this = $(this)
checked = !$this.hasClass(MultiMarkShip.SUB_SELECTED_CLASS)
_index = $this.attr('index')
confDetails = CONFIG.initLayer.find(function (itme) { return itme.title === '测量时间' })
$this.toggleClass(MultiMarkShip.SUB_SELECTED_CLASS)
let filteredObjects = _.filter(confDetails.children, obj => obj.index == _index);
_.forEach(filteredObjects, obj => {
obj.notCreate = !checked;
});
if (checked) {
$this.css({
color: $this.attr('fontcolor'),
background: $this.attr('bgcolor'),
})
} else {
$this.css({
color: '#999',
background: '#ddd',
})
}
var oldDataList = MAPutils.measureTimeAllData
//筛选有效Features
var newDataList = oldDataList.map(function (item,index) {
if(item.index == _index){
item.isBoolean = !item.isBoolean
}
return item
})
var rootLayer = MAPutils.getLayerByTitle("测量时间");
//重新绘制
MAPutils.getLayerByTitle("测量时间").getSource().clear();
$.each(newDataList, function (index, item) {
if(item.isBoolean == true) {
var v = item
MAPutils.drawVectorFeature(rootLayer, {
geom: v.geom,
id: v.guid,
kv: {
// markType: "shoalWaterLayer",
data: v,
layerType: 'MeasuringTimePlaneLayer'
},
style: new ol.style.Style({
fill: new ol.style.Fill({
color: [200, 200, 200,0.4]
}),
stroke: new ol.style.Stroke({
color: v.color,
width:3
}),
}),
});
}
});
})
},
这是一个跳转链接,会跳转到小破站,我写的,放心。。。
小破站的屏幕录制,感兴趣的可以看一眼最终实现效果