轻松打造个性化Leaflet地图标记

前期准备

在开始自定义标点(marker)功能开发前,我们已经完成了以下基础工作:

  1. 下载leaflet包并引入到项目中;
  2. 创建地图容器,地图实例使用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设定,其中的图片可以从阿里巴巴矢量图标库中去任意选择 推荐资源:

完全自定义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;
  }
}

注意!!!!

  1. 在Vue/React等框架中,需要使用:deep(.myIconCss)来深程度地设置样式,否则样式会无效
  2. iconAnchor参数是为了平衡地图不同层级对于标记的偏移,如果不设置这个参数,你自定义的标记会在地图缩放的过程中偏差位置
  3. 偏移量的计算规则:[宽度的一半,高度]。CSS中宽高分别为12像素,所以偏移量设定为[6,12]
  4. 建议同时设置popupAnchor控制弹出框位置

这样,一个完全自定义的标记就生成了。

扩展,带有数字显示的marker

另外,如果需要制作的是带有数字或者字母显示的marker,也是同理,这里我以字体图标库中的图片为底,再在其中显示marker的数字或者字母

实现步骤:

  1. 准备一个中空的标记图标(推荐使用PNG透明背景)
  2. 使用绝对定位将数字显示在图标中央

尽量选择中空的图片,方便突出其中数字的显示。

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);
  }
}

应用场景:

  1. 地图上标记用户当前位置
  2. 突出显示被选中的POI点
  3. 紧急事件的位置标记
  4. 需要特别关注的重要地点

最终效果:

总结

本文详细介绍了Leaflet中自定义标记的多种方法:

  1. 基础标记实现
  2. 自定义图片标记
  3. 完全自定义HTML+CSS标记
  4. 带数字/文字的标记实现
  5. 动态特效标记(水波纹效果) 每种方法都有其适用场景,开发者可以根据实际项目需求选择最合适的实现方式。

好的,以上是本次分享内容,再次感谢各位前辈的宝贵经验,后续将持续分享更多实践成果。

相关推荐
前端大卫1 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘2 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare2 小时前
浅浅看一下设计模式
前端
Lee川2 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix2 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人2 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl2 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人2 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼2 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端