Bläddra i källkod

feat: 地图“干线协调”和“勤务路线”添加方向箭头图标

sequoia tungfang 3 veckor sedan
förälder
incheckning
a4cb4a0d86
2 ändrade filer med 66 tillägg och 4 borttagningar
  1. BIN
      src/assets/map/direction.png
  2. 66 4
      src/components/TongzhouTrafficMap.vue

BIN
src/assets/map/direction.png


+ 66 - 4
src/components/TongzhouTrafficMap.vue

@@ -479,7 +479,65 @@ export default {
         overlays.push(polyline);
 
         const totalPoints = segmentPath.length;
-        const indices = this.pickEvenlySpacedIndices(totalPoints, 8);
+
+        // --- 核心优化:全路段物理距离均匀放置方向箭头 ---
+        // 1. 计算整条 segmentPath 的总物理距离及每个点的累计距离
+        const pathDistances = [0];
+        let totalPathDist = 0;
+        for (let j = 0; j < totalPoints - 1; j++) {
+          const d = this.calcApproxDistance(segmentPath[j], segmentPath[j+1]);
+          totalPathDist += d;
+          pathDistances.push(totalPathDist);
+        }
+
+        // 2. 设定标准间距:约每 0.0018 度 (约 200 米) 放置一个箭头
+        const targetSpacing = 0.0018;
+        let currentTargetDist = targetSpacing / 2; // 第一个箭头放在 1/2 间距处,让分布更美观
+
+        while (currentTargetDist < totalPathDist) {
+          // 3. 寻找对应 targetDist 的路径位置 (线性插值)
+          let foundIdx = 0;
+          for (let j = 0; j < pathDistances.length - 1; j++) {
+            if (currentTargetDist >= pathDistances[j] && currentTargetDist <= pathDistances[j + 1]) {
+              foundIdx = j;
+              break;
+            }
+          }
+
+          const p1 = segmentPath[foundIdx];
+          const p2 = segmentPath[foundIdx + 1];
+          if (p1 && p2) {
+            // 在 p1 和 p2 之间线性插值
+            const ratio = (currentTargetDist - pathDistances[foundIdx]) / (pathDistances[foundIdx + 1] - pathDistances[foundIdx]);
+            const lng1 = p1.lng || (Array.isArray(p1) ? Number(p1[0]) : 0);
+            const lat1 = p1.lat || (Array.isArray(p1) ? Number(p1[1]) : 0);
+            const lng2 = p2.lng || (Array.isArray(p2) ? Number(p2[0]) : 0);
+            const lat2 = p2.lat || (Array.isArray(p2) ? Number(p2[1]) : 0);
+            
+            const midLng = lng1 + (lng2 - lng1) * ratio;
+            const midLat = lat1 + (lat2 - lat1) * ratio;
+
+            const bearing = this.calcBearingDeg({ lng: lng1, lat: lat1 }, { lng: lng2, lat: lat2 });
+            const rotation = bearing - 90;
+
+            const directionMarker = new this.AMap.Marker({
+              position: [midLng, midLat],
+              content: `
+                <div style="transform: rotate(${rotation}deg); width: 20px; height: 10px; display: flex; align-items: center; pointer-events: none; opacity: 0.85;">
+                  <img src="${require('@/assets/map/direction.png')}" style="width: 100%; height: auto;" />
+                </div>
+              `,
+              offset: new this.AMap.Pixel(-10, -5),
+              zIndex: 20,
+              bubble: true
+            });
+            overlays.push(directionMarker);
+          }
+          currentTargetDist += targetSpacing;
+        }
+
+        // 为圆点保留原来的分布 logic (不受箭头影响)
+        const indices = this.pickEvenlySpacedIndices(totalPoints, 6);
 
         // 为第一个和最后一个圆点设置特殊类型
         for (let i = 0; i < indices.length; i++) {
@@ -604,9 +662,13 @@ export default {
       const latRad = ((a.lat + b.lat) / 2) * Math.PI / 180;
       const dx = (b.lng - a.lng) * Math.cos(latRad);
       const dy = (b.lat - a.lat);
-      let deg = Math.atan2(dy, dx) * 180 / Math.PI;
-      if (deg < 0) deg += 360;
-      return deg;
+      
+      // 使用地理方位角公式:0度为北,顺时针增加
+      // atan2(dy, dx) 返回数学角度(0为东,逆时针)
+      // geographic_bearing = (90 - math_angle + 360) % 360
+      const mathAngle = Math.atan2(dy, dx) * 180 / Math.PI;
+      let bearing = (90 - mathAngle + 360) % 360;
+      return bearing;
     },
 
     calcAngleDiffDeg(a, b) {