静态箭头连线

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>OpenLayers 历史轨迹(带箭头)效果演示</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/ol@9.1.0/ol.css"
    />
    <script src="https://cdn.jsdelivr.net/npm/ol@9.1.0/dist/ol.js"></script>
    <style>
      html,
      body {
        margin: 0;
        height: 100%;
        width: 100%;
      }
      #map {
        width: 100%;
        height: 100%;
        background: #f8f8f8;
      }
      .info {
        position: absolute;
        top: 10px;
        left: 10px;
        padding: 10px;
        background: rgba(255, 255, 255, 0.8);
        border: 1px solid #ccc;
        border-radius: 5px;
        font-family: sans-serif;
        z-index: 1;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <div class="info">
      <h4>历史轨迹箭头效果演示</h4>
      <p>
        此 Demo 展示了如何使用 Style Function 动态为每一段轨迹线添加方向箭头。
      </p>
    </div>

    <script>
      /**
       * 核心函数:绘制历史轨迹(带箭头方向)
       * @param {ol.Map} map - OpenLayers 的 Map 对象
       * @param {Array<Array<{longitude: number, latitude: number}>>} multiHistoryWayPoints - 轨迹数组
       */
      function createHistoryWays(map, multiHistoryWayPoints) {
        const historyWayFeatures = [];

        for (const historyWay of multiHistoryWayPoints) {
          if (!Array.isArray(historyWay) || historyWay.length < 2) continue;

          for (let i = 0; i < historyWay.length - 1; i++) {
            const curPointCoor = historyWay[i];
            const nextPointCoor = historyWay[i + 1];

            // Use the global 'ol' object to access classes
            const lineGeometry = new ol.geom.LineString([
              ol.proj.fromLonLat([
                curPointCoor.longitude,
                curPointCoor.latitude,
              ]),
              ol.proj.fromLonLat([
                nextPointCoor.longitude,
                nextPointCoor.latitude,
              ]),
            ]);

            const lineFeature = new ol.Feature({
              geometry: lineGeometry,
            });

            historyWayFeatures.push(lineFeature);
          }
        }

        if (historyWayFeatures.length === 0) {
          console.warn("没有有效的历史轨迹数据来创建图层。");
          return;
        }

        const vectorSource = new ol.source.Vector({
          features: historyWayFeatures,
        });

        const historyLayer = new ol.layer.Vector({
          source: vectorSource,
        });

        const arrowSvg = `
          <svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
            <path d="M2 10 L18 10 M12 4 L18 10 L12 16"
                  fill="none" stroke="rgba(0, 123, 255, 0.9)" stroke-width="2"
                  stroke-linecap="round" stroke-linejoin="round" />
          </svg>`;

        const arrowIconSrc = "data:image/svg+xml;base64," + btoa(arrowSvg);

        const styleFunction = (feature) => {
          const geometry = feature.getGeometry();
          const coords = geometry.getCoordinates();
          const start = coords[0];
          const end = coords[1];
          const dx = end[0] - start[0];
          const dy = end[1] - start[1];
          const rotation = Math.atan2(dy, dx);

          return [
            // Lines now start with 'ol.style'
            new ol.style.Style({
              stroke: new ol.style.Stroke({
                color: "rgba(0, 123, 255, 0.8)",
                width: 3,
              }),
            }),
            new ol.style.Style({
              geometry: new ol.geom.Point(end),
              image: new ol.style.Icon({
                src: arrowIconSrc,
                anchor: [0.75, 0.5],
                rotateWithView: true,
                rotation: -rotation,
              }),
            }),
          ];
        };

        historyLayer.setStyle(styleFunction);

        map.addLayer(historyLayer);
        map.getView().fit(vectorSource.getExtent(), {
          padding: [80, 80, 80, 80],
          duration: 1000,
        });

        console.log("成功创建并添加了历史轨迹图层。");
      }

      // --- Demo 初始化 ---

      // All classes are now accessed via the global 'ol' object
      const map = new ol.Map({
        target: "map",
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM(),
          }),
        ],
        view: new ol.View({
          center: ol.proj.fromLonLat([116.397428, 39.90923]),
          zoom: 10,
        }),
      });

      const sampleTracks = [
        [
          { longitude: 116.3, latitude: 39.9 },
          { longitude: 116.35, latitude: 39.92 },
          { longitude: 116.4, latitude: 39.9 },
          { longitude: 116.45, latitude: 39.93 },
          { longitude: 116.5, latitude: 39.91 },
        ],
        [
          { longitude: 116.32, latitude: 39.98 },
          { longitude: 116.38, latitude: 39.99 },
          { longitude: 116.42, latitude: 39.96 },
        ],
      ];

      createHistoryWays(map, sampleTracks);
    </script>
  </body>
</html>
相关推荐
会周易的程序员6 小时前
js-shm: 高性能 Node.js 共享内存模块
开发语言·javascript·c++·node.js·共享内存·shm
笨蛋不要掉眼泪6 小时前
Java虚拟机:常用参数
java·开发语言·python
带娃的IT创业者6 小时前
重新定义前端构建速度:深度解析 SWC 如何用 Rust 颠覆 JavaScript 工具链
前端·javascript·rust·前端构建·swc
happy_0x3f6 小时前
前端应用的离线暂停更新策略
开发语言·前端·php
shylyly_7 小时前
C++中的类型转换
开发语言·c++·匿名对象·隐式类型转换·拷贝优化
新中地GIS开发老师7 小时前
零基础WebGIS开发入门 | GeoJSON数据持久化
前端·javascript·gis·webgis·三维gis开发
北冥you鱼7 小时前
Go 语言新手扫盲:指针 * 和 & 使用场景详解
开发语言·后端·golang
cui_ruicheng7 小时前
Python数据分析(一):数据分析概述与环境搭建
开发语言·python·数据分析
blns_yxl8 小时前
正则驱动实时表单验证(HTML+CSS+JS+正则)
javascript·css·html
心平气和量大福大8 小时前
C#-WPF-UserControl-生命周期(加载 退出)
开发语言·c#·wpf