8.5 KiB
你是一个资深嵌入式 GUI 工程师,请用 LVGL 8.x(C/C++)实现一个“GNSS Sky Plot(卫星天空图)”页面。 屏幕分辨率:横屏 480(w) × 222(h)。 要求:严格按下面给出的像素布局绘制;不要自作主张改布局;不要改元素文案;颜色体系必须围绕主色 0xEBA341,并与暖色工程风格一致;所有控件必须可复用、可刷新数据。
============================================================
- 页面总体布局(像素级) ============================================================
-
页面根容器 root:尺寸 480×222,背景色为浅暖米色(见样式 token)。
-
分三块: A. 顶部 TopBar:高度 30px,占满宽 480 B. 内容区 Content:高度 222-30=192px,y=30
- 左侧 SkyPlotPanel:x=8, y=38, w=277, h=176
- 右侧 StatusPanel:x=293, y=38, w=179, h=176 注:Content 区顶部留 8px 间距,因此两个 panel 的 y=30+8=38;左右 panel 之间留 8px 间距。
-
全局圆角:8px
-
全局描边:2px(主色强调边)
============================================================ 2) 样式与颜色 token(必须使用,统一风格)
主色(Amber): #EBA341 (0xEBA341) 主色深(AmberDark): #C98118 背景(WarmBG): #F6E6C6 面板底(PanelBG): #FAF0D8 分隔线(Line): #E7C98F 文字主(Text): #6B4A1E 文字弱(TextDim): #8A6A3A 警告(Warn): #B94A2C 成功(Ok): #3E7D3E 信息蓝(Info): #2D6FB6
星座颜色(用于 SYS/图例): GPS: #E3B11F GLN: #2D6FB6 GAL: #3E7D3E BD: #B94A2C
SNR 状态颜色(用于点的外环/填充): SNR_GOOD:#3E7D3E SNR_FAIR:#8FBF4D SNR_WEAK:#C18B2C NOT_USED:#B94A2C IN_VIEW: #6E6E6E (灰)
字体:
- 标题/栏标题:20px(或 LVGL 内置近似字号)
- 表头:14px
- 列表内容:16px
- 底部 summary:14px
============================================================ 3) TopBar(高度30)
TopBar 容器:x=0,y=0,w=480,h=30,背景 WarmBG,底部分隔线 2px Line。 左侧标题:
- label_title:改为 Summary 文本: "USE: 7/18|HDOP: 1.6|FIX: 3D"
- USE/HDOP/FIX 三段使用不同颜色,整体与主题协调
右侧电量显示(仅占位,不实现电量算法):
- battery_icon:x=410,y=6,w=26,h=14,描边 2px TextDim,填充透明,右侧小凸点 3×6。
- label_batt:x=442,y=5,文本 "100%",色 TextDim,字号 18。
============================================================ 4) 左侧 SkyPlotPanel(x=8,y=38,w=292,h=176)
面板容器:
- panel_sky:圆角 10,背景 PanelBG,描边 2px AmberDark。
内部绘制一个“天空圆图”:
- 圆图外接正方形区域 sky_area:x=10,y=2,w=170,h=170(相对于 panel_sky) => 圆心 C = (10+85, 2+85) = (95,87) 相对 panel_sky 内部坐标 => 半径 R = 82(留出描边与文字空间)
绘制内容(使用 lv_canvas 或自绘对象都可以,但必须呈现): a) 外圆(地平线 0°):圆环描边 Line 2px b) 3 条同心圆(30°/60°/90°):
- r=R*2/3(约55)
- r=R*1/3(约27)
- r=0(中心点) 圆线使用 Line 1px 虚线效果(如做不到虚线,用细实线也可以) c) 十字方位线:N-S 与 E-W 两条线穿过圆心,线色 Line 1px d) 方位文字:
- "N" 放在圆上方:中心对齐于圆心x,y=2-2(贴近圆外)
- "E" 放右侧:x=10+170+8,y=95-10
- "W" 放左侧:x=2,y=95-10(在圆左边空白处) 文字色 Text,字号 18 e) 仰角刻度文字:
- 将刻度改为“指向 10 点半方向”:在圆心到 10:30 方向的斜线处依次标 "90°"(靠近外圈)、"60°"(r=55处)、"30°"(r=27处)
- 文本沿该斜线排列,整体视觉连线指向 10 点半方向 文字色 TextDim,字号 16 f) 圆心附近标注:
- label_horizon:放在圆心略下:文本 "0° Horizon",色 TextDim,字号 12
卫星点绘制(动态):
- 每颗卫星用一个小圆点对象 sat_dot(建议 lv_obj + 圆角=半径)
- 点半径:10px(直径20)
- 点内显示卫星 ID(两位或三位数字),文字白色或深棕(根据底色自动取对比度,优先白)
- 点的位置由 (azimuth, elevation) 映射到圆内: r = R * (1 - elevation/90) x = Cx + r * sin(azimuth) y = Cy - r * cos(azimuth) (azimuth: 0°=N, 90°=E)
- 点填充颜色:按星座(GPS/GLN/GAL/BD)
- 点外环/小标:按 SNR 状态(GOOD/FAIR/WEAK/NOT_USED/IN_VIEW):
- GOOD/FAIR/WEAK:用对应颜色做 2px 外环
- NOT_USED:外环 Warn
- IN_VIEW:外环 灰
- 若该卫星 used_in_fix=true,在点旁边增加小标签 "USE":
- use_tag:圆角 6,背景 Ok,文字白色,字号 12
- 位置:贴点左下角偏移(dx=-12, dy=12),避免遮挡数字
图例(在 SkyPlotPanel 内右下角区域):
- legend_sys(星座图例)放在圆图右侧、靠下:
- 小色块 10×10 + 文本(GPS/GLONASS/Galileo/BeiDou)
- 位置:x=190,y=105 起,行高 15
- legend_snr(SNR 图例)放在 legend_sys 上方、与其左对齐(SkyPlotPanel 右上角区域):
- 文本顺序: "SNR Good" "SNR Weak" "Not Used" "In View"
- 用小圆点示意(直径10)+ 文本
- 位置:x=190 起,纵向排布(行高 15),整体位于 legend_sys 上方;与 legend_sys 间距 6px;整体上移 30px;小圆点与文字排布规则同 legend_sys(色块 y+4,文字 x+14)
- 文本色 TextDim,字号 12
============================================================ 5) 右侧 StatusPanel(x=293,y=38,w=179,h=176)
面板容器:
- panel_status:圆角 10,背景 PanelBG,描边 2px AmberDark
标题条(高度 26):
- header:x=0,y=0,w=179,h=26,背景 Amber,圆角上半部保持
- label:居中 "SATELLITE STATUS",文字色 #2A1A05,字号 14 加粗
表头行(高度 22,y=26):
- 背景:#F2D9A5
- 列:ID / SYS / ELEV / SNR / USE
- 列宽(像素):ID=24, SYS=38, ELEV=39, SNR=38, USED=39(ELEV=USED,SNR=SYS)
- 文本居中,色 TextDim,字号 12
数据列表区(y=48 到 y=176,高度 128):
- 以“固定行高”方式渲染,行高 17px,可显示 7 行(剩余滚动/分页不实现也可,但必须结构预留)
- 每行 5 列对齐表头
- 行底部分隔线 1px Line
- SYS 文本颜色按星座色(GPS/GLN/GAL/BD)
- USED 列:若 used=true 显示 "YES" 颜色 Ok;否则 "NO" 颜色 Warn
- 其它列文字色 Text
- 当卫星数量超过可显示行数时,列表按以下优先级排序显示:USED=YES 优先,SNR 高优先,其次仰角高,再按 PRN/SVID 升序
底部 Summary 区移除,空间全部让给数据列表区
============================================================ 6) 数据结构与刷新接口(必须提供)
定义数据结构(示例):
-
struct SatInfo { int id; // PRN/SVID enum Sys {GPS, GLN, GAL, BD} sys; float azimuth; // 0..359 deg float elevation; // 0..90 deg int snr; // dB-Hz bool used; enum SNRState {GOOD, FAIR, WEAK, NOT_USED, IN_VIEW} snr_state; };
-
struct GnssStatus { int sats_in_use; int sats_in_view; float hdop; enum Fix {NOFIX, FIX2D, FIX3D} fix; };
必须实现两个刷新函数(供上层调用):
- void ui_gnss_skyplot_set_sats(const SatInfo* sats, int count); -> 更新圆图卫星点(创建/复用对象),更新右侧表格前 N 行
- void ui_gnss_skyplot_set_status(GnssStatus st); -> 更新底部 summary 文本与 FIX 颜色
============================================================ 7) 交互(最小)
- 左上角允许预留 Back 按钮位置(但本需求不必须实现)。
- 页面不需要触摸交互;仅需要刷新显示。
- Backspace 键行为:触发 TopBar 的 Back 按钮逻辑,与其它页面一致。
============================================================ 8) 交付物要求
- 提供一个函数 ui_gnss_skyplot_create(lv_obj_t* parent) 返回页面根对象。
- 所有对象指针保存在静态/结构体中,支持重复进入页面不泄漏。
- 不要使用外部图片资源;全部用 LVGL 绘制。
- 输出代码应可直接编译(伪代码不接受)。
按以上要求生成完整 LVGL 页面代码。