Architecture
Fenix8V3View had grown to 632 lines mixing layout constants, font
metrics, icon drawing, data lookup and orchestration. Split into:
Layout the 500-canvas constants, scaling, font choice and text drawing
Icons the three bitmap icons plus the primitive glyphs
Settings every stored preference and its default, in one place
Fields unchanged in scope, but value() is now seven category
functions that each return null for ids they do not own --
the ids interleave, so dispatching on ranges does not work
View what is left: the drawing order
The view is down to 359 lines and no longer reaches for a property or a
font metric directly.
Verification
Added a harness that walks all 75 ids in the simulator and reports each
rendered value with its pixel width. It caught a real one: pushDistance
and pushes compile on every device but throw "Symbol Not Found" at
runtime on a fenix 8 -- they are wheelchair counters that only some
firmware carries. Every optional ActivityMonitor, UserProfile, Weather
and Activity member is now behind a `has` check.
The same run showed two date fields overflowing their slot, so long
values now step down a font size rather than running into the ring.
Always-on mode checked against the simulator's Always-On display mode:
band fill gone, unlit ticks gone, slots hidden, time and date dimmed.
Also: Chinese "Day Date" was missing its 日, since it built the string by
hand instead of going through the localised date format.
All 17 devices build.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
332 lines
19 KiB
Markdown
332 lines
19 KiB
Markdown
# Fenix 8 V3 — Garmin 数据表盘
|
||
|
||
按 `watchface-kit` 设计稿 1:1 还原的多指标数据表盘。设计画布 **500×500**,渲染时按屏宽等比缩放 `s = screenWidth / 500`,支持圆形 AMOLED(Fenix 8 / Epix 2 / Venu 3 等)与圆屏 MIP(Fenix 7 / Enduro 3 / FR255 等)共 17 款设备。
|
||
|
||
- **SDK**:Connect IQ SDK 9.1.0(`monkeyc` 9.1.0,`minSdkVersion="4.2.0"`)
|
||
- **语言**:Monkey C;界面文案含英文与简体中文
|
||
- **类型**:`watchface`
|
||
- **应用 ID**:`f8a3c1b2c3d44e5f8a9b0c1d2e3f4a5b`
|
||
|
||
设计稿本体(7 张 SVG + tokens + 逆向脚本)在 `design/`,是本仓库所有坐标与配色的唯一来源。
|
||
|
||
---
|
||
|
||
## 1. 目录结构
|
||
|
||
```
|
||
fenix8v3-watchface/
|
||
├── manifest.xml # 应用清单(ID / 支持设备 / 语言)
|
||
├── monkey.jungle # 构建配置
|
||
├── design/ # ⭐ 设计稿原件(唯一事实来源)
|
||
│ ├── watchface-0N-*.svg # 7 套主题的矢量还原稿
|
||
│ ├── watchface-tokens.json # 配色 token
|
||
│ └── rebuild.py # 原作者从位图逆向出 SVG 的脚本(仅存档,不参与构建)
|
||
├── tools/
|
||
│ ├── gen_themes.py # design/*.svg -> source/Themes.mc
|
||
│ ├── gen_fields.py # 字段表 -> FieldTable.mc + settings.xml + 两种语言文案
|
||
│ ├── gen_icons.py # design/*.svg -> 各尺寸图标位图 + 启动图标
|
||
│ └── gen_preview_svg.py # source/Themes.mc -> preview-themes.svg + preview.html
|
||
├── source/
|
||
│ ├── Fenix8V3App.mc # 应用入口(12 行壳子)
|
||
│ ├── Fenix8V3View.mc # 绘制顺序:进度环 / 各元素 / 常亮模式
|
||
│ ├── Layout.mc # 500 画布常量、缩放、字号选择、文字绘制
|
||
│ ├── Icons.mc # 图标:位图三件套 + 其余图元
|
||
│ ├── Fields.mc # 75 项数据字段的取值与格式化
|
||
│ ├── Settings.mc # 所有设置项的读取与默认值
|
||
│ ├── FieldTable.mc # ⚠️ 自动生成:字段 id 表
|
||
│ └── Themes.mc # ⚠️ 自动生成:七套主题配色
|
||
├── resources/ # 英文文案 + 设置项定义(部分自动生成)
|
||
├── resources-chn/ # 简体中文文案
|
||
├── resources-icons-<宽度>/ # ⚠️ 自动生成:按屏幕尺寸光栅化的图标
|
||
├── resources-launcher-<尺寸>/ # ⚠️ 自动生成:各尺寸启动图标
|
||
└── bin/ # 编译产物(已 gitignore)
|
||
```
|
||
|
||
重新生成全部派生文件:
|
||
|
||
```bash
|
||
python3 tools/gen_themes.py && python3 tools/gen_fields.py \
|
||
&& python3 tools/gen_icons.py && python3 tools/gen_preview_svg.py
|
||
```
|
||
|
||
三份渲染实现(表盘 / SVG 预览 / HTML 预览)只有 **一份颜色数据**:`Themes.mc`。预览脚本直接解析它,不会与固件漂移。字段表、设置项、两种语言的文案同样只有 `tools/gen_fields.py` 里那一张表。
|
||
|
||
---
|
||
|
||
## 1.5 代码结构
|
||
|
||
一句话:**位置归 `Layout`,内容归 `Fields`,配色归 `Themes`,设置归 `Settings`,`Fenix8V3View` 只剩画的顺序。**
|
||
|
||
| 模块 | 负责 | 不负责 |
|
||
|------|------|--------|
|
||
| `Layout` | 500 基准画布的全部坐标常量、`px()` 缩放、极坐标换算、字号选择与自动缩字、渐变文字的分带绘制 | 具体画什么 |
|
||
| `Icons` | 三个位图图标的加载与染色、电池、蓝牙、其余数据项的图元 | 图标该出现在哪个数据位(由字段 id 决定,但查表在这里) |
|
||
| `Fields` | 75 项字段的取值、单位换算、本地化文案(星期/月份/标签) | 排版 |
|
||
| `Settings` | 每个设置项的读取与默认值,包含空值回退 | 设置项的 UI 定义(在 `settings.xml`) |
|
||
| `Fenix8V3View` | `onUpdate` 的绘制顺序、进度环、常亮模式 | 以上任何一项的细节 |
|
||
|
||
`Fields.value()` 按分类拆成 7 个函数(`dateTime` / `activity` / `body` / `system` / `environment` / `weather` / `custom`),每个在不认识 id 时返回 `null`,`value()` 依次尝试。id 是交错的(1、2、3 是活动,8、11、12 是身体,14 又是活动),所以按区间派发行不通。
|
||
|
||
`Fields.Ctx` 每次绘制构造一个,把 `ActivityMonitor` / `Weather` / `UserProfile` / `SensorHistory` 的查询**懒加载并缓存**——四个数据位可能都要天气,但只查一次;没有数据位用到 `UserProfile` 时就完全不查。
|
||
|
||
|
||
## 2. 布局(500 基准,取自设计稿 SVG 路径的墨迹包围盒)
|
||
|
||
| 元素 | 位置 | 说明 |
|
||
|------|------|------|
|
||
| 进度环 | 内半径 `231.09`,外半径 `249.10` | 见 §3 |
|
||
| 电量图标 | `x=192.70`,`cy=53.20`,`26.20×17.81` | 圆角外框 + 按电量填充 + 右侧触点 |
|
||
| 电量数值 | 左对齐 `x=232.00` | `NN%` |
|
||
| 上方双数据 | 图标 `cy=90`,数值 `cy=131.06`;左 `x=157.00`,右 `x=343.70` | 居中对齐 |
|
||
| 时间 | `cy=221.10`;小时右对齐 `x=211.40`,分钟左对齐 `x=276.02` | 竖向渐变,见 §4 |
|
||
| 冒号 | `x=237.88`,`24.24×21.30`,`y=183.68 / 234.57` | 两块矩形 |
|
||
| 日期带 | `y=286.30`,高 `44.19`,文字 `cy=308.10` | 蓝牙 `cx=36.88`、星期 `cx=178.05`、月日 `cx=298.28`、AM/PM 右对齐 `465.89` |
|
||
| 底部数值 | `cy=366.76`;左格右对齐 `234.30`,右格左对齐 `267.40` | 过宽时自动降一档字号 |
|
||
| 底部标签 | `cy=410.88`,同上对齐 | 跟随所选数据(`DST` / `STEP` / `距离` …) |
|
||
|
||
字号按设计稿的**字面高度(cap height)**选取:日期带与电量 `25.34`、上方数据与底部行 `31.50`、时间 `98.70`。
|
||
|
||
---
|
||
|
||
## 3. 进度环
|
||
|
||
刻度是**等角宽的环形扇区**(`fillPolygon` 四点),不是径向线段。
|
||
|
||
- **顶弧**:21 根,角度 `6.5 + 4.0k`(k=0..20),角宽 `3.108°`
|
||
- **底弧**:21 根,角度 `6.005 + 3.0k`,角宽 `2.086°`
|
||
- **四象限**:右上 `+a`、左上 `-a`、左下 `180+a`、右下 `180-a`(角度为自 12 点起顺时针)
|
||
- **锚点圆点**:半径 `9.00`,位于圆心距 `240.10`、角度 `0 / 93.15 / 180 / 266.85`
|
||
|
||
**点亮方向**(与设计稿一致):两条顶弧从 9 点 / 3 点一侧朝 12 点填充;两条底弧从 6 点朝两侧填充。
|
||
|
||
每根刻度的颜色是设计稿里**逐根取样**的实测值(`Themes.RINGTOP[21]` / `RINGBOTTOM[21]`),不是插值近似。
|
||
|
||
> **已知近似**:设计稿中底弧最多只点亮 14/21 根,因此 `RINGBOTTOM` 的第 15–21 项无法实测,由 `gen_themes.py` 对最后 8 根做最小二乘线性外推得到。只有当指标超过约 67% 时才会显示这几根。
|
||
|
||
### 指标进度换算
|
||
|
||
| idx | 指标 | 分母 |
|
||
|-----|------|------|
|
||
| 0 | 步数 | `stepGoal` |
|
||
| 1 | 卡路里 | 固定 2000 kcal |
|
||
| 2 | 距离 | 10 km |
|
||
| 3 | 楼层 | `floorsClimbedGoal`(缺省 10) |
|
||
| 4 | 动动条 | `MOVE_BAR_LEVEL_MAX`(=5) |
|
||
|
||
---
|
||
|
||
## 4. 时间数字的竖向渐变
|
||
|
||
设计稿的小时 / 分钟数字带竖向多段渐变(如 Ember 分钟由 `#FEAA00` 渐变到 `#FF2600`)。Monkey C 无法给文字直接填渐变,实现方式是**同一串数字画 11 遍,每遍用 `dc.setClip` 限制在一条横向色带内**,色带颜色取自 `Themes.HOURS` / `Themes.MINUTES`(各 11 个停止点,实测自设计稿的 `linearGradient`)。首尾两条色带向外延伸,保证字形不会有未绘制的缝隙。
|
||
|
||
---
|
||
|
||
## 5. 字号选择
|
||
|
||
Connect IQ 只暴露 `getFontAscent` / `getFontDescent` / `getFontHeight`,**没有字面高度接口**,而 ascent 里含有数字和大写字母用不到的变音符空间。因此代码用两个实测比例把 ascent 折算成 cap height:
|
||
|
||
```
|
||
文本字体(Roboto 系) cap ≈ 0.76 × ascent
|
||
数字字体(Bionic 系) cap ≈ 0.71 × ascent
|
||
```
|
||
|
||
比例是在模拟器里渲染后、从截图上量出墨迹得到的(fenix847mm:`FONT_XTINY` ascent 29 → 大写高 22px;`FONT_NUMBER_MILD` ascent 82 → 数字高 58px)。`pickFont` 取折算后**最接近**目标 cap height 的字体,而不是"最大且不超过"——后者会在设计尺寸落在两档字体之间时白白小一号。
|
||
|
||
各机型内置字体不完全相同(Roboto-Regular / RobotoCondensed-Bold / Yantramanav / 各机型位图字体),比例会有几个百分点误差。设计稿使用的是更粗更方的第三方字体,不随包分发,字形差异无法消除。
|
||
|
||
---
|
||
|
||
## 6. 七套主题
|
||
|
||
由 `tools/gen_themes.py` 从 `design/watchface-0N-*.svg` 生成。每套包含:顶/底弧各 21 根刻度色、未点亮刻度色、锚点色、日期带底/字色、冒号色、小时/分钟各 11 段渐变、强调色(图标与 DST/STEP 标签)、主文字色(各项数值)。
|
||
|
||
| # | 主题 | 主色调 | 强调色 | 日期带 |
|
||
|---|------|--------|--------|--------|
|
||
| 1 | Ember | 黄 → 红 | `#FEAA05` | 橙底黑字 |
|
||
| 2 | Aurora | 黄绿 → 青 | `#ADABAE` | 深灰底白字 |
|
||
| 3 | Brass | 金铜 | `#B57E4B` | 深棕底白字 |
|
||
| 4 | Voltage | 蓝 → 黄 | `#ADABAE` | 蓝底黑字 |
|
||
| 5 | Reef | 橙 → 青 | `#FEAA05` | 青底黑字 |
|
||
| 6 | Acid | 黄绿(近单色) | `#C6FA03` | 深灰底黑字 |
|
||
| 7 | Kelp | 橙 → 绿 | `#34C294` | 深灰底黑字 |
|
||
|
||
改配色:编辑 / 替换 `design/` 里的 SVG,然后
|
||
|
||
```bash
|
||
python3 tools/gen_themes.py && python3 tools/gen_preview_svg.py
|
||
```
|
||
|
||
新增主题需同步在 `settings.xml` 的 `Theme` 列表与 `strings.xml`(含 `resources-chn/`)中登记。
|
||
|
||
---
|
||
|
||
## 7. 可配置设置与数据字段
|
||
|
||
19 项设置,在 Garmin Connect 手机 App 的「表盘设置」里改(定义在 `resources/settings/settings.xml`,默认值在 `properties.xml`,两者由 `tools/gen_fields.py` 生成)。
|
||
|
||
| 设置 | 键 | 默认 |
|
||
|------|----|------|
|
||
| 主题 | `Theme` | 1 (Ember) |
|
||
| 四段进度环指标 | `RingTR/TL/BR/BL` | 步数 / 卡路里 / 动动条 / 楼层 |
|
||
| 四个数据位 | `LeftTop` `RightTop` `BottomLeft` `BottomRight` | 日出 / 高低温 / 距离 / 步数 |
|
||
| 温度单位 | `TempUnit` | 跟随手表 |
|
||
| 第二时区 1 / 2 偏移(分钟) | `AltOffset1` `AltOffset2` | 0 |
|
||
| 自定义文字 1 / 2 / 3 | `Custom1/2/3` | 空 |
|
||
| 显示顶行 / 日期带 / 底行 | `ShowTop` `ShowBand` `ShowBottom` | true |
|
||
|
||
进度环指标:步数、卡路里、距离、楼层、动动条、活动分钟(对周目标)、身体电量。
|
||
|
||
### 数据字段
|
||
|
||
四个数据位共用一张 **75 项** 的字段表,编号沿用 [watchface.io/docs/datafields](https://watchface.io/docs/datafields),两边可以直接对照。底部两格的小标签跟随所选字段自动变化,不需要单独配置。
|
||
|
||
| 分类 | 字段 |
|
||
|------|------|
|
||
| 日期时间 | 时间、UTC 时间、第二时区 1/2、星期月日、星期日、月日、日、星期(简写/全称)、月份(名称/数字)、上午下午、周数(ISO / 日历) |
|
||
| 活动 | 步数、步数取整、剩余步数、卡路里、活动卡路里、活动分钟(总/中强度/高强度/本周)、距离、上楼层数、下楼层数、爬升高度、推行距离、推行次数 |
|
||
| 身体 | 心率、静息心率、压力指数、血氧、呼吸频率、身体电量、活动条(正/反向)、体重、BMI、恢复时间、最大摄氧量(跑/骑) |
|
||
| 系统 | 电量、剩余天数、电量+天数、闹钟、通知、勿扰、蓝牙、太阳能强度 |
|
||
| 环境 | 海拔、海平面气压、环境气压、日出、日落、下一太阳事件、距太阳事件、月龄、月球照明 |
|
||
| 天气 | 气温、最高/最低、体感、最高、最低、湿度、降水概率、风速、风向角、风向、更新时间 |
|
||
| 自定义 | 自定义文字 1 / 2 / 3 |
|
||
|
||
加字段:在 `tools/gen_fields.py` 的 `FIELDS` 表里加一行,跑一遍生成器,再到 `source/Fields.mc` 的 `value()` 里补一个分支。设置项、两种语言的文案、表盘标签会自动跟上。
|
||
|
||
### ⚠️ 没有实现的字段,以及原因
|
||
|
||
watchface.io 的完整目录约 300 项,本表只收了 **手表本机能算出来的** 那些。其余几类不是没做,是一个自包含的 Connect IQ 表盘做不了:
|
||
|
||
| 没做的 | 原因 |
|
||
|--------|------|
|
||
| OpenWeatherMap(约 30 项)、StormGlass.io(5 项) | 需要 `Communications.makeWebRequest` + 用户自备 API key + 后台服务定时拉取与缓存。是另一个子系统,且要求用户自己去注册 key |
|
||
| 各运动项目的 WTD / 近 7 天 / 本月 / 近 28 天 汇总(约 80 项) | Connect IQ 不暴露按运动分类的历史累计。这些数据在 GreenBlack 那边是通过手机侧与 Garmin Connect 的集成同步来的,本机 API 只有 `ActivityMonitor.getHistory()` 的最近几天步数/卡路里/距离 |
|
||
| 第三方 App 复杂功能(CGM、Hydration、QuoteGlance 等 12 项) | 需要用户装了对应的 App,并通过 Complications API 订阅 |
|
||
| 日历事件、计时器、倒计时 | 日历不对 CIQ 开放;表盘拿不到触摸输入,没法做启停 |
|
||
| 秒数 | 需要 `onPartialUpdate` 每秒重绘。技术上可行,但会明显吃电,暂未做 |
|
||
| 晨昏蒙影、黄金/蓝调时刻(约 14 项) | 可以自己算太阳高度角推出来,只是还没写;月龄和月球照明已经是这样算的 |
|
||
| 睡眠得分、训练状态 | `ActivityMonitor.Info` 上没有这两个字段(SDK 9.1.0 实测) |
|
||
| 标记类字段(Marker,约 35 项) | 那是给刻度型表盘做环形标记用的,本表盘的进度环用的是自己的指标体系 |
|
||
|
||
---
|
||
|
||
## 8. 数据来源与权限
|
||
|
||
| 元素 | API |
|
||
|------|-----|
|
||
| 步数 / 卡路里 / 距离 / 楼层 / 动动条 / 活动分钟 / 呼吸 / 压力 / 恢复时间 | `ActivityMonitor.getInfo()` |
|
||
| 心率 | `Activity.getActivityInfo().currentHeartRate`,回退 `ActivityMonitor.getHeartRateHistory()` |
|
||
| 血氧 / 身体电量 | `SensorHistory`(需 `SensorHistory` 权限) |
|
||
| 静息心率 / 体重 / 身高 / 最大摄氧量 | `UserProfile.getProfile()`(需 `UserProfile` 权限) |
|
||
| 海拔 / 环境气压 / 海平面气压 | `Activity.getActivityInfo()` |
|
||
| 日出 / 日落 | `Weather.getSunrise/getSunset(location, time)`,位置取 `CurrentConditions.observationLocationPosition`,回退 `Activity.currentLocation` |
|
||
| 气温 / 体感 / 湿度 / 降水 / 风 | `Weather.getCurrentConditions()` |
|
||
| 最高 / 最低气温 | `Weather.getDailyForecast()[0]` |
|
||
| 电量 / 剩余天数 / 太阳能 | `System.getSystemStats()`(`battery` 是 0–100 的百分比,不是 0–1) |
|
||
| 闹钟 / 通知 / 勿扰 / 蓝牙 / 单位制 | `System.getDeviceSettings()` |
|
||
| 月龄 / 月球照明 | 自算(儒略日 + 朔望月 29.530588853 天) |
|
||
| 周数 | 自算(ISO 8601 与日历周两种) |
|
||
|
||
### 权限
|
||
|
||
`manifest.xml` 声明两项:`UserProfile`(静息心率、体重、VO2max)与 `SensorHistory`(血氧、身体电量)。用户安装时会看到授权提示。
|
||
|
||
> `Sensor` 权限**不能**用于 `type="watchface"`(除非同时申请 `Background`),编译器会直接拒绝。所以海拔与气压走 `Activity.Info` 而不是 `Sensor.getInfo()`。
|
||
|
||
单位与制式跟随手表:`is24Hour`、`distanceUnits`、`temperatureUnits`(温度可用 `TempUnit` 覆盖)。天气与日出需手表已配对并同步过数据,否则显示 `--`。
|
||
|
||
---
|
||
|
||
## 8.2 常亮显示(AOD)
|
||
|
||
AMOLED 机型在常亮模式下必须压低点亮像素,否则既费电又有烧屏风险,Garmin 上架审核也会卡。`onEnterSleep` / `onExitSleep` 切换到 `drawAmbient()`:
|
||
|
||
- 不画日期带底色(整条亮橙色横幅是最费电的元素)
|
||
- 进度环只画**点亮的**刻度,且整体压暗到 45%
|
||
- 时间与日期压暗到 55%,其余数据位全部隐藏
|
||
- 整个画面按分钟在 ±4px 内游走,避免固定像素长期点亮
|
||
|
||
只在 `DeviceSettings.requiresBurnInProtection` 为真时启用;MIP 机型(Fenix 7 / Enduro 3 等)不受影响,照常全量绘制。
|
||
|
||
模拟器可用 `Settings → Display Mode` 切换验证。
|
||
|
||
---
|
||
|
||
## 8.5 多语言
|
||
|
||
`manifest.xml` 声明了 `eng` 与 `chn`,两套文案分别在 `resources/strings/` 与 `resources-chn/strings/`,由 `monkey.jungle` 的 `base.resourcePath = resources;resources-chn` 同时纳入编译(目录名的 `-chn` 后缀就是语言标记)。手表会按系统语言自动选择。
|
||
|
||
**表盘上的文字也走资源**,不是硬编码:
|
||
|
||
| 资源 | 英文 | 中文 |
|
||
|------|------|------|
|
||
| `DowNames` | `SUN,MON,…,SAT` | `周日,周一,…,周六` |
|
||
| `MonNames` | `JAN,FEB,…,DEC` | `1月,2月,…,12月` |
|
||
| `DateFormat` | `$1$ $2$` → `SEP 9` | `$1$$2$日` → `9月9日` |
|
||
| `Meridiem` | `AM,PM` | `上午,下午` |
|
||
| `FieldLabels` | `TEMP,KCAL,STEP,DST,…` | `气温,卡路里,步数,距离,…` |
|
||
|
||
逗号分隔的列表在 `loadStrings()` 里一次性读入并拆分(`loadResource` 每次调用开销不低,不宜放进 `onUpdate`)。
|
||
|
||
> 中文字形依赖手表固件里的 APAC 字体包(`fontSet: apac_twcn` / `apac_chn`)。国行机型自带;国际版若未安装中文字体包,会退回英文或显示方块。模拟器可用 `Settings → Language → Chinese (Simplified)` 验证。
|
||
|
||
---
|
||
|
||
## 9. 构建
|
||
|
||
需安装 Connect IQ SDK 9.1.0,`monkeyc` 在 PATH 中,并备好 `developer_key.der`(**不在仓库内**,需自行生成或提供)。
|
||
|
||
```bash
|
||
monkeyc -o bin/Fenix8V3.prg -f monkey.jungle -y developer_key.der -d fenix847mm
|
||
```
|
||
|
||
全部 17 款设备批量编译(已验证通过):
|
||
|
||
```bash
|
||
for d in enduro3 fenix843mm fenix847mm fenix8pro47mm fenix8solar47mm fenix8solar51mm \
|
||
epix2 epix2pro47mm epix2pro51mm fenix7 fenix7x fenix7s fr965 fr265 fr255 \
|
||
venu3 vivoactive5; do
|
||
monkeyc -o "bin/Fenix8V3_${d}.prg" -f monkey.jungle -y developer_key.der -d "$d" \
|
||
&& echo "[$d] OK" || echo "[$d] FAIL"
|
||
done
|
||
```
|
||
|
||
屏幕分辨率跨度较大(fenix7s 240×240 至 fenix847mm / venu3 454×454),全部按 `s = width/500` 缩放。
|
||
|
||
---
|
||
|
||
## 10. 模拟器与侧载
|
||
|
||
```bash
|
||
connectiq & # 启动模拟器
|
||
monkeydo bin/Fenix8V3_fenix847mm.prg fenix847mm # 载入表盘
|
||
```
|
||
|
||
非 release 编译会同时产出 `bin/*-settings.json`,可在模拟器 `View → Settings` 载入以实时切换主题与指标。注意模拟器会**持久化**已保存的设置,改 `properties.xml` 的默认值对已运行过的实例不生效,需先重置应用数据。
|
||
|
||
真机侧载:用 Garmin Express 或 Connect 手机 App 导入对应机型的 `bin/Fenix8V3_<device>.prg`,或把 `.prg` 拷入手表 `/GARMIN/Apps/`。
|
||
|
||
---
|
||
|
||
## 11. 预览
|
||
|
||
```bash
|
||
python3 tools/gen_preview_svg.py
|
||
```
|
||
|
||
产出 `preview-themes.svg`(七套主题一览)与 `preview.html`(可切换主题的单页)。两者用网页字体渲染文字,**几何与配色可信,字形不可信** —— 真机字形以模拟器截图为准。
|
||
|
||
---
|
||
|
||
## 12. 与设计稿的差异
|
||
|
||
1. **字体**。设计稿用的是一款更粗、更方的第三方字体;Garmin 只提供内置 Roboto / Bionic 系列,且各机型不同。字号按 cap height 对齐,字形无法一致。
|
||
2. **图标**。设计稿里的图标是位图描出的密集矢量路径(数百个点),不适合逐帧绘制;代码用圆、多边形、线段按实测的子形状位置重建了电量、日出/日落、多云三个图标。其余数据项(卡路里 / 步数 / 距离 / 楼层)设计稿未提供图标,为自绘。
|
||
3. **底弧高段颜色**为外推值,见 §3。
|
||
4. **进度环是实时数据**,设计稿中的是固定演示状态(右上 21/21、左上 10/21、右下 9/21、左下 14/21)。
|
||
|
||
---
|
||
|
||
## 13. 设计稿版权
|
||
|
||
`design/` 内的 SVG、tokens 与 `rebuild.py` 来自 `watchface-kit`,版权归原作者所有。本仓库是按该设计稿实现的 Monkey C 表盘。
|