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-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) const height = Math.max(280, systemInfo.windowHeight) return { width, height, left: 0, top: 0, } } Page({ 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, 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() { this.measureStageAndCanvas() this.loadMapConfigFromRemote() }, onUnload() { if (mapEngine) { mapEngine.destroy() mapEngine = null } }, loadMapConfigFromRemote() { const currentEngine = mapEngine if (!currentEngine) { return } loadRemoteMapConfig(REMOTE_GAME_CONFIG_URL) .then((config) => { if (mapEngine !== currentEngine) { return } currentEngine.applyRemoteMapConfig(config) }) .catch((error) => { if (mapEngine !== currentEngine) { return } const errorMessage = error && error.message ? error.message : '鏈煡閿欒' this.setData({ configStatusText: `杞藉叆澶辫触: ${errorMessage}`, statusText: `杩滅▼鍦板浘閰嶇疆杞藉叆澶辫触: ${errorMessage} (${INTERNAL_BUILD_VERSION})`, }) }) }, measureStageAndCanvas() { const page = this const applyStage = (rawRect?: Partial) => { const fallbackRect = getFallbackStageRect() const rect: MapEngineStageRect = { width: rawRect && typeof rawRect.width === 'number' ? rawRect.width : fallbackRect.width, height: rawRect && typeof rawRect.height === 'number' ? rawRect.height : fallbackRect.height, left: rawRect && typeof rawRect.left === 'number' ? rawRect.left : fallbackRect.left, top: rawRect && typeof rawRect.top === 'number' ? rawRect.top : fallbackRect.top, } const currentEngine = mapEngine if (!currentEngine) { return } currentEngine.setStage(rect) const canvasQuery = wx.createSelectorQuery().in(page) canvasQuery.select('#mapCanvas').fields({ node: true, size: true }) canvasQuery.exec((canvasRes) => { const canvasRef = canvasRes[0] as any if (!canvasRef || !canvasRef.node) { page.setData({ statusText: `WebGL 寮曟搸鍒濆鍖栧け璐?(${INTERNAL_BUILD_VERSION})`, }) return } const dpr = wx.getSystemInfoSync().pixelRatio || 1 try { currentEngine.attachCanvas(canvasRef.node, rect.width, rect.height, dpr) } catch (error) { page.setData({ statusText: `WebGL 鍒濆鍖栧け璐?(${INTERNAL_BUILD_VERSION})`, }) } }) } const query = wx.createSelectorQuery().in(page) query.select('.map-stage').boundingClientRect() query.exec((res) => { const rect = res[0] as WechatMiniprogram.BoundingClientRectCallbackResult | undefined applyStage(rect) }) }, handleTouchStart(event: WechatMiniprogram.TouchEvent) { if (mapEngine) { mapEngine.handleTouchStart(event) } }, handleTouchMove(event: WechatMiniprogram.TouchEvent) { if (mapEngine) { mapEngine.handleTouchMove(event) } }, handleTouchEnd(event: WechatMiniprogram.TouchEvent) { if (mapEngine) { mapEngine.handleTouchEnd(event) } }, handleTouchCancel() { if (mapEngine) { mapEngine.handleTouchCancel() } }, handleRecenter() { if (mapEngine) { mapEngine.handleRecenter() } }, handleRotateStep() { if (mapEngine) { mapEngine.handleRotateStep() } }, handleRotationReset() { if (mapEngine) { mapEngine.handleRotationReset() } }, handleSetManualMode() { if (mapEngine) { mapEngine.handleSetManualMode() } }, handleSetNorthUpMode() { if (mapEngine) { mapEngine.handleSetNorthUpMode() } }, handleSetHeadingUpMode() { if (mapEngine) { mapEngine.handleSetHeadingUpMode() } }, handleCycleNorthReferenceMode() { if (mapEngine) { mapEngine.handleCycleNorthReferenceMode() } }, handleAutoRotateCalibrate() { if (mapEngine) { mapEngine.handleAutoRotateCalibrate() } }, handleToggleGpsTracking() { if (mapEngine) { mapEngine.handleToggleGpsTracking() } }, handleToggleOsmReference() { if (mapEngine) { mapEngine.handleToggleOsmReference() } }, handleToggleDebugPanel() { this.setData({ showDebugPanel: !this.data.showDebugPanel, }) }, handleCloseDebugPanel() { this.setData({ showDebugPanel: false, }) }, handleDebugPanelTap() {}, })