Openlayers 教程 - feature(图形要素)两种悬浮事件以及使用范围
- 核心代码
- 完整代码:
- 在线示例
之前介绍了 Openlayers
的点击事件,这次介绍一下悬浮事件。
悬浮事件和点击事件还是有区别的:一般点击事件是一次事件,而悬浮事件往往是两次事件。
比如,点击改变颜色,想要改回来,再执行一遍即可;
而悬浮事件改变颜色,往往需要鼠标移入改变颜色,移出还原颜色。
本文介绍了图形要素(Feature)的三种悬浮事件实现方式:
- 开启地图事件,通过传递给图形要素(
Feature
)的方式实现。 - 开启地图事件,判断当前图形要素(
Feature
)的方式实现。 - 通过图形要素(
Feature
)选中交互实现。
三种方式可根据实际需求来选择使用,详情见代码注释。
本文包括核心代码、完整代码以及在线示例。
核心代码
三种注册悬浮事件方式:
// 注册地图悬浮事件
function registerMapEvent() {
map.on('pointermove', function (event) {
map.forEachFeatureAtPixel(event.pixel, function (feature) {
// 为移动到的 feature 发送自定义的 mousemove 消息
try {
feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
} catch (e) {
console.error(e);
}
feature.dispatchEvent && feature.dispatchEvent({type: 'mousemove', event});
});
});
}
// 单击事件对象
const func1 = function (e) {
console.log('触发悬浮事件: ', e.target)
feature1.setStyle(hoverStyle1)
}
// 记录对象,用于清除事件
feature1.set('eventFunction', func1);
feature1.on('mousemove', func1)
//分割线 =================================================================
// 开启地图悬浮事件
// 可以记录移入和移出事件
function featureMapHover() {
const feature = features[1]
// 用来记录选中的图形要素
let selected = null;
// 用来关闭悬浮离开状态
let unselect = false;
function mapHoverFunc(e) {
if (selected !== null) {
selected = null;
}
map.forEachFeatureAtPixel(e.pixel, function (f) {
// 这里可以判断某个或者某些图形要素组
if (f === feature) {
selected = f;
return true;
} else {
return false;
}
});
// 鼠标移入
if (selected) {
console.log('悬浮中', e);
unselect = false;
feature.setStyle(hoverStyle2)
//鼠标移出
} else {
if (!unselect) {
console.log('已移开');
unselect = true;
feature.setStyle(undefined)
}
}
}
map.set('eventFunction', mapHoverFunc);
map.on('pointermove', mapHoverFunc);
}
//分割线 =================================================================
// 选中交互来实现悬浮事件
function featureSelectHover() {
// 创建一个选择交互实例
const selectInteraction = new ol.interaction.Select({
// 设置触发选择的事件条件为点击事件
condition: ol.events.condition.pointerMove,
// 设置图层
layers: [layerSelect],
});
map.set('selectInteraction',selectInteraction);
selectInteraction.on('select',function (e){
console.log('e.selected',e.selected)
if(e.selected.length>0){
console.log('选中:',e.selected)
}else{
console.log('取消选中!')
}
});
// 将选择交互添加到地图实例中
map.addInteraction(selectInteraction);
}
完整代码:
<html lang="en">
<head>
<meta charSet="utf-8">
<!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
<link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
<style>
/* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
.map {
height: 400px;
width: 100%;
float: left;
}
</style>
<!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
<script src="http://openlayers.vip/examples/resources/ol.js"></script>
<script src="./turf.min.js"></script>
<script src="./tiandituLayers.js"></script>
<title>OpenLayers example</title>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<h2>OpenLayers feature hover</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div>
<br/>
<br/>
<script type="text/javascript">
var map = new ol.Map({
// 地图容器
target: 'map',
// 地图图层,比如底图、矢量图等
layers: [
getIMG_CLayer(),
getIBO_CLayer(),
getCIA_CLayer(),
],
// 地图视野
view: new ol.View({
projection: "EPSG:4326",
// 定位
center: [115.67724700667199, 37.73879478106912],
// 缩放
zoom: 6,
maxZoom: 18,
minZoom: 1,
})
});
// 注册地图悬浮事件
function registerMapEvent() {
map.on('pointermove', function (event) {
map.forEachFeatureAtPixel(event.pixel, function (feature) {
// 为移动到的 feature 发送自定义的 mousemove 消息
try {
feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
} catch (e) {
console.error(e);
}
feature.dispatchEvent && feature.dispatchEvent({type: 'mousemove', event});
});
});
}
registerMapEvent();
// 默认样式
var defaultStyle = new ol.style.Style({
//边框样式
stroke: new ol.style.Stroke({
color: 'red',
width: 2,
}),
//填充样式
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.3)',
}),
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'white',
})
})
})
var hoverStyle1 = new ol.style.Style({
//边框样式
stroke: new ol.style.Stroke({
color: '#00ff00',
width: 2,
}),
//填充样式
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.3)',
}),
})
var hoverStyle2 = new ol.style.Style({
//边框样式
stroke: new ol.style.Stroke({
color: '#00ffff',
width: 2,
}),
//填充样式
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.3)',
}),
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'white',
})
})
})
// 初始化图层
var layer = initVectorLayer();
// 选中图形要素图层
var layerSelect = initVectorLayer();
// 点线面数组
var features = [];
// 传递的方式开启悬浮的图形要素
let polygon1 = "POLYGON((112.80630306271966 46.27140545436643,116.23403743771966 44.33781170436643,117.81606868771966 40.29484295436643,117.90395931271966 38.36124920436643,117.81606868771966 35.02140545436643,116.14614681271966 32.38468670436643,113.50942806271966 33.26359295436643,111.75161556271966 34.58195232936643,110.60903743771966 35.46085857936643,113.28970150021968 36.03214764186642,111.35610775021968 36.33976482936642,110.91665462521968 36.91105389186642,111.22427181271968 37.52628826686642,112.10317806271968 37.30656170436642,112.41079525021968 37.78996014186642,112.32290462521968 38.36124920436642,111.44399837521968 38.66886639186642,110.52114681271968 39.10831951686642,110.38931087521968 39.81144451686642,111.09243587521968 40.07511639186642,112.19106868771968 40.38273357936642,112.49868587521968 41.04191326686642,111.88345150021968 41.21769451686642,111.26821712521968 40.86613201686642,110.43325618771968 40.91007732936642,110.65298275021968 41.39347576686642,110.47720150021968 42.66788982936642,111.79556087521968 42.75578045436642,110.38931087521968 43.19523357936642,110.56509212521968 44.24992107936642,111.44399837521968 43.76652264186642,111.79556087521968 44.16203045436642,111.09243587521968 44.60148357936642,111.22427181271968 45.30460857936642,112.10317806271968 44.95304607936642,112.67446712521968 45.26066326686642,111.75161556271968 45.78800701686642,111.88345150021968 46.40324139186642,112.14712337521968 47.94132732936642,112.45474056271968 47.15031170436642,113.99282650021968 47.28214764186642,113.28970150021968 46.79874920436642,114.95962337521968 46.71085857936642,112.80630306271966 46.27140545436643))";
// 移入和移出事件的图形要素
let polygon2 = "POLYGON((123.94676492355833 44.03121337817592,118.40965554855833 38.23043212817592,121.66160867355833 32.82515869067592,129.30809304855833 33.39644775317592,129.92332742355833 39.46090087817592,123.94676492355833 44.03121337817592))";
// 选中方式的悬浮的图形要素
let polygon3 = "POLYGON((107.96587424038064 27.434398296739595,125.98345236538064 30.554515484239595,126.68657736538064 24.446117046739595,110.16313986538064 17.942210796739595,107.96587424038064 27.434398296739595))";
// 添加点线面
function addFeatures() {
// 这里处理一下,可以自由传图形要素 start===================================================
layer.getSource().clear();
layerSelect.getSource().clear();
features = [];
const feature1 = getFeatureByWKT(polygon1);
const feature2 = getFeatureByWKT(polygon2);
const feature3 = getFeatureByWKT(polygon3);
// 单击事件对象
const func1 = function (e) {
console.log('触发悬浮事件: ', e.target)
feature1.setStyle(hoverStyle1)
}
// 记录对象,用于清除事件
feature1.set('eventFunction', func1);
feature1.on('mousemove', func1)
features.push(...[feature1, feature2]);
layer.getSource().addFeatures([feature1, feature2]);
layerSelect.getSource().addFeatures([feature3]);
map.getView().fit([93.64037006658276, 10.72265625,128.53294819158273, 51.181893294147805], {
duration: 1,//动画的持续时间,
callback: null,
});
}
addFeatures();
/**
* @todo 矢量图层
* @returns {VectorLayer}
* @constructor
*/
function initVectorLayer() {
//实例化一个矢量图层Vector作为绘制层
let source = new ol.source.Vector();
//创建一个图层
let customVectorLayer = new ol.layer.Vector({
source: source,
zIndex: 2,
//设置样式
style: defaultStyle,
});
//将绘制层添加到地图容器中
map.addLayer(customVectorLayer);
return customVectorLayer;
}
/**
* @todo wkt格式数据转化成图形对象
* @param {string} wkt "POINT(112.7197265625,39.18164062499999)" 格式数据
* @param {string|Projection} sourceCode 源投影坐标系
* @param {string|Projection} targetCode 目标投影坐标系
* @returns {Feature}
*/
function getFeatureByWKT(wkt, sourceCode, targetCode) {
try {
let view = map.getView();
if (!wkt) {
return null;
}
let format = new ol.format.WKT();
let feature;
feature = format.readFeature(wkt, {
featureProjection: targetCode || view.getProjection(),
dataProjection: sourceCode || view.getProjection(),
});
return feature;
} catch (e) {
console.log(e);
return null;
}
}
// 开启地图悬浮事件
// 可以记录移入和移出事件
function featureMapHover() {
const feature = features[1]
// 用来记录选中的图形要素
let selected = null;
// 用来关闭悬浮离开状态
let unselect = false;
function mapHoverFunc(e) {
if (selected !== null) {
selected = null;
}
map.forEachFeatureAtPixel(e.pixel, function (f) {
// 这里可以判断某个或者某些图形要素组
if (f === feature) {
selected = f;
return true;
} else {
return false;
}
});
// 鼠标移入
if (selected) {
console.log('悬浮中', e);
unselect = false;
feature.setStyle(hoverStyle2)
//鼠标移出
} else {
if (!unselect) {
console.log('已移开');
unselect = true;
feature.setStyle(undefined)
}
}
}
map.set('eventFunction', mapHoverFunc);
map.on('pointermove', mapHoverFunc);
}
// 选中交互来实现悬浮事件
function featureSelectHover() {
// 创建一个选择交互实例
const selectInteraction = new ol.interaction.Select({
// 设置触发选择的事件条件为点击事件
condition: ol.events.condition.pointerMove,
// 设置图层
layers: [layerSelect],
});
map.set('selectInteraction',selectInteraction);
selectInteraction.on('select',function (e){
console.log('e.selected',e.selected)
if(e.selected.length>0){
console.log('选中:',e.selected)
}else{
console.log('取消选中!')
}
});
// 将选择交互添加到地图实例中
map.addInteraction(selectInteraction);
}
featureMapHover();
featureSelectHover();
// 清空事件
function clearFunc() {
const feature = features[0];
const func = feature.get('eventFunction');
feature.un('mousemove', func);
feature.setStyle(undefined)
const funcMap = map.get('eventFunction');
map.un('pointermove', funcMap);
const selectInteraction = map.get('selectInteraction');
map.removeInteraction(selectInteraction);
}
</script>
<h4>左一为传递方式实现悬浮事件,契合面相对象思想,但是不能记录移出事件!</h4>
<h4>左二为地图方式实现悬浮事件,整个地图开启悬浮事件,可以记录移入移出事件!</h4>
<h4>下侧为选中交互实现悬浮事件,契合面向对象思想,可以绑定图层,不能记录移出事件!</h4>
<button id="clearFunc" onClick="clearFunc()">关闭所有事件</button>
</body>
</html>
在线示例
在线示例:Openlayers 教程 - feature(图形要素)三种悬浮事件(移入移出)以及适用范围