前期准备
在开始自定义标点(marker)功能开发前,我们已经完成了以下基础工作:
- 下载leaflet包并引入到项目中;
- 创建地图容器,地图实例使用mapRef指示;
html
<div id="mapRef" ></div>
这里准备工作就简短的介绍一下,前面有相关介绍,感兴趣的宝子可以看看,就不再过多赘述了(其实是我懒得再编辑了。。。)快速上手Leaflet:轻松创建你的第一个交互地图
加载marker数据
在官方文档中可以了解到marker的加载方式,这里我们可以看到其中的经纬度[50.5,30.5]数据是至关重要的,只有这个数据才决定了标记的位置。
js
L.marker(<LatLng> latlng, <Marker options> options?);
//示例
L.marker([50.5, 30.5]).addTo(mapRef);

可以看到官方给出的基本效果,但是在实际项目中,可能会遇到其他更多的需求,这样基本的标记就显得不够看了:
- 不同类型的数据可能需要不同的标记样式
- 选择了某个标记需要使其显得更加突出明显
- 需要在地图上展示复杂的业务数据
- 需要实现交互式的标记效果
- 自定义icon图片 本章的重点就是如何进行自定义标记点样式
自定义icon图片
本章的重点就是如何进行自定义标记点样式
在官方文档中,可以注意到,在marker的经纬度数据之后,还有一个可选择的options,这里我们选择icon的参数进行设定。
js
var myIcon = L.icon({
iconUrl: 'my-icon.png',
iconSize: [38, 95],
iconAnchor: [22, 94],
popupAnchor: [-3, -76],
shadowUrl: 'my-icon-shadow.png',
shadowSize: [68, 95],
shadowAnchor: [22, 94]
});
L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
这里是官方的icon设定,其中的图片可以从阿里巴巴矢量图标库中去任意选择 推荐资源:
- 阿里巴巴矢量图标库:www.iconfont.cn/
- Flaticon:www.flaticon.com/
- Font Awesome:fontawesome.com/icons
完全自定义icon
上面讲解的是只更换图片的方式,有需要的同学可以自行进行测试。 接下来才是我要说的真正的重点, 因为涉及到需要展示的标记数据中可能包含其他需要展示的信息,又或者是图标库中没有自己想要的图片,想要自己用HTML + CSS 设计一个,那么就得使用接下来的方法了。
js
var myIcon = L.divIcon({className: 'my-div-icon'});
// 你可以在 .my-div-icon CSS 中设置样式
L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
官方文档中给出了另外一种设计方式,DivIcon代表一个轻量级的标记图标,使用一个简单的 <div> 元素而不是图片。继承自 icon ,但忽略了 iconUrl 和 shadow 选项。
自己设计其中的html参数就可以实现心中的自由!!!
js
//自定义icon的样式
let myIconHtml = '<div class="myIconCss"></div>'
//自定义icon
let myIcon = L.divIcon({
className: "",
html:myIconHtml,
iconAnchor:[6, 12],//偏移量
})
//应用到标记中
L.marker([50.505, 30.57], {icon: myIcon}).addTo(mapRef);
js
/* 在Vue/React组件中需要使用深度选择器 */
:deep(.myIconCss) {
width: 12px;
height: 12px;
transform: rotate(45deg);
cursor: default;
box-sizing: border-box;
background: radial-gradient(circle, #ccc, #d3237a, #ccc);
transition: all 0.1s;
&:hover {
transform: rotate(45deg) scale(1.2);
box-shadow: 0 0 5px 2px #fff;
}
}
注意!!!!
- 在Vue/React等框架中,需要使用
:deep(.myIconCss)来深程度地设置样式,否则样式会无效 iconAnchor参数是为了平衡地图不同层级对于标记的偏移,如果不设置这个参数,你自定义的标记会在地图缩放的过程中偏差位置- 偏移量的计算规则:
[宽度的一半,高度]。CSS中宽高分别为12像素,所以偏移量设定为[6,12] - 建议同时设置
popupAnchor控制弹出框位置
这样,一个完全自定义的标记就生成了。
扩展,带有数字显示的marker
另外,如果需要制作的是带有数字或者字母显示的marker,也是同理,这里我以字体图标库中的图片为底,再在其中显示marker的数字或者字母
实现步骤:
- 准备一个中空的标记图标(推荐使用PNG透明背景)
- 使用绝对定位将数字显示在图标中央
尽量选择中空的图片,方便突出其中数字的显示。
js
//自定义icon的样式,这里与之前的有些微的差别
let myIconHtml = '<div class="myIconNumCss" style="background-image: url(${getStaticFilePath("../../../assets/Ear_war_fore/marker_1-1.png")})">'
//自定义icon
let myIcon = L.divIcon({
className: "",
html:myIconHtml + '数字' + "</div>",
iconAnchor: [25, 50],//偏移量
})
//应用到标记中
L.marker([50.505, 30.57], {icon: myIcon}).addTo(mapRef);
css
// 自定义地图icon
:deep(.myIconNumCss) {
width: 50px;
height: 50px;
background-size: contain;
background-repeat: no-repeat;
cursor: default;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding-bottom: 14px;
font-weight: bolder;
font-size: 14px;
}
这里有一个方法getStaticFilePath,如果图片加载不出来可以使用这个方法
js
// 获取本地静态资源路径
export function getStaticFilePath(path) {
const modules = import.meta.glob("/src/assets/**/*.{png,svg,jpg,jpeg,json}", {
eager: true,
import: "default",
});
path = path.replace(/.*?(/assets/)/, "/src$1");
return modules[path];
}
最终效果:
这样的处理方式,可以使得在地图缩放过程对这个icon进行转换,来适应不同的业务需求
扩展,凸显标记,动态波纹效果
有时候业务需求中需要加载很多marker,但有时需要对某一个点进行特别显示,比如选中状态或重点标注。这时可以使用CSS动画实现水波纹效果。
js
let point_dynamic = null, //动态点图层实例
// 绘制动态marker(水波纹效果)
draw_dynamic_point: (latlng) => {
if (point_dynamic != null) {
point_dynamic.setLatLng(latlng);
} else {
point_dynamic = L.marker(latlng, {
icon: L.divIcon({
className: "point_selected",
html: '<div class="point_dynamic"></div>',
iconAnchor: [6, 12],
}),
}).addTo(mapRef);
}
},
};
css
:deep(.point_dynamic) {
width: 12px;
height: 12px;
border-radius: 50px;
box-sizing: border-box;
background: rgb(211, 35, 122);
animation: dynamic 1s linear infinite;
}
@keyframes dynamic {
0% {
transform: scale(1);
}
25% {
transform: scale(2);
// border-color: rgba(255, 0, 0, 0.9);
background: rgba(211, 35, 122, 0.9);
}
50% {
transform: scale(3);
// border-color: rgba(255, 0, 0, 0.75);
background: rgba(211, 35, 122, 0.75);
}
75% {
transform: scale(4);
// border-color: rgba(255, 0, 0, 0.5);
background: rgba(211, 35, 122, 0.5);
}
100% {
transform: scale(5);
// border-color: rgba(255, 0, 0, 0.1);
background: rgba(211, 35, 122, 0.1);
}
}
应用场景:
- 地图上标记用户当前位置
- 突出显示被选中的POI点
- 紧急事件的位置标记
- 需要特别关注的重要地点
最终效果:

总结
本文详细介绍了Leaflet中自定义标记的多种方法:
- 基础标记实现
- 自定义图片标记
- 完全自定义HTML+CSS标记
- 带数字/文字的标记实现
- 动态特效标记(水波纹效果) 每种方法都有其适用场景,开发者可以根据实际项目需求选择最合适的实现方式。
好的,以上是本次分享内容,再次感谢各位前辈的宝贵经验,后续将持续分享更多实践成果。