轻松打造个性化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. 动态特效标记(水波纹效果) 每种方法都有其适用场景,开发者可以根据实际项目需求选择最合适的实现方式。

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

相关推荐
华仔啊2 小时前
CSS实现高级流光按钮动画,这几行代码堪称神来之笔
前端·css
用户3777967210962 小时前
新值依赖旧值?并发更新的“坑”
javascript
歪歪1002 小时前
详细介绍一下“集中同步+分布式入库”方案的具体实现步骤
开发语言·前端·分布式·后端·信息可视化
林太白2 小时前
rust17-部门管理模块
前端·后端·rust
_处女座程序员的日常2 小时前
如何预览常见格式word、excel、ppt、图片等格式的文档
前端·javascript·word·excel·开源软件
明月与玄武2 小时前
前端文件上传终极指南:从原理到架构实践!
前端·前端文件上传终极指南
布列瑟农的星空3 小时前
后台类项目如何挖掘前端技术亮点
前端·面试
wangbing11254 小时前
layui窗口标题
前端·javascript·layui
qq_398586544 小时前
Utools插件实现Web Bluetooth
前端·javascript·electron·node·web·web bluetooth