15 KiB
天气组件视觉重构 Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 彻底重构阑山桌面天气系列组件的背景视觉和文字排版,为每种图标风格(Google Weather / Geometric / Breezy / Lemon)提供独立的背景配色和视觉质感,参考各天气 App 的 Material Design 风格,实现几何质感+柔和渐变+层次分明的排版。
Architecture: 保留现有数据层(WeatherWidgetBase、WeatherSnapshot、WeatherIconAssetResolver)和组件注册机制不变。核心改动:1) 将 MaterialWeatherVisualTheme.ResolvePalette() 扩展为按 styleId 分派不同配色方案;2) 重构 MaterialWeatherSceneControl 为按 styleId 渲染不同背景风格;3) 改进各天气 Widget 的文字排版层次。先创建 HTML Mock 验证视觉效果。
Tech Stack: Avalonia UI (XAML + C# code-behind)、HTML/CSS (Mock 预览)
当前状态分析
现有天气组件体系
5 个天气组件,全部继承自 WeatherWidgetBase:
| 组件 | 文件 | 功能 |
|---|---|---|
| WeatherWidget | WeatherWidget.axaml(.cs) |
基础天气:温度+状况+图标+位置 |
| WeatherClockWidget | WeatherClockWidget.axaml(.cs) |
天气+时钟 |
| ExtendedWeatherWidget | ExtendedWeatherWidget.axaml(.cs) |
扩展天气:含指标/小时/多日预报 |
| HourlyWeatherWidget | HourlyWeatherWidget.axaml(.cs) |
逐小时天气 |
| MultiDayWeatherWidget | MultiDayWeatherWidget.axaml(.cs) |
多日天气 |
核心问题
- 背景与图标风格脱钩:
MaterialWeatherVisualTheme.ResolvePalette()只返回一套配色,与WeatherVisualStyleId(GoogleWeatherV4/Geometric/Breezy/LemonFlutter)完全无关。切换图标风格时背景不变。 - 背景视觉单调:
MaterialWeatherSceneControl只有一种手绘几何风格(椭圆+云+雨滴),质感差,缺乏各 App 的特色。 - 文字排版粗糙: 温度数字不够大,信息层次不分明,指标用纯文字堆叠,预报区域无卡片样式。
- 半透明遮罩硬编码: 所有组件都覆盖
<Border Background="#30FFFFFF" />等硬编码遮罩,不随风格变化。
各天气 App 风格特征
Google Weather (v4):
- 背景:大面积柔和蓝白渐变,晴天偏暖黄蓝,雨天偏深蓝灰
- 装饰:极简,几乎无几何装饰,纯靠渐变色彩表现天气氛围
- 排版:温度超大(72px+),天气状况中等,位置小字
Geometric Weather (几何天气):
- 背景:深色系渐变(深蓝/深紫/深灰),搭配半透明几何圆形装饰
- 装饰:大面积半透明圆形叠加,营造深度感
- 排版:紧凑信息密度,指标用小标签
Breezy Weather (微风天气):
- 背景:清新渐变(浅蓝/浅绿/浅紫),比 Geometric 更明亮
- 装饰:柔和波浪线条 + 少量几何装饰,Material Design 风格
- 排版:卡片式预报,圆角芯片
Lemon Weather (柠檬天气):
- 背景:暖色系渐变(橙黄/粉紫/暖蓝),柠檬2偏扁平,柠檬3偏Material
- 装饰:天气场景装饰(太阳光芒/云朵轮廓/雨丝),更有场景感
- 排版:温度超大,天气图标突出
设计方案
视觉论文 (Visual Thesis)
每种图标风格拥有独特的背景渐变配色和几何装饰语言——Google 纯净渐变、Geometric 深色几何、Breezy 清新波浪、Lemon 暖色场景——配合超大温度数字和层次分明的排版,在桌面小组件空间内实现 Material Design 的几何质感。
配色方案设计
每种风格 × 每种天气条件 × 昼夜 = 独立配色。以下为关键配色定义:
Google Weather 风格
| 天气 | 白天 Top→Bottom | 夜晚 Top→Bottom |
|---|---|---|
| Clear | #4FC3F7 → #B3E5FC | #0D47A1 → #1A237E |
| PartlyCloudy | #81D4FA → #E1F5FE | #1565C0 → #283593 |
| Cloudy | #90A4AE → #CFD8DC | #37474F → #455A64 |
| Rain | #78909C → #B0BEC5 | #263238 → #37474F |
| Storm | #546E7A → #78909C | #1A1A2E → #263238 |
| Snow | #E1F5FE → #FFFFFF | #1A237E → #283593 |
| Fog/Haze | #B0BEC5 → #ECEFF1 | #455A64 → #546E7A |
Geometric 风格
| 天气 | 白天 Top→Bottom | 夜晚 Top→Bottom |
|---|---|---|
| Clear | #1A237E → #3949AB | #0A0E27 → #1A1A3E |
| PartlyCloudy | #283593 → #5C6BC0 | #0D1033 → #1E1E4A |
| Cloudy | #37474F → #607D8B | #1A1A2E → #2D2D44 |
| Rain | #1A237E → #3F51B5 | #0A0E27 → #1A1A3E |
| Storm | #1A1A2E → #3F51B5 | #050510 → #1A1A2E |
| Snow | #E8EAF6 → #C5CAE9 | #1A237E → #283593 |
| Fog/Haze | #455A64 → #78909C | #1A1A2E → #37474F |
Breezy 风格
| 天气 | 白天 Top→Bottom | 夜晚 Top→Bottom |
|---|---|---|
| Clear | #4DD0E1 → #80DEEA | #006064 → #00838F |
| PartlyCloudy | #4FC3F7 → #B2EBF2 | #00695C → #00897B |
| Cloudy | #80CBC4 → #B2DFDB | #37474F → #546E7A |
| Rain | #4DB6AC → #80CBC4 | #004D40 → #00695C |
| Storm | #26A69A → #4DB6AC | #1A1A2E → #004D40 |
| Snow | #E0F7FA → #FFFFFF | #006064 → #00838F |
| Fog/Haze | #80CBC4 → #E0F7FA | #37474F → #546E7A |
Lemon 风格
| 天气 | 白天 Top→Bottom | 夜晚 Top→Bottom |
|---|---|---|
| Clear | #FFB74D → #FFF176 | #1A237E → #311B92 |
| PartlyCloudy | #FF8A65 → #FFCC80 | #283593 → #4A148C |
| Cloudy | #BCAAA4 → #D7CCC8 | #37474F → #4E342E |
| Rain | #90A4AE → #B0BEC5 | #1A1A2E → #311B92 |
| Storm | #78909C → #90A4AE | #0D0D1A → #1A1A2E |
| Snow | #FFF9C4 → #FFFFFF | #1A237E → #311B92 |
| Fog/Haze | #D7CCC8 → #EFEBE9 | #4E342E → #5D4037 |
排版改进方案
- 温度超大化: 温度字号从 56-58px 提升到 64-72px(基础组件),形成视觉锚点
- 层次分明: 温度 → 天气状况 → 位置/指标,字号递减,透明度递减
- 指标标签化: 湿度/风速/AQI 用半透明圆角标签展示,而非纯文字
- 预报芯片化: 小时/每日预报用圆角半透明芯片卡片
- 图标间距: 天气图标与文字之间增加 8-12px 间距
文件变更清单
| 文件 | 操作 | 说明 |
|---|---|---|
Views/Components/MaterialWeatherVisualTheme.cs |
修改 | 扩展 ResolvePalette 支持 styleId 分派,新增4套风格配色 |
Views/Components/MaterialWeatherSceneControl.cs |
修改 | 按 styleId 渲染不同背景风格(纯渐变/深色几何/清新波浪/暖色场景) |
Views/Components/WeatherWidgetBase.cs |
修改 | 传递 styleId 到 SceneControl.Apply(),移除硬编码遮罩 |
Views/Components/WeatherWidget.axaml |
修改 | 改进排版层次,移除硬编码遮罩 |
Views/Components/WeatherWidget.axaml.cs |
修改 | 适配新排版 |
Views/Components/WeatherClockWidget.axaml |
修改 | 改进排版,移除硬编码遮罩 |
Views/Components/WeatherClockWidget.axaml.cs |
修改 | 适配新排版 |
Views/Components/ExtendedWeatherWidget.axaml |
修改 | 改进排版,指标标签化,预报芯片化 |
Views/Components/ExtendedWeatherWidget.axaml.cs |
修改 | 适配新排版+标签+芯片 |
Views/Components/HourlyWeatherWidget.axaml |
修改 | 改进排版,预报芯片化 |
Views/Components/HourlyWeatherWidget.axaml.cs |
修改 | 适配新排版+芯片 |
Views/Components/MultiDayWeatherWidget.axaml |
修改 | 改进排版 |
Views/Components/MultiDayWeatherWidget.axaml.cs |
修改 | 适配新排版 |
mocks/weather-widget-mock.html |
新建 | HTML Mock 预览(4种风格×2种天气×2种主题) |
Task 分解
Task 1: 创建 HTML Mock 预览
Files:
-
Create:
mocks/weather-widget-mock.html -
Step 1: 创建 HTML Mock 文件
创建完整的 HTML Mock,包含:
-
4 种风格(Google / Geometric / Breezy / Lemon)× 2 种天气(晴/雨)× 2 种主题(亮/暗)
-
每种风格展示基础天气组件(温度+状况+图标+位置)
-
改进后的排版:超大温度、层次分明、指标标签化
-
亮色/暗色主题切换按钮
-
Step 2: 在浏览器中打开 Mock 验证效果
Run: start mocks/weather-widget-mock.html
Task 2: 扩展 MaterialWeatherVisualTheme 支持多风格配色
Files:
-
Modify:
LanMountainDesktop/Views/Components/MaterialWeatherVisualTheme.cs -
Step 1: 修改 ResolvePalette 方法签名
将 ResolvePalette(MaterialWeatherCondition condition, bool isNight) 改为 ResolvePalette(string? styleId, MaterialWeatherCondition condition, bool isNight),内部按 styleId 分派到不同配色方案。
- Step 2: 新增 Google Weather 配色表
为 GoogleWeatherV4 风格定义所有天气条件×昼夜的配色(参考上面配色方案设计章节)。
- Step 3: 新增 Geometric 配色表
为 Geometric 风格定义深色系配色。
- Step 4: 新增 Breezy 配色表
为 Breezy 风格定义清新渐变配色。
- Step 5: 新增 Lemon 配色表
为 LemonFlutter 风格定义暖色系配色。
- Step 6: 更新所有调用点
将所有 ResolvePalette(condition, isNight) 调用改为 ResolvePalette(styleId, condition, isNight)。
Task 3: 重构 MaterialWeatherSceneControl 支持多风格背景
Files:
-
Modify:
LanMountainDesktop/Views/Components/MaterialWeatherSceneControl.cs -
Step 1: 扩展 Apply 方法签名
将 Apply(MaterialWeatherCondition condition, MaterialWeatherPalette palette, bool isLive) 改为 Apply(string? styleId, MaterialWeatherCondition condition, MaterialWeatherPalette palette, bool isLive),存储 styleId。
- Step 2: 实现 Google Weather 风格渲染
纯渐变背景,无几何装饰。背景使用 palette 的 BackgroundTop→BackgroundBottom 渐变。仅保留天气特效(雨滴/雪花/雾线)。
- Step 3: 实现 Geometric 风格渲染
深色渐变 + 大面积半透明几何圆形叠加。在基础渐变上叠加 2-3 个大椭圆(使用 palette 的 PrimaryShape/SecondaryShape/AccentShape),营造深度感。保留天气特效。
- Step 4: 实现 Breezy 风格渲染
清新渐变 + 柔和波浪线条。在基础渐变上绘制 2-3 条正弦波浪线(使用 palette 的 SurfaceTint),营造微风感。保留天气特效。
- Step 5: 实现 Lemon 风格渲染
暖色渐变 + 天气场景装饰。晴天绘制太阳光芒(放射线),多云绘制云朵轮廓,雨天绘制雨丝。保留天气特效。
- Step 6: 更新所有调用点
将所有 SceneControl.Apply(condition, palette, isLive) 改为 SceneControl.Apply(styleId, condition, palette, isLive)。
Task 4: 更新 WeatherWidgetBase 传递 styleId
Files:
-
Modify:
LanMountainDesktop/Views/Components/WeatherWidgetBase.cs -
Step 1: 修改 ApplyCurrentScene 方法
在 ApplyCurrentScene() 中将 CurrentVisualStyleId 传递给 SceneControl.Apply()。
- Step 2: 修改 ApplySnapshot 中的 ResolvePalette 调用
将 MaterialWeatherVisualTheme.ResolvePalette(CurrentCondition, isNight) 改为 MaterialWeatherVisualTheme.ResolvePalette(CurrentVisualStyleId, CurrentCondition, isNight)。
Task 5: 改进各天气 Widget 的 XAML 排版
Files:
-
Modify:
WeatherWidget.axaml— 移除硬编码遮罩<Border Background="#30FFFFFF" />,改用 palette 驱动的半透明遮罩 -
Modify:
WeatherClockWidget.axaml— 同上 -
Modify:
ExtendedWeatherWidget.axaml— 同上 + 指标区域改用标签样式 -
Modify:
HourlyWeatherWidget.axaml— 同上 + 预报区域改用芯片样式 -
Modify:
MultiDayWeatherWidget.axaml— 同上 -
Step 1: 移除所有硬编码遮罩
将 <Border Background="#30FFFFFF" /> / #42FFFFFF / #34FFFFFF / #38FFFFFF / #3CFFFFFF 替换为 <Border x:Name="OverlayBorder" />,在 code-behind 中根据 palette 设置遮罩颜色。
- Step 2: 改进 WeatherWidget 排版
增大温度字号(58→64),增加图标与文字间距,调整位置文字透明度。
- Step 3: 改进 WeatherClockWidget 排版
增大时钟字号,增加天气信息与时间间距。
- Step 4: 改进 ExtendedWeatherWidget 排版
指标用半透明圆角标签,小时/每日预报用圆角芯片卡片。
- Step 5: 改进 HourlyWeatherWidget 排版
预报区域用圆角芯片卡片样式。
- Step 6: 改进 MultiDayWeatherWidget 排版
每日预报行增加分隔线和更好的间距。
Task 6: 更新各天气 Widget 的 code-behind
Files:
-
Modify: 所有天气 Widget 的
.axaml.cs文件 -
Step 1: 更新 WeatherWidget.axaml.cs
-
设置 OverlayBorder 背景
-
增大温度字号
-
适配新排版参数
-
Step 2: 更新 WeatherClockWidget.axaml.cs
-
设置 OverlayBorder 背景
-
适配新排版
-
Step 3: 更新 ExtendedWeatherWidget.axaml.cs
-
设置 OverlayBorder 背景
-
指标标签化(CreateMetric 改为带圆角背景的标签)
-
预报芯片化
-
Step 4: 更新 HourlyWeatherWidget.axaml.cs
-
设置 OverlayBorder 背景
-
预报芯片化(CreateChip 改为带圆角背景的芯片)
-
Step 5: 更新 MultiDayWeatherWidget.axaml.cs
-
设置 OverlayBorder 背景
-
适配新排版
Task 7: 验证与测试
- Step 1: 运行项目查看效果
Run: dotnet run --project LanMountainDesktop/LanMountainDesktop.csproj
- Step 2: 运行相关测试
Run: dotnet test LanMountainDesktop.slnx -c Debug
- Step 3: 检查圆角规范合规
确认所有组件 RootBorder 使用 DesignCornerRadiusComponent,新增的标签/芯片使用 DesignCornerRadiusSm/DesignCornerRadiusMd。
假设与决策
- 4 套独立风格: 每种图标风格对应独立的背景配色和装饰风格,切换图标风格时背景也跟着变
- 配色表驱动: 所有颜色定义在
MaterialWeatherVisualTheme中,不硬编码到 SceneControl - 保留天气特效: 雨滴/雪花/雾线/闪电等天气特效在所有风格中保留,但颜色跟随 palette
- 遮罩动态化: 半透明遮罩颜色从 palette 中派生,而非硬编码
#30FFFFFF - 排版渐进改进: 不做大规模 XAML 重构,而是在现有结构上优化字号/间距/透明度
- 数据层不变: WeatherSnapshot、WeatherIconAssetResolver、WeatherWidgetBase 的数据逻辑不变
- 接口兼容: IDesktopComponentWidget 等接口实现不变
验证步骤
- HTML Mock 在浏览器中展示 4 种风格效果满意
- Avalonia 项目编译通过
- 运行项目,切换图标风格时背景配色和装饰风格跟着变化
- 亮色/暗色主题切换正常
- 5 个天气组件排版层次分明
- 指标标签化和预报芯片化正常显示
- 测试通过