feat(island): 参考 WinIsland 重写灵动岛(squircle + 三种底 + 字号系数排版 + 空闲细缝)
参考: 工作目录 WinIsland-master.zip(Rust/Direct2D 的 Windows 动态岛),
逐项提取的设计 token 归档在 docs/winisland-design-tokens.md。
视觉与造型:
- 连续圆角 squircle(新增 island/squircle.ts,超椭圆角,对齐 WinIsland utils/shape.rs),
胶囊半径 = min(圆角, h/2)(满圆角),展开卡 = min(48*圆角/20, w/2, h/2)(WinIsland expanded_island_radius)
- 三种底: 纯黑(WinIsland default)/ 毛玻璃(win.setBackgroundMaterial('acrylic'),等价 HostBackdropBrush)/
主题色渐变;描边 1px 白 alpha .118(纯黑)/.157(玻璃),展开投影 0 2px 3px rgba(0,0,0,.11)
- Apple 系统色: 强调蓝 #0a84ff、警告橙 #ff9f0a、危险红 #ff453a;白字 alpha 分级 .92/.72/.58
- 状态色只做"内层微染 + 描边 + 徽标",不外溢(保持外圈偏红 = 0)
排版(本次重点):
- 基础字号 11–20px,岛内**所有文本** = 基础字号 × 排版系数
(标题 1.08 / 正文 0.95 / 次要 0.78 / 徽标与按钮 0.76 / 胶囊标题 0.92 / 胶囊副题 0.74),
与 WinIsland 的 font_size 模型一致;实测 13→19px 全部文本倍率 1.462(=19/13)
- 图标、按钮高度、间距也由字号推导,改字号不会溢出
形态与设置:
- 尺寸基准对齐 WinIsland 比例(胶囊 216x34 基准、展开 +156/+186 等),卡片 = 窗口 - 2*5px 且水平居中
- 6 个停靠位(顶/底 × 左/中/右,对齐 WinIsland DockPosition)
- 新增"空闲细缝"(WinIsland hidden_width):空闲留一条 6px 宽竖条,来消息自动展开
- 所有设置依旧"改即生效";顺带修掉 hide() 用 skipWindow 绕过 syncWindow 导致细缝不生效的问题
验证(verify:desktop 49 → 53 项,全绿):
- 字号即时生效: 13px→19px 五项文本倍率全部 1.462
- 风格即时生效: 纯黑 fill=rgb(0,0,0)/材质 none;毛玻璃 fill=rgba(10,10,14,.59)/材质 acrylic;主题色 fill=rgb(11,11,15)
- 空闲细缝: 16x36 → 来消息 268x44;关闭后完全隐藏
- 6 锚点、开合不震动(0.00px / 无过冲)、截图 6 张(比例偏差 0.000、外圈偏红 0)全部保持
- verify:e2e 133/133、verify:web 19/19 不受影响;截图归档到 docs/screenshots/island/
工程发现: Windows 对透明窗口有约 36px 最小高度(请求 32px 实际 36px),
空闲细缝高度据此设下限并写入注释与 README。
This commit is contained in:
1 parent
9c9ac69ac6
commit
3f2b135211
17 files changed
+1632
-588
No files matched your search
@@ -72,12 +72,17 @@ export const DEFAULT_ISLAND_APPEARANCE = {
|
||||
width: 268,
|
||||
radius: 20,
|
||||
opacity: 1,
|
||||
accent: '#6cc4ff',
|
||||
/** 默认强调色采用 Apple 系统蓝(与 WinIsland 的系统色体系一致) */
|
||||
accent: '#0a84ff',
|
||||
fontSize: 13,
|
||||
animations: true,
|
||||
speed: 1,
|
||||
position: 'top-center',
|
||||
alwaysOnTop: true,
|
||||
/** 纯黑底(WinIsland default 风格) */
|
||||
style: 'black',
|
||||
/** 空闲时完全隐藏(与原行为一致;打开后空闲会留一条细缝) */
|
||||
idleSliver: false,
|
||||
} as const;
|
||||
|
||||
/** 个性化设置项的合法区间(前端滑块与后端校验共用,避免越界导致布局错乱) */
|
||||
@@ -86,19 +91,59 @@ export const ISLAND_APPEARANCE_RANGES = {
|
||||
width: { min: 220, max: 420 },
|
||||
radius: { min: 8, max: 32 },
|
||||
opacity: { min: 0.4, max: 1 },
|
||||
fontSize: { min: 11, max: 18 },
|
||||
fontSize: { min: 11, max: 20 },
|
||||
speed: { min: 0.5, max: 2 },
|
||||
} as const;
|
||||
|
||||
/** 停靠位置可选值 */
|
||||
export const ISLAND_POSITIONS = ['top-center', 'top-left', 'top-right', 'bottom-center'] as const;
|
||||
/** 停靠位置可选值(与 WinIsland 的 DockPosition 一致:顶/底 × 左/中/右) */
|
||||
export const ISLAND_POSITIONS = [
|
||||
'top-center',
|
||||
'top-left',
|
||||
'top-right',
|
||||
'bottom-center',
|
||||
'bottom-left',
|
||||
'bottom-right',
|
||||
] as const;
|
||||
|
||||
export const ISLAND_POSITION_LABELS: Record<(typeof ISLAND_POSITIONS)[number], string> = {
|
||||
'top-center': '顶部居中',
|
||||
'top-left': '左上角',
|
||||
'top-right': '右上角',
|
||||
'bottom-center': '底部居中',
|
||||
'bottom-left': '左下角',
|
||||
'bottom-right': '右下角',
|
||||
};
|
||||
|
||||
/** 视觉风格可选值(参考 WinIsland 的 island_style) */
|
||||
export const ISLAND_STYLES = ['black', 'glass', 'tinted'] as const;
|
||||
|
||||
export const ISLAND_STYLE_LABELS: Record<(typeof ISLAND_STYLES)[number], string> = {
|
||||
black: '纯黑(灵动岛默认)',
|
||||
glass: '毛玻璃(半透明模糊)',
|
||||
tinted: '主题色渐变',
|
||||
};
|
||||
|
||||
/**
|
||||
* 空闲细缝尺寸(参考 WinIsland hidden_width = 5:空闲态是一条很窄的圆角柱)。
|
||||
* 宽度固定 6px,高度取胶囊高度的一部分,视觉上就是一条"小黑条"。
|
||||
*/
|
||||
export const ISLAND_SLIVER_WIDTH = 6;
|
||||
|
||||
/** 岛内文本的排版系数(相对基础字号,集中在这里方便统一调整) */
|
||||
export const ISLAND_TYPE_SCALE = {
|
||||
/** 展开卡标题 */
|
||||
title: 1.08,
|
||||
/** 正文 */
|
||||
body: 0.95,
|
||||
/** 次要说明 / 元信息 */
|
||||
meta: 0.78,
|
||||
/** 徽标 / 按钮 */
|
||||
badge: 0.76,
|
||||
/** 胶囊主标题 */
|
||||
pillTitle: 0.92,
|
||||
/** 胶囊副标题 */
|
||||
pillSub: 0.74,
|
||||
} as const;
|
||||
/** 默认学期周次上限 */
|
||||
export const DEFAULT_WEEK_COUNT = 20;
|
||||
|
||||
|
||||
@@ -415,26 +415,45 @@ export interface IslandAppearance {
|
||||
height: number;
|
||||
/** 胶囊宽度(px,220~420) */
|
||||
width: number;
|
||||
/** 卡片圆角(px,8~32) */
|
||||
/** 卡片圆角(px,8~32):采用连续圆角(squircle),此值为四角的基准半径 */
|
||||
radius: number;
|
||||
/** 整体不透明度(0.4~1) */
|
||||
opacity: number;
|
||||
/** 主题色(强调色,用于高亮与按钮) */
|
||||
accent: string;
|
||||
/** 基础字号(px,11~18) */
|
||||
/**
|
||||
* 基础字号(px,11~20)——参考 WinIsland 的 font_size:
|
||||
* 岛内**所有文本**都由它乘以各自的排版系数得出,因此改字号会整体等比缩放。
|
||||
*/
|
||||
fontSize: number;
|
||||
/** 是否启用动画(关闭后展开/收起为瞬时) */
|
||||
animations: boolean;
|
||||
/** 动画速度倍率(0.5 慢 ~ 2 快) */
|
||||
speed: number;
|
||||
/** 显示位置 */
|
||||
/** 显示位置(顶/底 × 左/中/右,与 WinIsland 的 DockPosition 对齐) */
|
||||
position: IslandPosition;
|
||||
/** 是否始终置顶 */
|
||||
alwaysOnTop: boolean;
|
||||
/**
|
||||
* 视觉风格(参考 WinIsland 的 island_style):
|
||||
* - `black`:纯黑底(默认,WinIsland `default` 风格)
|
||||
* - `glass`:半透明 + 背景模糊(WinIsland `glass` 风格)
|
||||
* - `tinted`:强调色渐变(本产品特色,保持与原主题色一致)
|
||||
*/
|
||||
style: IslandStyle;
|
||||
/**
|
||||
* 空闲时是否保留一条"细缝"(参考 WinIsland 的 hidden_width:空闲态是一条很窄的圆角柱)。
|
||||
* 关闭时(默认)空闲即完全隐藏,与原行为一致。
|
||||
*/
|
||||
idleSliver: boolean;
|
||||
}
|
||||
|
||||
/** 灵动岛停靠位置 */
|
||||
export type IslandPosition = 'top-center' | 'top-left' | 'top-right' | 'bottom-center';
|
||||
/** 灵动岛停靠位置(6 个锚点,与 WinIsland 一致) */
|
||||
export type IslandPosition =
|
||||
'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right';
|
||||
|
||||
/** 灵动岛视觉风格 */
|
||||
export type IslandStyle = 'black' | 'glass' | 'tinted';
|
||||
|
||||
/** 灵动岛当前状态(主进程持有,渲染进程与冒烟测试读取) */
|
||||
export interface IslandState {
|
||||
|
||||
Reference in new issue
Block a user