📌 学习目标
- 掌握创建悬停效果的实现方法
- 理解相关API的使用
- 能够独立完成类似功能开发
MapLibre GL JS 从入门到精通 - 130+实战案例
🎯 核心概念
创建悬停效果以突出显示要素。
💻 完 整 代 码
代码示例
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [-100.486052, 37.830348],
zoom: 2
});
let hoveredStateId = null;
map.on('load', () => {
map.addSource('states', {
'type': 'geojson',
'data':
'https://maplibre.org/maplibre-gl-js/docs/assets/us_states.geojson'
});
// 依赖要素状态的填充透明度表达式将在悬停状态设置为true时渲染悬停效果。
map.addLayer({
'id': 'state-fills',
'type': 'fill',
'source': 'states',
'layout': {},
'paint': {
'fill-color': '#627BC1',
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1,
0.5
]
}
});
map.addLayer({
'id': 'state-borders',
'type': 'line',
'source': 'states',
'layout': {},
'paint': {
'line-color': '#627BC1',
'line-width': 2
}
});
// 当用户将鼠标移到state-fill图层上方时,我们将更新
// 鼠标下方要素的要素状态。
map.on('mousemove', 'state-fills', (e) => {
if (e.features.length > 0) {
if (hoveredStateId) {
map.setFeatureState(
{source: 'states', id: hoveredStateId},
{hover: false}
);
}
hoveredStateId = e.features[0].id;
map.setFeatureState(
{source: 'states', id: hoveredStateId},
{hover: true}
);
}
});
// 当鼠标离开state-fill图层时,更新之前悬停要素的要素状态。
map.on('mouseleave', 'state-fills', () => {
if (hoveredStateId) {
map.setFeatureState(
{source: 'states', id: hoveredStateId},
{hover: false}
);
}
hoveredStateId = null;
});
});
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<title>Create a hover effect</title>
<meta property="og:description" content="使用事件和要素状态创建每个要素的悬停效果。" />
<meta property="og:created" content="2006-06-25" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [-100.486052, 37.830348],
zoom: 2
});
let hoveredStateId = null;
map.on('load', () => {
map.addSource('states', {
'type': 'geojson',
'data':
'https://maplibre.org/maplibre-gl-js/docs/assets/us_states.geojson'
});
// 依赖要素状态的fill-opacity表达式将在要素的
// 悬停状态设置为true时呈现悬停效果。
map.addLayer({
'id': 'state-fills',
'type': 'fill',
'source': 'states',
'layout': {},
'paint': {
'fill-color': '#627BC1',
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1,
0.5
]
}
});
map.addLayer({
'id': 'state-borders',
'type': 'line',
'source': 'states',
'layout': {},
'paint': {
'line-color': '#627BC1',
'line-width': 2
}
});
// 当用户将鼠标移动到state-fill图层上时,我们将更新
// 鼠标下要素的要素状态。
map.on('mousemove', 'state-fills', (e) => {
if (e.features.length > 0) {
if (hoveredStateId) {
map.setFeatureState(
{source: 'states', id: hoveredStateId},
{hover: false}
);
}
hoveredStateId = e.features[0].id;
map.setFeatureState(
{source: 'states', id: hoveredStateId},
{hover: true}
);
}
});
// 当鼠标离开state-fill图层时,更新之前悬停要素的要素状态。
map.on('mouseleave', 'state-fills', () => {
if (hoveredStateId) {
map.setFeatureState(
{source: 'states', id: hoveredStateId},
{hover: false}
);
}
hoveredStateId = null;
});
});
</script>
</body>
</html>
🔍 代码解析
1. 初始化地图
使用 new maplibregl.Map() 创建地图实例,配置美国区域作为初始视图。
2. 关键配置项
- map.addSource(): 添加GeoJSON数据源
- feature-state: 使用要素状态控制样式
- map.setFeatureState(): 设置要素状态
- hover状态: 通过feature-state实现悬停效果
3. 核心机制
使用要素状态(feature-state)实现悬停效果:
- 通过paint属性中的表达式根据状态设置透明度
- 鼠标进入时设置hover:true,透明度变为1
- 鼠标离开时设置hover:false,透明度变为0.5
⚙️ 参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| source | string | 是 | 数据源ID |
| id | number/string | 是 | 要素ID |
| state | object | 是 | 要设置的键值对状态 |
🎨 效果说明

运行代码后,地图显示美国各州区域。鼠标悬停在某个州上时,该州会高亮显示(透明度从0.5变为1),移开后恢复原状。通过这种方式可以清晰区分当前悬停的州。
💡 常 见 问 题
Q1: 悬停效果不生效?
A: 检查以下几点:
- 确认数据源包含id字段(要素需要唯一ID)
- 检查paint表达式中是否正确使用了feature-state
- 确认hoveredStateId变量正确更新
Q2: 为什么使用feature-state而不是直接修改样式?
A: feature-state是MapLibre优化的状态管理机制,可以高效更新单个要素样式而不触发整个图层的重绘。
Q3: 如何添加更丰富的悬停效果?
A: 可以同时修改多个paint属性:
'fill-color': [
'case',
['boolean', ['feature-state', 'hover'], false],
'#ff0000', // 高亮色
'#627BC1' // 默认色
],
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1,
0.5
]
📝 练习任务
- 基础练习:修改悬停时的颜色和高亮效果
- 进阶挑战:添加边框高亮效果
- 拓展思考:如何实现点击选中效果?
- 综合实践:创建一个可交互的州信息展示系统
🌟 最佳实践
- 状态追踪: 使用变量追踪当前悬停的要素ID
- 性能优化: 使用feature-state避免频繁重绘
- 清理状态: 鼠标离开时重置状态,避免状态残留
- 视觉效果: 透明度变化是最简单的悬停反馈
- 组合效果: 结合颜色、边框、阴影等多重效果
🔗 延伸阅读
-
[下一课预告]:将继续学习地图图层的基础知识
本文是MapLibre GL JS实践课程系列的一部分,欢迎关注收藏

546

被折叠的 条评论
为什么被折叠?



