news 2026/10/5 20:10:48

悬停以后行程卡片跑位了,折叠屏旅行图鉴如何保存地图视口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
悬停以后行程卡片跑位了,折叠屏旅行图鉴如何保存地图视口

折叠屏从展开态切到悬停态,旅行地图通常会从左右并排改成上下分区。第一版把选中站点和地图偏移都留在页面局部,窗口一变化,白崖灯塔的标记又回到默认位置,右侧行程卡也跟着跳回第一天。

折叠屏旅行图鉴的界面有 DAY 1~DAY 3、雾港车站到落日营地的时间线,以及可缩放的路线画布。这里最需要保住的是“正在看哪一天、选中哪个站点、地图停在哪儿”,而不是某一种布局的像素位置。

把行程和视口拆成两份状态

行程选择属于业务状态,视口属于交互状态。它们都应该跨布局保留,但各自的保存规则不同。

exportinterfaceTripStop{id:stringdayId:stringtitle:stringtime:stringcoordinate:{x:number,y:number}}exportinterfaceMapViewport{scale:numberoffsetX:numberoffsetY:number}exportinterfaceTripWorkspace{selectedDayId:stringselectedStopId:stringviewport:MapViewport posture:'compact'|'halfFolded'|'expanded'}

站点坐标是地图坐标,不随窗口宽度变化。offsetX与offsetY保存用户平移后的画布位置;折叠屏改变姿态时,布局只改变地图容器大小,不重置这份视口状态。

点击站点时不要按数组下标保存

时间线可能按日期过滤,也可能把已完成站点收起。用selectedStop: number会让“第二项”在过滤后指向另一处地点。

exportclassTripController{privatestops:TripStop[]=[]workspace:TripWorkspace={selectedDayId:'day-1',selectedStopId:'',viewport:{scale:1,offsetX:0,offsetY:0},posture:'expanded'}selectStop(stopId:string):boolean{conststop=this.stops.find((item:TripStop)=>item.id===stopId)if(!stop)returnfalsethis.workspace.selectedStopId=stop.idthis.workspace.selectedDayId=stop.dayIdreturntrue}visibleStops():TripStop[]{returnthis.stops.filter((item:TripStop)=>item.dayId===this.workspace.selectedDayId)}}

ForEach同样传入stop.id作为键。站点列表重新排序后,正在探索的橙色标记仍落在同一个地点。

姿态变化只重排区域

悬停态不该创建第二份地图组件状态。页面根据姿态决定时间线和地图的排列方向,控制器始终使用同一个workspace。

@BuildertripBody(){if(this.workspace.posture==='expanded'){Row({space:18}){this.stopTimeline(this.visibleStops())this.mapPanel(this.workspace.viewport)}.height('100%')}else{Column({space:14}){this.mapPanel(this.workspace.viewport)this.stopTimeline(this.visibleStops())}.height('100%')}}

地图组件不读取selectedDay的数组位置,只根据selectedStopId高亮目标。时间线放到下半屏时,白崖灯塔仍保持原来的选中状态。

手势坐标需要换算回地图坐标

缩放后的拖动距离不能直接写入偏移。将屏幕位移除以缩放倍数,再更新视口,放大后手指移动 20 像素才不会让地图飞出很远。

functionclamp(value:number,min:number,max:number):number{returnMath.max(min,Math.min(max,value))}exportfunctionpan(viewport:MapViewport,dx:number,dy:number):MapViewport{return{...viewport,offsetX:viewport.offsetX+dx/viewport.scale,offsetY:viewport.offsetY+dy/viewport.scale}}exportfunctionzoomAt(viewport:MapViewport,focusX:number,focusY:number,nextScale:number):MapViewport{constscale=clamp(nextScale,0.7,2.6)constmapX=(focusX-viewport.offsetX)/viewport.scaleconstmapY=(focusY-viewport.offsetY)/viewport.scalereturn{scale,offsetX:focusX-mapX*scale,offsetY:focusY-mapY*scale}}

zoomAt让手势焦点停在原处。无论用户在展开态还是悬停态调整地图,视觉上都像在同一张地图上继续操作。

交通凭证与行程选择分离

页面中的登乘凭证开关只决定凭证是否展开,不应覆盖当前站点。恢复页面时,单独保存这类短暂状态即可。

exportinterfaceTripSnapshot{selectedDayId:stringselectedStopId:stringviewport:MapViewport passOpen:boolean}exportfunctionrestore(snapshot:TripSnapshot,stops:TripStop[]):TripWorkspace{constselected=stops.some((item:TripStop)=>item.id===snapshot.selectedStopId)return{selectedDayId:selected?snapshot.selectedDayId:'day-1',selectedStopId:selected?snapshot.selectedStopId:(stops[0]?.id??''),viewport:snapshot.viewport,posture:'expanded'}}

当前旅行数据为本地行程。后续接入地图服务或折叠状态接口时,接口层只负责提供坐标和姿态变化;行程选择、视口换算与恢复逻辑继续由本地状态层处理。卡片无论移到上半屏还是侧栏,都不会失去用户刚才看到的位置。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 20:04:25

Mac UltraEdit 16 Registration 后,把授权配置改到 TaoToken 的完整记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 20:02:30

Kamailio select框架实战:从核心语法到SIP路由与状态查询

我最早接触 Kamailio 的 select 框架,是在一个深夜排查电话路由问题的现场。当时要做一个很简单的判断:如果请求的 SIP URI 里带了某个自定义参数,就转给特定网关,否则走默认中继。用伪变量(PV)写条件判断虽…

作者头像 李华
网站建设 2026/10/5 19:42:56

iOS快照测试实战指南:从原理到CI集成与踩坑记录

先说个每天都在发生的场景:你改了一个按钮的圆角,或者调了一个 cell 的间距,代码 review 时没人发现问题,因为差异在视觉层面实在太细微了。用户却在版本更新后说“这个界面看起来怪怪的”。这种问题你想靠什么手段拦住&#xff1…

作者头像 李华
网站建设 2026/10/5 19:23:20

OpenClaw02_基础知识手册:openclaw.json 与 workspace 配置入门

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华