diff --git a/src/config/mork.js b/src/config/mork.js
index e2f3e11..a1226e1 100644
--- a/src/config/mork.js
+++ b/src/config/mork.js
@@ -53,8 +53,8 @@ export const queryMapAllStation = () => {
"station_name": "起点",
"station_type": "Station",
"action_type": "Customize",
- "x": 1.20309,
- "y": -0.238922,
+ "x": 0,
+ "y": -0,
"angle": -0.006407
},
{
@@ -346,8 +346,8 @@ export const getRouteInfo = () => {
"route_id": 1,
"start_id": 1,
"end_id": 2,
- "start_x": 1.20309,
- "start_y": -0.238922,
+ "start_x": 0,
+ "start_y": -0,
"end_x": 4.01522,
"end_y": 0.0628335,
"navigation_mode": "0",
@@ -711,8 +711,8 @@ export const getRouteInfo = () => {
"end_id": 1,
"start_x": 2.33115,
"start_y": -0.196742,
- "end_x": 1.20309,
- "end_y": -0.238922,
+ "end_x": 0,
+ "end_y": -0,
"navigation_mode": "1",
"route_type": "1"
}
diff --git a/src/pages/modules/map/index copy.vue b/src/pages/modules/map/index copy.vue
index 6875639..e039154 100644
--- a/src/pages/modules/map/index copy.vue
+++ b/src/pages/modules/map/index copy.vue
@@ -64,6 +64,46 @@
+
+
+
{{ $t('pathType') }}
+
+
+
{{ $t('straightPath') }}
+
+
+
+
{{ $t('reversePath') }}
+
+
+
+
{{ $t('bidirectionalPath') }}
+
+
+
{
- const nextPoint = this.pathData[index + 1]
- let controlX, controlY
- if (nextPoint) {
- // 有下一个点时,使用当前终点和下一个起点的中点作为控制点
- controlX = (point.px_end_x + nextPoint.px_start_x) / 2
- controlY = (point.px_end_y + nextPoint.px_start_y) / 2
- } else {
- // 最后一个点,使用当前终点作为控制点
- controlX = point.px_end_x
- controlY = point.px_end_y
+ // 根据 navigation_mode 设置路径颜色
+ let pathColor, pathColor1
+ switch(point.navigation_mode) {
+ case '0': // 直行 - 绿色
+ pathColor = 'rgba(0, 167, 26, 0.5)'
+ pathColor1= '#00a71a'
+ break
+ case '1': // 后退 - 黄色
+ pathColor = 'rgba(255, 87, 34, 0.5)'
+ pathColor1= '#ff5722'
+ break
+ case '2': // 双向 - 蓝色
+ pathColor = 'rgba(0, 125, 255, 0.5)'
+ pathColor1= '#007dff'
+ break
+ default:
+ pathColor = '#fff'
+ pathColor1= '#fff'
}
- this.ctx.beginPath()
- this.ctx.moveTo(point.px_start_x, point.px_start_y)
- this.ctx.quadraticCurveTo(controlX, controlY, point.px_end_x, point.px_end_y)
+
+ // 选中状态高亮
if (this.selectedPath.route_id === point.route_id) {
- this.ctx.strokeStyle = '#ff5722' // 橙色高亮
- this.ctx.lineWidth = 4
+ this.ctx.strokeStyle = pathColor1
+
} else {
- this.ctx.strokeStyle = '#009de5' // 默认蓝色
- this.ctx.lineWidth = 2
+ this.ctx.strokeStyle = pathColor
+ }
+ this.ctx.lineWidth = 6
+ this.ctx.beginPath()
+
+ if (point.route_type === '0') {
+ this.drawArc(point, index)
+ } else {
+ this.drawStraightLine(point)
}
this.ctx.stroke()
+
+ // 绘制箭头(大于号样式)
+ this.drawArrowheads(point, index)
})
},
+ drawStraightLine(point) {
+ this.ctx.moveTo(point.px_start_x, point.px_start_y)
+ this.ctx.lineTo(point.px_end_x, point.px_end_y)
+ },
+ drawArc(point, index) {
+ const prevPoint = this.pathData[index - 1]
+ const nextPoint = this.pathData[index + 1]
+
+ // 计算进入方向(从上一个线段)
+ let entryDirection
+ if (prevPoint && prevPoint.route_type === "1") {
+ // 上一个点是直线,使用上一个线段的朝向
+ entryDirection = Math.atan2(
+ point.px_start_y - prevPoint.px_start_y,
+ point.px_start_x - prevPoint.px_start_x
+ )
+ } else {
+ // 没有上一个点或上一个点也是圆弧,使用默认方向
+ entryDirection = Math.atan2(
+ point.px_end_y - point.px_start_y,
+ point.px_end_x - point.px_start_x
+ )
+ }
+
+ // 计算离开方向(到下一个线段)
+ let exitDirection
+ if (nextPoint && nextPoint.route_type === "1") {
+ // 下一个点是直线,使用下一个线段的朝向
+ exitDirection = Math.atan2(
+ nextPoint.px_end_y - point.px_end_y,
+ nextPoint.px_end_x - point.px_end_x
+ )
+ } else {
+ // 没有下一个点或下一个点也是圆弧,使用默认方向
+ exitDirection = Math.atan2(
+ point.px_end_y - point.px_start_y,
+ point.px_end_x - point.px_start_x
+ )
+ }
+
+ // 计算圆弧控制点
+ const controlPoint = this.calculateArcControlPoint(
+ point.px_start_x, point.px_start_y,
+ point.px_end_x, point.px_end_y,
+ entryDirection, exitDirection
+ )
+
+ this.ctx.moveTo(point.px_start_x, point.px_start_y)
+ this.ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, point.px_end_x, point.px_end_y)
+ },
+ // 绘制箭头(大于号样式)
+ drawArrowheads(point, index) {
+ const t = 0.5 // 箭头位置在路径中间
+
+ let arrowX, arrowY, dirX, dirY
+
+ if (point.route_type === '1') {
+ // 直线路径
+ arrowX = point.px_start_x + (point.px_end_x - point.px_start_x) * t
+ arrowY = point.px_start_y + (point.px_end_y - point.px_start_y) * t
+ dirX = point.px_end_x - point.px_start_x
+ dirY = point.px_end_y - point.px_start_y
+ } else {
+ // 圆弧路径
+ const prevPoint = this.pathData[index - 1]
+ const nextPoint = this.pathData[index + 1]
+ const entryDirection = prevPoint && prevPoint.route_type === "1"
+ ? Math.atan2(point.px_start_y - prevPoint.px_start_y, point.px_start_x - prevPoint.px_start_x)
+ : Math.atan2(point.px_end_y - point.px_start_y, point.px_end_x - point.px_start_x)
+ const exitDirection = nextPoint && nextPoint.route_type === "1"
+ ? Math.atan2(nextPoint.px_end_y - point.px_end_y, nextPoint.px_end_x - point.px_end_x)
+ : Math.atan2(point.px_end_y - point.px_start_y, point.px_end_x - point.px_start_x)
+ const controlPoint = this.calculateArcControlPoint(
+ point.px_start_x, point.px_start_y,
+ point.px_end_x, point.px_end_y,
+ entryDirection, exitDirection
+ )
+
+ // 二次贝塞尔曲线中间点
+ arrowX = Math.pow(1 - t, 2) * point.px_start_x
+ + 2 * (1 - t) * t * controlPoint.x
+ + Math.pow(t, 2) * point.px_end_x
+ arrowY = Math.pow(1 - t, 2) * point.px_start_y
+ + 2 * (1 - t) * t * controlPoint.y
+ + Math.pow(t, 2) * point.px_end_y
+
+ // 曲线在中间点的方向向量
+ dirX = 2 * (1 - t) * (controlPoint.x - point.px_start_x)
+ + 2 * t * (point.px_end_x - controlPoint.x)
+ dirY = 2 * (1 - t) * (controlPoint.y - point.px_start_y)
+ + 2 * t * (point.px_end_y - controlPoint.y)
+ }
+
+ // 归一化方向向量
+ const length = Math.sqrt(dirX ** 2 + dirY ** 2)
+ if (length === 0) return
+
+ const normDirX = dirX / length
+ const normDirY = dirY / length
+
+ // 根据 navigation_mode 绘制箭头
+ switch(point.navigation_mode) {
+ case '0': // 直行 - 单个向前箭头
+ this.drawGreaterThanArrow(arrowX, arrowY, normDirX, normDirY)
+ break
+
+ case '1': // 后退 - 也是单个向前箭头
+ this.drawGreaterThanArrow(arrowX, arrowY, normDirX, normDirY)
+ break
+
+ case '2': // 双向 - 两个方向箭头
+ // 向前箭头(稍微偏移)
+ this.drawGreaterThanArrow(
+ arrowX - normDirX * 8,
+ arrowY - normDirY * 8,
+ normDirX,
+ normDirY
+ )
+ // 向后箭头(稍微偏移)
+ this.drawGreaterThanArrow(
+ arrowX + normDirX * 8,
+ arrowY + normDirY * 8,
+ -normDirX,
+ -normDirY
+ )
+ break
+ }
+ },
+ // 绘制大于号样式的箭头
+ drawGreaterThanArrow(x, y, dirX, dirY) {
+ const arrowLength = 2 // 箭头长度
+ const arrowWidth = 4 // 箭头宽度
+
+ // 计算垂直方向向量(旋转90度)
+ const perpX = -dirY
+ const perpY = dirX
+
+ // 计算大于号的三个点
+ // 顶点(箭头尖端)
+ const tipX = x + dirX * arrowLength
+ const tipY = y + dirY * arrowLength
+
+ // 左侧点
+ const leftX = x - dirX * arrowLength / 2 + perpX * arrowWidth / 2
+ const leftY = y - dirY * arrowLength / 2 + perpY * arrowWidth / 2
+
+ // 右侧点
+ const rightX = x - dirX * arrowLength / 2 - perpX * arrowWidth / 2
+ const rightY = y - dirY * arrowLength / 2 - perpY * arrowWidth / 2
+
+ // 绘制大于号形状
+ this.ctx.beginPath()
+ this.ctx.moveTo(leftX, leftY) // 从左侧点开始
+ this.ctx.lineTo(tipX, tipY) // 画到尖端
+ this.ctx.lineTo(rightX, rightY) // 画到右侧点
+ this.ctx.strokeStyle = '#fff'
+ this.ctx.lineWidth = 1.5
+ this.ctx.lineCap = 'round'
+ this.ctx.lineJoin = 'round'
+ this.ctx.stroke()
+ },
+ // 计算圆弧控制点
+ calculateArcControlPoint(startX, startY, endX, endY, entryDir, exitDir) {
+ const midX = (startX + endX) / 2
+ const midY = (startY + endY) / 2
+
+ // 计算方向差异
+ let angleDiff = exitDir - entryDir
+
+ // 规范化角度差异到 [-PI, PI] 范围
+ while (angleDiff > Math.PI) angleDiff -= 2 * Math.PI
+ while (angleDiff < -Math.PI) angleDiff += 2 * Math.PI
+
+ // 计算弯曲方向和强度
+ const distance = Math.sqrt((endX - startX) ** 2 + (endY - startY) ** 2)
+ const bendStrength = Math.tan(angleDiff / 4) * distance * 0.5
+
+ // 计算垂直于平均方向的控制点偏移
+ const avgDirection = (entryDir + exitDir) / 2
+ const perpendicularDir = avgDirection + Math.PI / 2
+
+ const controlX = midX + bendStrength * Math.cos(perpendicularDir)
+ const controlY = midY + bendStrength * Math.sin(perpendicularDir)
+
+ return { x: controlX, y: controlY }
+ },
drawMarkers () {
if (!this.pointData.length || !this.ctx) return
if (!this.cachedImages.marker) {
@@ -385,24 +633,24 @@ export default {
}
return // 等待图标加载完成后再绘制
}
- this.pointData.forEach(point => {
- // 绘制选中状态
- if (point.station_id === this.selectedPointId) {
+ this.pointData.forEach((point, index) => {
+ if (point.station_type === 'Station') {
this.ctx.beginPath()
this.ctx.arc(point.px_x, point.px_y, 5, 0, Math.PI * 2)
- this.ctx.fillStyle = '#59ccd2'
+ if (point.station_id === this.selectedPointId) {
+ this.ctx.fillStyle = index === 0 ? '#d700c1' : '#009de5'
+ this.ctx.fill()
+ } else {
+ this.ctx.strokeStyle = index === 0 ? 'rgba(215, 0, 193, 0.6)' : 'rgba(0, 157, 229, 0.6)'
+ this.ctx.lineWidth = 11
+ this.ctx.stroke()
+ this.ctx.fillStyle = 'rgba(255,255,255,0.6)'
+ }
this.ctx.fill()
- } else {
- this.ctx.drawImage(this.cachedImages.marker, point.px_x - MARKER_SIZE / 2, point.px_y - MARKER_SIZE / 2, MARKER_SIZE, MARKER_SIZE)
- }
- // 绘制点位名称(文字大小随缩放变化)
- if (point.station_type === 'Station') {
this.ctx.font = '12px Arial'
- this.ctx.fillStyle = '#62fa0a'
+ this.ctx.fillStyle = index === 0 ? '#d700c1' : '#62fa0a'
this.ctx.textAlign = 'center'
this.ctx.fillText(point.station_name, point.px_x, point.px_y + 22)
- // this.ctx.fillText(point.x, point.px_x, point.px_y + 34)
- // this.ctx.fillText(point.y, point.px_x, point.px_y + 50)
}
})
},
@@ -501,7 +749,7 @@ export default {
this.showPathPopup = false
} else {
this.selectedPath = path
- this.calculatePopupPosition(event, 95, this.pathPopupStyle)
+ this.calculatePopupPosition(event, 143, this.pathPopupStyle)
this.showPathPopup = true
}
this.redrawCanvas()
@@ -893,4 +1141,69 @@ export default {
font-size: 0.18rem;
line-height: 0.32rem;
color: #fff;
+
+.marker_wrap
+ position absolute
+ bottom 10px
+ right 10px
+ z-index 20
+.path-legend
+ border 1px solid rgba(77, 155, 205, 0.6)
+ border-radius 8px
+ padding 12px
+ box-shadow 0 2px 8px rgba(0, 0, 0, 0.3)
+.legend-title
+ font-size 14px
+ font-weight bold
+ color #fff
+ margin-bottom 10px
+ text-align center
+ border-bottom 1px solid rgba(255, 255, 255, 0.2)
+ padding-bottom 5px
+.legend-item
+ display flex
+ align-items center
+ margin-bottom 8px
+ &:last-child
+ margin-bottom 0
+.line-sample
+ position relative
+ width 50px
+ height 10px
+ margin-right 10px
+ display flex
+ align-items center
+ justify-content center
+.straight-line
+ background rgba(0, 167, 26, 0.4) // 直行 - 绿色
+.reverse-line
+ background rgba(255, 87, 34, 0.4) // 后退 - 橙色
+.bidirectional-line
+ background rgba(0, 125, 255, 0.4) // 双向 - 蓝色
+ justify-content space-between
+.legend-text
+ font-size 12px
+ color #e0e0e0
+ white-space nowrap
+.arrow-container
+ position absolute
+ display flex
+ align-items center
+ justify-content center
+
+/* 直行和后退路径箭头 - 右侧 */
+.straight-line .arrow-container,
+.reverse-line .arrow-container
+ left calc(50% - 3px)
+
+/* 双向路径箭头 */
+.bidirectional-line .arrow-container
+ &.left-arrow
+ left 12px
+ &.right-arrow
+ right 12px
+
+/* 箭头SVG样式 */
+.arrow-svg
+ filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.5))
\ No newline at end of file
diff --git a/src/pages/modules/map/index.vue b/src/pages/modules/map/index.vue
index e039154..3a5e245 100644
--- a/src/pages/modules/map/index.vue
+++ b/src/pages/modules/map/index.vue
@@ -18,6 +18,8 @@
class="mapSvg"
ref="mapSvg"
xmlns="http://www.w3.org/2000/svg"
+ width="5000"
+ height="5000"
>