静态箭头连线

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>
相关推荐
伍哥的传说2 小时前
QRCode React 完全指南:现代化二维码生成解决方案
前端·javascript·react.js·qrcode.react·react二维码生成·qrcodesvg·qrcodecanvas
NiKo_W2 小时前
Git 版本回退与撤销修改
开发语言·git·安全
listhi5202 小时前
Map对象在JavaScript循环中的使用
开发语言·前端·javascript
大可门耳2 小时前
Qt第一课:Qt是什么?相对于其他框架的优劣势是什么
开发语言·qt
西阳未落3 小时前
C语言中的内存函数(memcpy, memmove, memcmp, memset)
c语言·开发语言
axban5 小时前
QT M/V架构开发实战:QFileSystemModel介绍
开发语言·qt·架构
钢门狂鸭7 小时前
关于rust的crates.io
开发语言·后端·rust
Lionel_SSL7 小时前
《深入理解Java虚拟机》第三章读书笔记:垃圾回收机制与内存管理
java·开发语言·jvm
技术猿188702783518 小时前
PHP 与 WebAssembly 的 “天然隔阂”
开发语言·php·wasm