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);
相关推荐
cyadyx34 分钟前
Vite 比 Webpack 构建效率更高
前端·webpack·node.js·vite
mCell2 小时前
AI 时代 SVG 画图的潜力
前端·agent·svg
我命由我123458 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js
Hopebearer_9 小时前
页面突然只剩 DOM?一次静态资源版本错配排查
前端·部署
东风破_9 小时前
ESLint 是什么?为什么你的项目需要它?
前端·后端·代码规范
圣殿骑士-Khtangc11 小时前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
BigTopOne11 小时前
【ijkplayer】 硬解码流程
前端
kyriewen12 小时前
DeepSeek Harness开源第一天我就上手了——和Claude Code的差距比想象中大
前端·ai编程·deepseek
捡田螺的小男孩12 小时前
什么是 Skill?手把手带你写一个简单有用的 Skill!
前端·后端·程序员
IT_陈寒12 小时前
Redis集群这个坑,差点让我通宵
前端·人工智能·后端