. 地图绑定(闪烁根因入口)
trajectory.vue Lines 5-19 <map id="raceTrajMap" class="map" latitude="center.latitude" longitude="center.longitude" scale="scale" markers="markers" circles="circles" polyline="polylines" enable-satellite="satellite" show-location="false" enable-zoomenable-scroll
@markertap="onMarkerTap"
/>
要点:微信小程序 <map> 的 polyline 没有 Android 那种 Polyline.setPoints(),只能靠改 data 触发重绘。
- 播放主循环(每 tick 都会改 polyline)
trajectory.vue
Lines 888-918
toggleReplayPlayback() {
if (this.gcjPath.length < 2) return
this.replayPlaying = !this.replayPlaying
this.stopReplayTimer()
if (this.replayPlaying) {
if (this.playbackIndex >= this.gcjPath.length - 1) {
this.playbackIndex = 0
this.updateMapLayers()
}
if (!this.overviewSelected) {
this.followPlaybackCenter()
}
this.scheduleReplayTick()
}
},
scheduleReplayTick() {
this.stopReplayTimer()
const delay = Math.max(80, Math.round(BASE_TICK_MS / this.speedMul))
this.replayTimer = setTimeout(() => this.onReplayTick(), delay)
},
onReplayTick() {
if (!this.replayPlaying || this.gcjPath.length < 2) return
if (this.playbackIndex >= this.gcjPath.length - 1) {
this.stopReplay()
return
}
this.playbackIndex += 1
// 回放 tick 走轻量刷新,避免 markers/polyline 全量重建导致闪烁
this.updateReplayFrame(true)
this.scheduleReplayTick()
},
间隔:BASE_TICK_MS = 520,倍速 x2 时约 260ms 更新一次;x3 约 173ms。
- 每帧更新折线 + 游标(当前“防闪烁”实现)
},
syncTrackPolylinesToMap(subPath) {
if (!subPath.length || subPath.length < 2) {
this.trackPolylinePair = null
return []
}
if (!this.trackPolylinePair) {
this.trackPolylinePair = buildTrajectoryTrackPolylines(subPath)
} else {
syncTrajectoryTrackPolylinePoints(this.trackPolylinePair, subPath)
}
return this.trackPolylinePair
},
// ...
updateReplayFrame(followMap = true) {
const path = this.gcjPath
if (!path.length) return
const subPath = this.resolveTrackSubPath()
const trackPolylines = this.syncTrackPolylinesToMap(subPath)
this.polylines = [...this.coursePolylines, ...trackPolylines]
const cursorIdx = this.resolvePlaybackCursorIndex(path.length)
this.refreshPlaybackCursorMarker(cursorIdx)
if (followMap && !this.overviewSelected) {
this.followPlaybackCenter(cursorIdx)
}
},
工具函数:
raceTrajectoryMap.js
Lines 144-176
export function buildTrajectoryTrackPolylines(points) {
if (!Array.isArray(points) || points.length < 2) return []
const pts = [...points]
return [
{
points: pts,
color: TRAJECTORY_TRACK_OUTLINE_COLOR,
width: TRAJECTORY_POLYLINE_OUTLINE_WIDTH,
arrowLine: false,
},
{
points: pts,
color: TRAJECTORY_TRACK_COLOR,
width: TRAJECTORY_POLYLINE_WIDTH,
arrowLine: true,
},
]
}
export function syncTrajectoryTrackPolylinePoints(pair, points) {
if (!Array.isArray(points) || points.length < 2) return false
if (!Array.isArray(pair) || pair.length < 2) return false
const pts = [...points]
pair[0].points = pts
pair[1].points = pts
return true
}
1 个回复
Ask小助手 - Ask社区AI助手
从你的代码和描述来看,这是微信小程序 map 组件的已知问题。微信小程序
map的polyline每次数据更新都会触发整条线重绘,导致视觉上出现“闪烁”或“从无到有”的效果。你的代码已经做了很多优化尝试,比如复用
trackPolylinePair对象、直接修改内部points引用等,但问题根源在于微信小程序底层渲染机制。问题原因
微信小程序的
<map>组件对polyline的处理方式是:只要polyline数组的引用发生变化,或者内部对象的属性被检测到变化,就会对整个 polyline 进行重绘。不存在类似 Android 原生Polyline.setPoints()的增量更新方法。解决方案
方案一:降低更新频率(最直接有效)
你当前的基准间隔是 520ms,倍速后约 173ms-260ms 更新一次。可以尝试适当降低频率,减少重绘次数。
方案二:使用分段 polyline 替代单条线
将轨迹拆分成多段 polyline,已经绘制完成的部分不再变化,只更新最新的一段。这样已画好的部分不会被重绘。
已有资料中 ask 社区的讨论也印证了这个问题:uni-app map组件polyline 和markers 动态增加重绘问题,其中提到“数据变化轨迹会全部重绘显示,中间就有个无到有的看着像闪烁一样”。
方案三:使用双层 polyline 减少视觉闪烁
你代码中已经使用了双层 polyline(轮廓线 + 主线),这是一个好的做法。可以进一步尝试让轮廓线略宽于主线,利用轮廓线的存在掩盖主线重绘时的短暂消失。
方案四:插件市场方案
如果以上方案效果仍不理想,可以尝试插件市场的地图轨迹专用组件,它们可能采用了其他渲染策略:
uni.createMapContext的轨迹播放组件补充说明
这是微信小程序 map 组件的底层限制,在官方优化之前无法从根本上消除闪烁。以上方案主要是通过减少重绘频率和优化视觉效果来减轻闪烁感。如果对轨迹播放流畅度要求极高,可以考虑使用 WebView 内嵌高德/腾讯地图 JS API 来实现,但这会增加开发复杂度。
要回复问题请先登录或注册
公告
更多>相关问题