openlayer实现定位闪烁

一、项目介绍

产品说地图上只标一个图标,有点看不清在哪里,不够明显,行吧,那我给你加个动画,现在可以看清楚了吧。

二、初始化地图

初始化一个高德地图并定义一个矢量图层,用来展示矢量图标。

js 复制代码
//高德地图
this.raster = new TileLayer({
    source: new XYZ({
     url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=2&style=6",
     }),
 });
 //矢量图层
 this.source = new VectorSource({ wrapX: false });
 this.vector = new VectorLayer({
      source: this.source,
      zIndex: 100,
      declutter: true  // 避免图标重叠
 });
 
 //初始化地图
 this.map = new Map({
  layers: [this.raster, this.vector],
  target: id,
  view: new View({
    center: fromLonLat(this.center),
    zoom: 13,
  }),
  controls: [], // 不添加任何默认控件
});

三、创建矢量图标

然后引入icon类型,创建一个icon图标。

方法类别 核心类/API 优点 适用场景 关键提示
图片图标 ol/style/Icon 简单直接,支持多种图片格式 使用静态图片(PNG, JPG, SVG等)作为图标 注意调整锚点(anchor)以确保精准定位
字体图标 (Canvas) ol/style/Icon + Canvas 可动态生成,灵活修改颜色样式 需要动态控制颜色、大小的图标 将Canvas转换为DataURL使用
字体图标 (Text) ol/style/Text 无需图片,使用字体文件,矢量缩放清晰 使用iconfont等字体图标库 确保字体文件正确加载,处理Unicode编码
矢量图形 ol/style/RegularShape 由代码生成,无需外部资源,可动态设置样式 简单几何形状(圆形、方形、星形等) 可组合使用多种Style实现复杂效果
js 复制代码
//feacture图形
 const iconFeature = new Feature({
      geometry: new Point(fromLonLat([item.lon,item.lat])),
      name: item?.name,
      id: item?.id,
      type: "icon",
      description: description,
      item: item,
      population: 4000,
      rainfall: 500,
  });
  //样式
 const iconStyle = new Style({
      image: new Icon({
        anchor: [0.5, 0.5],
        scale: 0.4,
        src: url,
      }),
      text: new Text({
        text: iconFeature.get("name"),
        textAlign: "center",
        textBaseline: "middle",
        offsetY: 30, // 文字向下偏移
        font: "bold 14px Calibri,sans-serif",
        fill: new Fill({
          color: "#333",
        }),
        stroke: new Stroke({
          color: "#fff",
          width: 1,
        }),
      }),
    });

    iconFeature.setStyle(iconStyle);
    this.source.addFeature(iconFeature);

四、闪烁图标

OpenLayers 提供了多种图层事件监听函数,允许你监测图层的状态变化、用户交互以及渲染过程。

事件类型 主要事件名称 说明 适用场景
图层状态事件 loadstart, loadend 监听图层数据的开始加载和加载完成状态 显示加载进度条、处理加载异常
visibilitychanged 图层可见性改变时触发 同步控制其他图层显示隐藏、动态调整界面元素
图层操作事件 addlayer, removelayer 图层被添加到地图或从地图移除时触发 (注:这些是地图的事件,而非图层自身的事件) 维护图层列表、记录用户操作日志
渲染相关事件 prerender, postrender 在图层渲染前后触发 进行自定义绘制(如绘制遮罩、高亮)、性能监控
precompose, postcompose 在整个地图合成前后触发 (更像是地图上下文的事件) 高级效果处理(如滤镜)、地图截图
矢量图层交互事件 featureselected, featureunselected 使用 Select 交互时,要素被选中或取消选中时触发 显示弹出Popup、展示属性信息、执行自定义操作
图层变动事件 change, change:source, propertychange 图层属性(如源source)或样式发生变化时触发 响应式更新UI、动态调整地图行为

OpenLayers 中的 postrender 事件是一个非常重要的图层渲染事件,它在图层每一帧的渲染完成后触发。你可以利用这个事件在现有的图层渲染之上执行自定义的绘制操作、创建动画效果或进行后处理。

js 复制代码
 let radius = 20;

 this.vector.on("postrender", listerEvent );
 
 function listerEvent(evt){
      const features = this.source.getFeatures();
      if (radius >= 50) radius = 20;
      var opacity = (50 - radius) * (1 / 50); //不透明度
      var pointStyle = new Style({
        image: new CircleStyle({
          radius: radius,
          stroke: new Stroke({
            color: "rgba(35,143,196," + opacity + ")",
            width: 3 - radius / 50, //设置宽度
          }),
          offsetY: -20,
        }),
      });
      // 获取矢量要素上下文
      let vectorContext = getVectorContext(evt);
      vectorContext.setStyle(pointStyle);

      radius = radius + 0.3; //调整闪烁速度

      features.forEach((feature) => {
        if (feature.get("type") === "icon") {
          vectorContext.drawGeometry(feature.getGeometry());
        }
      });

      if (features.length) {
        this.map.render();
      }
    }
    

由于 postrender 事件在每一次图层渲染时都会触发(例如地图移动、缩放时),因此其回调函数的执行效率至关重要。

  1. 避免昂贵操作 :在回调函数中避免执行复杂的计算、大规模的 DOM 操作或频繁创建大量新对象(如复杂的样式 Style 或几何体 Geometry),否则极易造成页面卡顿。
  2. 及时清理 :当动画停止或不再需要监听 postrender 时,一定要使用 layer.un() 方法移除事件监听器,否则它会继续执行,浪费资源。
  3. 依赖 frameState :对于动画,利用 event.frameState.time 来计算动画状态,它可以提供一致的时间参考。
js 复制代码
//根据id删除矢量图标
 this.source.forEachFeature((feature) => {
  if (feature.get("id") === id) {
    this.source.removeFeature(feature);
  }
});
//移除监听
this.map.un("postrender",listerEvent);
相关推荐
Delroy2 分钟前
CSS Grid布局:从魔方拼图到网页设计大师 🎯
前端·css
拜晨10 分钟前
类型体操的实践与总结: 从useInfiniteScroll 到 InfiniteList
前端·typescript
月弦笙音14 分钟前
【XSS】后端服务已经加了放xss攻击,前端还需要加么?
前端·javascript·xss
code_Bo17 分钟前
基于vueflow实现动态添加标记的装置图
前端·javascript·vue.js
传奇开心果编程1 小时前
【传奇开心果系列】Flet框架实现的图形化界面的PDF转word转换器办公小工具自定义模板
前端·python·学习·ui·前端框架·pdf·word
IT_陈寒2 小时前
Python开发者必知的5个高效技巧,让你的代码速度提升50%!
前端·人工智能·后端
zm4352 小时前
浅记Monaco-editor 初体验
前端
超凌2 小时前
vue element-ui 对表格的单元格边框加粗
前端
前端搬运侠2 小时前
🚀 TypeScript 中的 10 个隐藏技巧,让你的代码更优雅!
前端·typescript