OpenLayer之聚合标注和信息框弹出
目录
OpenLayer之聚合标注和信息框弹出
效果图
聚合图层的组成
1、Vector的source,这里面主要放feature,这个source不是直接加载到Vector图层中的source
for (var i = 0; i < dataSource.length; i++) {
var coordinate = ol.proj.transform([dataSource[i].x, dataSource[i].y], 'EPSG:4326', 'EPSG:3857');
var attr = {
attribute: dataSource[i].attribute
};
features[i] = new ol.Feature({
geometry: new ol.geom.Point(coordinate),
attribute: attr
});
}
console.log(features);
var source = new ol.source.Vector({
features: features,
});
2、声明ol.source.Cluster
var clusterSource = new ol.source.Cluster({
distance: 40,
source: source
});
注意这里source是上面ol.source.Vector
初始化聚合图层
//加载聚合标注的矢量图层
var styleCache = {};
var layerVetor = new ol.layer.Vector({
source: clusterSource,//注意一定不要搞错了
style: function (feature, resolution) {
var size = feature.get('features').length;
var style = styleCache[size];
if (!style) {
style = [new ol.style.Style({
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */({
anchor: [0.5, 60],
anchorOrigin: 'top-right',
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
offsetOrigin: 'top-right',
offset: [0, 1],//偏移量设置
scale: 0.2, //图标缩放比例
opacity: 0.75, //透明度
src: 'Script/Marker.png'//图标的url
})),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: 'blue'
})
})
})];
styleCache[size] = style;
}
return style;
}
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.transform([104.06, 30.67], 'EPSG:4326', 'EPSG:3857'),
zoom: 10
}),
target: 'map',
controls: ol.control.defaults().extend([
new ol.control.FullScreen(),
new ol.control.OverviewMap(),
new ol.control.Zoom(),
new ol.control.MousePosition()
]),
});
map.addLayer(layerVetor);
弹出框的设置
/**
* 实现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(/** @type {olx.OverlayOptions} */({
element: container,
autoPan: true,
positioning: 'bottom-center',
stopEvent: false,
autoPanAnimation: {
duration: 250
}
}));
map.addOverlay(popup);
/**
* 添加关闭按钮的单击事件(隐藏popup)
* @return {boolean} Don't follow the href.
*/
closer.onclick = function () {
popup.setPosition(undefined); //未定义popup位置
closer.blur(); //失去焦点
return false;
};
/**
* 动态创建popup的具体内容
* @param {string} title
*/
function addFeatrueInfo(info) {
//新增a元素
var elementA = document.createElement('a');
content.appendChild(elementA); // 新建的div元素添加a子节点
var elementDiv1 = document.createElement('div');
elementDiv1.className = "markerText";
//elementDiv.innerText = info.att.text;
setInnerText(elementDiv1, "所属省份:"+info.proname);
content.appendChild(elementDiv1); // 为content添加div子节点
//新增div元素
var elementDiv = document.createElement('div');
elementDiv.className = "markerText";
//elementDiv.innerText = info.att.text;
setInnerText(elementDiv,"地名:"+ info.name);
content.appendChild(elementDiv); // 为content添加div子节点
}
/**
* 动态设置元素文本内容(兼容)
*/
function setInnerText(element, text) {
if (typeof element.textContent == "string") {
element.textContent = text;
} else {
element.innerText = text;
}
}
layerVetor.on('click', function (evt) {
var geometry = evt.Feature;
console.log(geometry);
});
/**
* 为map添加点击事件监听,渲染弹出popup
*/
map.on('click', function (evt) {
var coordinate = evt.coordinate;
//判断当前单击处是否有要素,捕获到要素时弹出popup
var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layerVetor) { return feature; });
var featuerInfo = feature.getProperties().features[0].N.attribute.attribute;
if (feature) {
content.innerHTML = ''; //清空popup的内容容器
addFeatrueInfo(featuerInfo); //在popup中加载当前要素的具体信息
if (popup.getPosition() == undefined) {
popup.setPosition(coordinate); //设置popup的位置
}
}
});
/**
* 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态
*/
map.on('pointermove', function (e) {
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
})
全部源码
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>聚合和弹出</title>
<link href="Script/ol.css" rel="stylesheet" />
<style type="text/css">
.ol-popup
{
position: absolute;
background-color: white;
-webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
bottom: 12px;
left: -50px;
}
.ol-popup:after, .ol-popup:before
{
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after
{
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before
{
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-closer
{
text-decoration: none;
position: absolute;
top: 2px;
right: 8px;
}
.ol-popup-closer:after
{
content: "✖";
height:30px;
padding:12px;
}
#popup-content
{
font-size: 14px;
font-family: "微软雅黑";
width:100px;
}
#popup-content .markerInfo
{
font-weight: bold;
}
</style>
<script src="Script/ol.js"></script>
<script src="Script/data.js"></script>
</head>
<body>
<div id="map">
<!-- Popup -->
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content">
</div>
</div>
</div>
<script>
var dataSource = county.items;
var features = new Array(dataSource.length);
for (var i = 0; i < dataSource.length; i++) {
var coordinate = ol.proj.transform([dataSource[i].x, dataSource[i].y], 'EPSG:4326', 'EPSG:3857');
var attr = {
attribute: dataSource[i].attribute
};
features[i] = new ol.Feature({
geometry: new ol.geom.Point(coordinate),
attribute: attr
});
}
console.log(features);
var source = new ol.source.Vector({
features: features,
});
var clusterSource = new ol.source.Cluster({
distance: 40,
source: source
});
//加载聚合标注的矢量图层
var styleCache = {};
var layerVetor = new ol.layer.Vector({
source: clusterSource,
style: function (feature, resolution) {
var size = feature.get('features').length;
var style = styleCache[size];
if (!style) {
style = [new ol.style.Style({
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */({
anchor: [0.5, 60],
anchorOrigin: 'top-right',
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
offsetOrigin: 'top-right',
offset: [0, 1],//偏移量设置
scale: 0.2, //图标缩放比例
opacity: 0.75, //透明度
src: 'Script/Marker.png'//图标的url
})),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: 'blue'
})
})
})];
styleCache[size] = style;
}
return style;
}
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.transform([104.06, 30.67], 'EPSG:4326', 'EPSG:3857'),
zoom: 10
}),
target: 'map',
controls: ol.control.defaults().extend([
new ol.control.FullScreen(),
new ol.control.OverviewMap(),
new ol.control.Zoom(),
new ol.control.MousePosition()
]),
});
map.addLayer(layerVetor);
/**
* 实现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(/** @type {olx.OverlayOptions} */({
element: container,
autoPan: true,
positioning: 'bottom-center',
stopEvent: false,
autoPanAnimation: {
duration: 250
}
}));
map.addOverlay(popup);
/**
* 添加关闭按钮的单击事件(隐藏popup)
* @return {boolean} Don't follow the href.
*/
closer.onclick = function () {
popup.setPosition(undefined); //未定义popup位置
closer.blur(); //失去焦点
return false;
};
/**
* 动态创建popup的具体内容
* @param {string} title
*/
function addFeatrueInfo(info) {
//新增a元素
var elementA = document.createElement('a');
content.appendChild(elementA); // 新建的div元素添加a子节点
var elementDiv1 = document.createElement('div');
elementDiv1.className = "markerText";
//elementDiv.innerText = info.att.text;
setInnerText(elementDiv1, "所属省份:"+info.proname);
content.appendChild(elementDiv1); // 为content添加div子节点
//新增div元素
var elementDiv = document.createElement('div');
elementDiv.className = "markerText";
//elementDiv.innerText = info.att.text;
setInnerText(elementDiv,"地名:"+ info.name);
content.appendChild(elementDiv); // 为content添加div子节点
}
/**
* 动态设置元素文本内容(兼容)
*/
function setInnerText(element, text) {
if (typeof element.textContent == "string") {
element.textContent = text;
} else {
element.innerText = text;
}
}
layerVetor.on('click', function (evt) {
var geometry = evt.Feature;
console.log(geometry);
});
/**
* 为map添加点击事件监听,渲染弹出popup
*/
map.on('click', function (evt) {
var coordinate = evt.coordinate;
//判断当前单击处是否有要素,捕获到要素时弹出popup
var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layerVetor) { return feature; });
var featuerInfo = feature.getProperties().features[0].N.attribute.attribute;
if (feature) {
content.innerHTML = ''; //清空popup的内容容器
addFeatrueInfo(featuerInfo); //在popup中加载当前要素的具体信息
if (popup.getPosition() == undefined) {
popup.setPosition(coordinate); //设置popup的位置
}
}
});
/**
* 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态
*/
map.on('pointermove', function (e) {
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
})
</script>
</body>
</html>
总结
这里我用的是一个data数据,这里的坐标主要针对天地图比较准点,OSM好像看着不太准,就当看看效果图把,这里有Bug就是这个点击查询元素不太灵敏,我想应该有个缓冲区,但是始终没有找到,还有就是那个我把Attribute与放在要素里面,点击选择的时候这个获取atrrbute真困难,这个东西没少浪费时间
转载自:https://blog.csdn.net/weixin_40184249/article/details/80874944