使用OpenLayers根据经纬度对地图进行多个标点,以及点击标点弹框的实现(从后台数据库获取经纬度数据)
程序员文章站
2022-05-31 13:28:38
...
说明:根据前面的知识,我们已经简单实现了离线地图以及根据经纬度单点标注地图且弹框的功能。具体实现操作请参照我的另外两篇博文:使用OpenLayers发布离线地图和使用OpenLayers根据经纬度对地图进行单个标点,以及点击标点弹框的实现(没有从后台获取经纬度数据)
1.拿到实际项目应用来说,根据经纬度来进行地图标点,一般情况下都是从后台数据库来拿到数据,前端离线地图再来进行显示标注并弹框,那我们要怎么实现呢?
2.首先,我们得先编写好对应的接口方法,控制层相关接口代码如下所示:
/**
* 获取经纬度信息
*/
@RequestMapping(value = "/getCameraList")
@ResponseBody
public List<CameraInfoVo> getCameraList() {
List<CameraInfoVo> CameraInfo = cameraService.getCameraList();
return CameraInfo;
}
3.该接口返回值是一个带有经纬度信息的List集合,测试该接口,返回json数据如下图所示:
4.既然接口实现没有出现问题,那么我们就可以去前端页面根据Ajax来对该接口进行一个调用:
5.不需要进行后台调用时,可以直接把数据写死在页面中,如下图所示:
6.实际项目中实现效果如下图所示:
7.最后附上前端主要JavaScript代码:
//利用ajax对后台接口进行调用
var back_data = [];
$.ajax({
//请求方式
type : "POST",
//请求的媒体类型
contentType: "application/json;charset=UTF-8",
//请求设置异步
async: false,
//请求地址
url : Feng.ctxPath + "/camera/getCameraList",
//请求成功
success : function(result) {
back_data=result;
console.log(result);
},
//请求失败,包含具体的错误信息
error : function(e){
console.log(e.status);
console.log(e.responseText);
}
});
//console.log(list);
console.log(back_data);
//固定json格式数据:
/*var back_data=[
{
"address":"五指山测试工地",
"cameraId":"T204",
"lat":"18.77520",
"lon":"109.5170"
},
{
"address":"椰树第三工业城测试工地",
"cameraId":"T206",
"lat":"19.9332",
"lon":"110.1424"
},
{
"address":"海南热带野生动物园测试工地",
"cameraId":"T214",
"lat":"19.7688",
"lon":"110.2477"
},
{
"address":"白石岭测试工地",
"cameraId":"T213",
"lat":"19.1607",
"lon":"110.3775"
},
{
"address":"海南大学测试工地",
"cameraId":"T212",
"lat":"20.06089",
"lon":"110.32645"
}
]*/
/**
* 数据转换
*/
var new_cicy_data = [];
for (let i = 0; i < back_data.length; i++) {
new_cicy_data[i] = back_data[i];
back_data[i].ol = [];
back_data[i].ol[0] = parseFloat(back_data[i].lon);
back_data[i].ol[1] = parseFloat(back_data[i].lat);
back_data[i].key = i;
}
console.log(new_cicy_data);
/**
* 实例化Map对象加载地图,默认底图加载天地图
*/
//地图设置中心,设置为海南五指山
var center=ol.proj.transform([109.5170,18.77520],'EPSG:4326','EPSG:3857');
//创建地图
//创建地图
var map=new ol.Map({
view:new ol.View({
center:center,
minZoom:8,//设置缩放的最大和最小级别
maxZoom:13,
zoom:8//设置默认加载的级别
}),
target:'mapCon'//要显示地图的DIV的ID
});
//添加一个使用离线瓦片地图的层
var offLineMap=new ol.layer.Tile({
source:new ol.source.XYZ({
url:'${ctxPath}/static/tile/{z}/{x}/{y}.png'//本例中地图瓦片保存在当前目录下的tile文件夹目录下
})
});
map.addLayer(offLineMap);
/**
* 创建标注样式函数,设置image为图标ol.style.Icon
*/
var createLabelStyle = function (feature) {
return new ol.style.Style({
image: new ol.style.Icon(
{
//设置图标点
anchor: [0.5, 60],
//图标起点
anchorOrigin: 'top-right',
//指定x值为图标点的x值
anchorXUnits: 'fraction',
//指定Y值为像素的值
anchorYUnits: 'pixels',
//偏移
offsetOrigin: 'top-right',
// offset:[0,10],
//图标缩放比例
// scale:0.5,
//透明度
opacity: 0.75,
//图标的url
src: '${ctxPath}/static/img/blueIcon.png'
}),
text: new ol.style.Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'middle',
//文字样式
font: 'normal 14px 微软雅黑',
//文本内容
text: feature.get('name'),
//文本填充样式(即文字颜色)
fill: new ol.style.Fill({ color: '#aa3300' }),
stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 })
})
});
}
/**
* 遍历绚烂设备标点
*/
for (let i = 0; i < new_cicy_data.length; i++) {
show_dian(new_cicy_data[i]);
}
//标点渲染
function show_dian(info) {
//实例化Vector要素,通过矢量图层添加到地图容器中
let iconFeature = new ol.Feature({
//坐标点
geometry: new ol.geom.Point(ol.proj.fromLonLat(info.ol)),
//名称属性
name: info.cameraId,
//address: info.address,
//自定义数据,作用:唯一标识符
//自定义数据,作用:唯一标识符
key: info.key,
});
iconFeature.setStyle(createLabelStyle(iconFeature));
//矢量标注的数据源
let vectorSource = new ol.source.Vector({
features: [iconFeature]
});
//矢量标注图层
let vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addLayer(vectorLayer);
//实例化Vector要素,通过矢量图层添加到地图容器中 end
}
/**
* 实现popup的html元素
*/
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
/**
* 在地图容器中创建一个Overlay
*/
var popup = new ol.Overlay({
//要转换成overlay的HTML元素
element: container,
//当前窗口可见
autoPan: true,
//Popup放置的位置
positioning: 'bottom-center',
//是否应该停止事件传播到地图窗口
stopEvent: false,
autoPanAnimation: {
//当Popup超出地图边界时,为了Popup全部可见,地图移动的速度
duration: 250
}
});
map.addOverlay(popup);
/**
* 添加关闭按钮的单击事件(隐藏弹窗)
*
*/
closer.onclick = function () {
//未定义popup位置
popup.setPosition(undefined);
//失去焦点
closer.blur();
return false;
};
/**
* 动态创建弹窗的具体内容
*/
function addFeatrueInfo(info) {
//新增a元素
var elementA = document.createElement('a');
elementA.className = "markerInfo";
/*elementA.href = info.titleURL;*/
//elementA.innerText = info.att.title;
setInnerText(elementA, info.cameraId);
// 新建的div元素添加a子节点
content.appendChild(elementA);
//新增div元素
var elementDiv = document.createElement('div');
elementDiv.className = "markerText";
// elementDiv.innerText = info.text;
setInnerText(elementDiv, info.address);
// 为content添加div子节点
content.appendChild(elementDiv);
//新增img元素
/*var elementImg = document.createElement('img');
elementImg.className = "markerImg";
elementImg.src = info.imgURL;
// 为content添加img子节点
content.appendChild(elementImg);*/
//无图片时调节样式
var elementImg = document.createElement('div');
elementImg.className = "markerImg";
elementImg.style = 'width:200px';
// 为content添加img子节点
content.appendChild(elementImg);
}
/**
* 动态设置元素文本内容(兼容)
*/
function setInnerText(element, text) {
if (typeof element.textContent == "string") {
element.textContent = text;
} else {
element.innerText = text;
}
}
/**
* 为map添加点击事件监听,渲染弹出popup
*/
map.on('click', function (evt) {
//判断当前单击处是否有要素,捕获到要素时弹出popup
var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) { return feature; });
if (feature) {
//清空popup的内容容器
content.innerHTML = '';
//在popup中加载当前要素的具体信息
addFeatrueInfo(new_cicy_data[feature.H.key]);
//设置popup的位置
popup.setPosition(ol.proj.fromLonLat(new_cicy_data[feature.H.key].ol));
}
});
/**
* 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态
*/
map.on('pointermove', function (e) {
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});
</script>
上一篇: Layer弹层组件的使用