diff --git a/miniprogram/assets/compass-north-arrow.svg b/miniprogram/assets/compass-north-arrow.svg
new file mode 100644
index 0000000..4fee519
--- /dev/null
+++ b/miniprogram/assets/compass-north-arrow.svg
@@ -0,0 +1,4 @@
+
diff --git a/miniprogram/assets/compass-north-arrow2.svg b/miniprogram/assets/compass-north-arrow2.svg
new file mode 100644
index 0000000..60db67a
--- /dev/null
+++ b/miniprogram/assets/compass-north-arrow2.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/miniprogram/engine/layer/gpsLayer.ts b/miniprogram/engine/layer/gpsLayer.ts
index c0e8e88..641626e 100644
--- a/miniprogram/engine/layer/gpsLayer.ts
+++ b/miniprogram/engine/layer/gpsLayer.ts
@@ -16,7 +16,11 @@ function buildVectorCamera(scene: MapScene): CameraState {
}
export class GpsLayer implements MapLayer {
- projectPoint(scene: MapScene): ScreenPoint {
+ projectPoint(scene: MapScene): ScreenPoint | null {
+ if (!scene.gpsPoint) {
+ return null
+ }
+
const camera = buildVectorCamera(scene)
const worldPoint = calibratedLonLatToWorldTile(scene.gpsPoint, scene.zoom, scene.gpsCalibration, scene.gpsCalibrationOrigin)
return worldToScreen(camera, worldPoint, false)
@@ -29,6 +33,10 @@ export class GpsLayer implements MapLayer {
draw(context: LayerRenderContext): void {
const { ctx, scene, pulseFrame } = context
const gpsScreenPoint = this.projectPoint(scene)
+ if (!gpsScreenPoint) {
+ return
+ }
+
const pulse = this.getPulseRadius(pulseFrame)
ctx.save()
diff --git a/miniprogram/engine/layer/trackLayer.ts b/miniprogram/engine/layer/trackLayer.ts
index 307a2c6..47d1dde 100644
--- a/miniprogram/engine/layer/trackLayer.ts
+++ b/miniprogram/engine/layer/trackLayer.ts
@@ -32,6 +32,9 @@ export class TrackLayer implements MapLayer {
draw(context: LayerRenderContext): void {
const { ctx, scene } = context
const points = this.projectPoints(scene)
+ if (!points.length) {
+ return
+ }
ctx.save()
ctx.lineCap = 'round'
diff --git a/miniprogram/engine/map/mapEngine.ts b/miniprogram/engine/map/mapEngine.ts
index 04dde4c..de6e186 100644
--- a/miniprogram/engine/map/mapEngine.ts
+++ b/miniprogram/engine/map/mapEngine.ts
@@ -47,17 +47,6 @@ const COMPASS_NEEDLE_SMOOTHING = 0.12
const GPS_TRACK_MAX_POINTS = 200
const GPS_TRACK_MIN_STEP_METERS = 3
-const SAMPLE_TRACK_WGS84: LonLatPoint[] = [
- worldTileToLonLat({ x: DEFAULT_CENTER_TILE_X - 0.72, y: DEFAULT_CENTER_TILE_Y + 0.44 }, DEFAULT_ZOOM),
- worldTileToLonLat({ x: DEFAULT_CENTER_TILE_X - 0.18, y: DEFAULT_CENTER_TILE_Y + 0.08 }, DEFAULT_ZOOM),
- worldTileToLonLat({ x: DEFAULT_CENTER_TILE_X + 0.22, y: DEFAULT_CENTER_TILE_Y - 0.16 }, DEFAULT_ZOOM),
- worldTileToLonLat({ x: DEFAULT_CENTER_TILE_X + 0.64, y: DEFAULT_CENTER_TILE_Y - 0.52 }, DEFAULT_ZOOM),
-]
-const SAMPLE_GPS_WGS84: LonLatPoint = worldTileToLonLat(
- { x: DEFAULT_CENTER_TILE_X + 0.12, y: DEFAULT_CENTER_TILE_Y - 0.06 },
- DEFAULT_ZOOM,
-)
-
type TouchPoint = WechatMiniprogram.TouchDetail
type GestureMode = 'idle' | 'pan' | 'pinch'
@@ -435,7 +424,7 @@ export class MapEngine {
defaultCenterTileX: number
defaultCenterTileY: number
tileBoundsByZoom: Record | null
- currentGpsPoint: LonLatPoint
+ currentGpsPoint: LonLatPoint | null
currentGpsTrack: LonLatPoint[]
currentGpsAccuracyMeters: number | null
hasGpsCenteredOnce: boolean
@@ -485,7 +474,7 @@ export class MapEngine {
this.defaultCenterTileX = DEFAULT_CENTER_TILE_X
this.defaultCenterTileY = DEFAULT_CENTER_TILE_Y
this.tileBoundsByZoom = null
- this.currentGpsPoint = SAMPLE_GPS_WGS84
+ this.currentGpsPoint = null
this.currentGpsTrack = []
this.currentGpsAccuracyMeters = null
this.hasGpsCenteredOnce = false
@@ -1302,13 +1291,12 @@ export class MapEngine {
const exactCenter = this.getExactCenterFromTranslate(this.state.tileTranslateX, this.state.tileTranslateY)
const resolvedViewport = this.resolveViewportForExactCenter(exactCenter.x, exactCenter.y, nextRotationDeg)
- this.state = {
- ...this.state,
+ this.setState({
...resolvedViewport,
rotationDeg: nextRotationDeg,
rotationText: formatRotationText(nextRotationDeg),
centerText: buildCenterText(this.state.zoom, resolvedViewport.centerTileX, resolvedViewport.centerTileY),
- }
+ })
this.syncRenderer()
}
@@ -1408,7 +1396,7 @@ export class MapEngine {
previewScale: this.previewScale || 1,
previewOriginX: this.previewOriginX || this.state.stageWidth / 2,
previewOriginY: this.previewOriginY || this.state.stageHeight / 2,
- track: this.currentGpsTrack.length ? this.currentGpsTrack : SAMPLE_TRACK_WGS84,
+ track: this.currentGpsTrack,
gpsPoint: this.currentGpsPoint,
gpsCalibration: GPS_MAP_CALIBRATION,
gpsCalibrationOrigin: worldTileToLonLat({ x: this.defaultCenterTileX, y: this.defaultCenterTileY }, this.defaultZoom),
@@ -1807,6 +1795,8 @@ export class MapEngine {
+
+
diff --git a/miniprogram/engine/renderer/mapRenderer.ts b/miniprogram/engine/renderer/mapRenderer.ts
index 4b84a18..8bec3e3 100644
--- a/miniprogram/engine/renderer/mapRenderer.ts
+++ b/miniprogram/engine/renderer/mapRenderer.ts
@@ -23,7 +23,7 @@ export interface MapScene {
previewOriginX: number
previewOriginY: number
track: LonLatPoint[]
- gpsPoint: LonLatPoint
+ gpsPoint: LonLatPoint | null
gpsCalibration: MapCalibration
gpsCalibrationOrigin: LonLatPoint
osmReferenceEnabled: boolean
diff --git a/miniprogram/engine/renderer/webglVectorRenderer.ts b/miniprogram/engine/renderer/webglVectorRenderer.ts
index c422633..0d408f5 100644
--- a/miniprogram/engine/renderer/webglVectorRenderer.ts
+++ b/miniprogram/engine/renderer/webglVectorRenderer.ts
@@ -137,9 +137,15 @@ export class WebGLVectorRenderer {
this.pushCircle(positions, colors, point.x, point.y, 6.5, [0.97, 0.98, 0.95, 1], scene)
}
- this.pushCircle(positions, colors, gpsPoint.x, gpsPoint.y, this.gpsLayer.getPulseRadius(pulseFrame), [0.13, 0.62, 0.74, 0.22], scene)
- this.pushCircle(positions, colors, gpsPoint.x, gpsPoint.y, 13, [1, 1, 1, 0.95], scene)
- this.pushCircle(positions, colors, gpsPoint.x, gpsPoint.y, 9, [0.13, 0.63, 0.74, 1], scene)
+ if (gpsPoint) {
+ this.pushCircle(positions, colors, gpsPoint.x, gpsPoint.y, this.gpsLayer.getPulseRadius(pulseFrame), [0.13, 0.62, 0.74, 0.22], scene)
+ this.pushCircle(positions, colors, gpsPoint.x, gpsPoint.y, 13, [1, 1, 1, 0.95], scene)
+ this.pushCircle(positions, colors, gpsPoint.x, gpsPoint.y, 9, [0.13, 0.63, 0.74, 1], scene)
+ }
+
+ if (!positions.length) {
+ return
+ }
gl.viewport(0, 0, this.canvas.width, this.canvas.height)
gl.useProgram(this.program)
@@ -231,4 +237,3 @@ export class WebGLVectorRenderer {
}
}
}
-
diff --git a/miniprogram/pages/map/map.json b/miniprogram/pages/map/map.json
index d3aae06..b8be3f9 100644
--- a/miniprogram/pages/map/map.json
+++ b/miniprogram/pages/map/map.json
@@ -1,4 +1,4 @@
{
- "navigationBarTitleText": "地图",
+ "navigationStyle": "custom",
"disableScroll": true
}
diff --git a/miniprogram/pages/map/map.ts b/miniprogram/pages/map/map.ts
index 715f052..06f29fe 100644
--- a/miniprogram/pages/map/map.ts
+++ b/miniprogram/pages/map/map.ts
@@ -1,39 +1,107 @@
import { MapEngine, type MapEngineStageRect, type MapEngineViewState } from '../../engine/map/mapEngine'
import { loadRemoteMapConfig } from '../../utils/remoteMapConfig'
-
+type CompassTickData = {
+ angle: number
+ long: boolean
+ major: boolean
+}
+type CompassLabelData = {
+ text: string
+ angle: number
+ rotateBack: number
+ radius: number
+ className: string
+}
type MapPageData = MapEngineViewState & {
showDebugPanel: boolean
+ statusBarHeight: number
+ topInsetHeight: number
+ panelTimerText: string
+ panelMileageText: string
+ panelDistanceValueText: string
+ panelProgressText: string
+ panelSpeedValueText: string
+ compassTicks: CompassTickData[]
+ compassLabels: CompassLabelData[]
}
-
-const INTERNAL_BUILD_VERSION = 'map-build-99'
+const INTERNAL_BUILD_VERSION = 'map-build-106'
const REMOTE_GAME_CONFIG_URL = 'https://oss-mbh5.colormaprun.com/wxmini/test/game.json'
-
let mapEngine: MapEngine | null = null
-
+function buildCompassTicks(): CompassTickData[] {
+ const ticks: CompassTickData[] = []
+ for (let angle = 0; angle < 360; angle += 5) {
+ ticks.push({
+ angle,
+ long: angle % 15 === 0,
+ major: angle % 45 === 0,
+ })
+ }
+ return ticks
+}
+function buildCompassLabels(): CompassLabelData[] {
+ return [
+ { text: '\u5317', angle: 0, rotateBack: 0, radius: 68, className: 'compass-widget__mark--cardinal compass-widget__mark--north' },
+ { text: '\u4e1c\u5317', angle: 45, rotateBack: 0, radius: 58, className: 'compass-widget__mark--intermediate compass-widget__mark--northeast' },
+ { text: '\u4e1c', angle: 90, rotateBack: 0, radius: 68, className: 'compass-widget__mark--cardinal' },
+ { text: '\u4e1c\u5357', angle: 135, rotateBack: 0, radius: 58, className: 'compass-widget__mark--intermediate' },
+ { text: '\u5357', angle: 180, rotateBack: 0, radius: 68, className: 'compass-widget__mark--cardinal' },
+ { text: '\u897f\u5357', angle: 225, rotateBack: 0, radius: 58, className: 'compass-widget__mark--intermediate' },
+ { text: '\u897f', angle: 270, rotateBack: 0, radius: 68, className: 'compass-widget__mark--cardinal' },
+ { text: '\u897f\u5317', angle: 315, rotateBack: 0, radius: 58, className: 'compass-widget__mark--intermediate compass-widget__mark--northwest' },
+ ]
+}
function getFallbackStageRect(): MapEngineStageRect {
const systemInfo = wx.getSystemInfoSync()
- const width = Math.max(320, systemInfo.windowWidth - 20)
- const height = Math.max(280, Math.floor(systemInfo.windowHeight * 0.66))
+ const width = Math.max(320, systemInfo.windowWidth)
+ const height = Math.max(280, systemInfo.windowHeight)
return {
width,
height,
- left: 10,
+ left: 0,
top: 0,
}
}
Page({
- data: { showDebugPanel: false } as MapPageData,
+ data: {
+ showDebugPanel: false,
+ statusBarHeight: 0,
+ topInsetHeight: 12,
+ panelTimerText: '00:00:00',
+ panelMileageText: '0m',
+ panelDistanceValueText: '108',
+ panelProgressText: '0/14',
+ panelSpeedValueText: '0',
+ compassTicks: buildCompassTicks(),
+ compassLabels: buildCompassLabels(),
+ } as MapPageData,
onLoad() {
+ const systemInfo = wx.getSystemInfoSync()
+ const statusBarHeight = systemInfo.statusBarHeight || 0
+ const menuButtonRect = wx.getMenuButtonBoundingClientRect()
+ const menuButtonBottom = menuButtonRect && typeof menuButtonRect.bottom === 'number' ? menuButtonRect.bottom : statusBarHeight
+
mapEngine = new MapEngine(INTERNAL_BUILD_VERSION, {
onData: (patch) => {
this.setData(patch)
},
})
- this.setData({ ...mapEngine.getInitialData(), showDebugPanel: false })
+ this.setData({
+ ...mapEngine.getInitialData(),
+ showDebugPanel: false,
+ statusBarHeight,
+ topInsetHeight: Math.max(statusBarHeight + 12, menuButtonBottom + 20),
+ panelTimerText: '00:00:00',
+ panelMileageText: '0m',
+ panelDistanceValueText: '108',
+ panelProgressText: '0/14',
+ panelSpeedValueText: '0',
+ compassTicks: buildCompassTicks(),
+ compassLabels: buildCompassLabels(),
+ })
},
onReady() {
@@ -67,10 +135,10 @@ Page({
return
}
- const errorMessage = error && error.message ? error.message : '未知错误'
+ const errorMessage = error && error.message ? error.message : '鏈煡閿欒'
this.setData({
- configStatusText: `载入失败: ${errorMessage}`,
- statusText: `远程地图配置载入失败: ${errorMessage} (${INTERNAL_BUILD_VERSION})`,
+ configStatusText: `杞藉叆澶辫触: ${errorMessage}`,
+ statusText: `杩滅▼鍦板浘閰嶇疆杞藉叆澶辫触: ${errorMessage} (${INTERNAL_BUILD_VERSION})`,
})
})
},
@@ -99,7 +167,7 @@ Page({
const canvasRef = canvasRes[0] as any
if (!canvasRef || !canvasRef.node) {
page.setData({
- statusText: `WebGL 引擎初始化失败 (${INTERNAL_BUILD_VERSION})`,
+ statusText: `WebGL 寮曟搸鍒濆鍖栧け璐?(${INTERNAL_BUILD_VERSION})`,
})
return
}
@@ -109,7 +177,7 @@ Page({
currentEngine.attachCanvas(canvasRef.node, rect.width, rect.height, dpr)
} catch (error) {
page.setData({
- statusText: `WebGL 初始化失败 (${INTERNAL_BUILD_VERSION})`,
+ statusText: `WebGL 鍒濆鍖栧け璐?(${INTERNAL_BUILD_VERSION})`,
})
}
})
@@ -212,6 +280,14 @@ Page({
showDebugPanel: !this.data.showDebugPanel,
})
},
+
+ handleCloseDebugPanel() {
+ this.setData({
+ showDebugPanel: false,
+ })
+ },
+
+ handleDebugPanelTap() {},
})
@@ -223,29 +299,3 @@ Page({
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/miniprogram/pages/map/map.wxml b/miniprogram/pages/map/map.wxml
index 78a9650..d2f0ffd 100644
--- a/miniprogram/pages/map/map.wxml
+++ b/miniprogram/pages/map/map.wxml
@@ -1,180 +1,254 @@
-