Electron `-electron-corner-smoothing`:把 CSS 圆角磨出系统级平滑曲线的实现与用法

📅 发布时间:2026/9/5 18:14:56
Electron `-electron-corner-smoothing`:把 CSS 圆角磨出系统级平滑曲线的实现与用法
Electron-electron-corner-smoothing把 CSS 圆角磨出系统级平滑曲线的实现与用法【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron-electron-corner-smoothing是 Electron 专属的实验性 CSS 规则用来在border-radius的圆角基础上进一步“磨平”曲率突变得到类似 macOS SwiftUI 连续圆角continuous corners的视觉效果。本文以官方 API 文档为骨架结合 Electron 仓库中的 Chromium 补丁、渲染端 C 实现与像素级测试用例完整讲解该规则的语法、system-ui关键字的平台差异、从 CSS 声明到 Skia 路径的渲染管线以及通过disableBlinkFeatures控制其可用性的方法。读完后你可以直接在自己的 Electron 应用里配置平滑圆角并理解其背后的几何算法与实现边界。规则定位解决什么问题普通border-radius生成的圆角由“直线边 四分之一圆弧”拼接而成在边与圆弧的连接点处曲率会发生突变。对于重视与操作系统设计语言一致性的桌面应用来说这种突变是一个容易被用户察觉的细节——macOS 的界面圆角实际采用的是曲率连续过渡的曲线而 Electron 的网页渲染内容默认并不具备这种能力。-electron-corner-smoothing正是为此设计的它不改变圆角半径本身而是调整圆角的“平滑度”smoothness让曲率在直线与圆弧之间缓慢过渡效果类似 Apple SwiftUI 的连续圆角也类似 Figma 中对设计元素提供的 “corner smoothing” 控制。该规则的作用对象与border-radius一致并且会同时影响目标元素的**边框borders、外框线outlines与阴影shadows**的轮廓形状。与border-radius的行为类似当元素尺寸过小、边长不足以容纳所选值时平滑度会渐进地回退back off。需要强调的是两点边界该规则仅在 Electron 中实现在浏览器中没有任何效果避免在非 Electron 环境依赖它同时它被明确视为实验性功能未来若被正式 CSS 标准取代可能需要迁移官方文档中提到的迁移方向可参考上游corner-shape相关演进见后文失效列表。形式化参考与基本语法官方文档给出的形式化定义如下-electron-corner-smoothing percentage [0,100] | system-ui属性说明Initial value0%InheritedNoAnimatableNoComputed valueAs specified也就是说初始值为0%不平滑该属性不继承不可参与 CSS 动画计算值就是指定值本身。取值只有两种形式0%–100%的百分比或关键字system-ui。以下示例展示不同平滑度百分比下的效果文档原例.box { width: 128px; height: 128px; background-color: cornflowerblue; border-radius: 24px; -electron-corner-smoothing: var(--percent); /* Column header in table below. */ }0%100%30%、60% 的中间状态见 corner-smoothing-example-30.svg 与 corner-smoothing-example-60.svg。非法取值的处理从源码结构看解析与渲染两端各有约束。CSS 解析层补丁中的longhands_custom.cc使用ConsumePercent并指定CSSPrimitiveValue::ValueRange::kNonNegative范围因此负百分比如-10%在解析阶段即被判为非法声明属性落回初始值而200%这类超出[0,100]的百分比可以解析通过但在渲染层被std::clamp(smoothness, 0.0f, 1.0f)钳制为100%见 Chromium 补丁。仓库测试夹具 spec/fixtures/api/corner-smoothing/shape/test.html 专门用200%、-10%、-200%三种“invalid”取值渲染了一整行样本并以此对照参考图验证上述行为。system-ui关键字跟随系统设计语言如果不想手动挑选百分比可以使用system-ui关键字让平滑度自动匹配当前操作系统的圆角风格.box { width: 128px; height: 128px; background-color: cornflowerblue; border-radius: 24px; -electron-corner-smoothing: system-ui; /* Match the system UI design. */ }各平台上的解析结果如下OS:macOSWindows, LinuxValue:60%0%Example:这个平台差异可以直接在实现中得到印证。补丁在contoured_border_geometry.cc中新增了SmoothnessFromLength函数补丁片段float SmoothnessFromLength(const Length length) { // none 0% if (length.IsNone()) { return 0.0f; } // system-ui keyword, represented internally as auto length if (length.HasAuto()) { #if BUILDFLAG(IS_MAC) return 0.6f; // macOS: 60% #else return 0.0f; // Windows / Linux: 0% #endif } return length.Percent() / 100.0f; }可以注意一个实现细节system-ui在内部并不是独立存储的关键字而是被编码为Length::Auto()——补丁注释里写得很直白“To keep this patch small, Length is used instead of a more descriptive custom type”为了让补丁更小用Length代替了更具描述性的自定义类型。因此system-ui最终被解析为Length::Auto()见补丁中StyleBuilderConverter::ConvertCornerSmoothing的实现序列化回 CSS 文本时再由CSSValueFromComputedStyleInternal还原为system-ui标识符。渲染管线从 CSS 声明到 Skia 路径该功能通过一个完整的 Chromium 补丁落地feat_corner_smoothing_css_rule_and_blink_painting.patch补丁头部的提交说明将其拆为三块主要改动理解这三块就能理解整条管线1. 注册 CSS 规则规则元数据注册在blink/renderer/core/css/css_properties.json5中补丁片段关键配置包括property_methods:ParseSingleValue与CSSValueFromComputedStyleInternal——前者是自定义解析逻辑先尝试system-ui标识符再回退为百分比后者负责从计算样式序列化出 CSS 值type_name: Length、default_value: Length::None()、keywords: [system-ui]runtime_flag: ElectronCSSCornerSmoothing——规则可用性由该运行时特性开关控制下文详述invalidate: [border-radius, paint, corner-shape]——该属性被声明为与border-radius、paint以及上游corner-shape属性联动失效。这里可以看到 Electron 在为上游corner-shape标准预留了对齐关系也解释了官方文档中“若被 CSS 标准取代可能需要迁移”的表述。配套地补丁还在css_property_equality.cc中补充了该属性的相等性比较ElectronCornerSmoothing()逐字节比较保证样式重算时的正确判定。2. 改造 Blink 的圆角绘制路径Blink 用ContouredRect描述带圆角的矩形。补丁为其CornerCurvature结构增加了一个smoothness_分量默认 0并让ComputeContouredBorderFromStyle在四角曲率之后追加SmoothnessFromLength(style.ElectronCornerSmoothing())作为输入同时IsRound()的判定增加!IsSmooth()条件——也就是说只有平滑度为 0 的纯圆角才会走快速路径平滑圆角会走新的分支。PathBuilder::AddContouredRect在检测到IsSmooth()后对半径做ConstrainRadii()保证半径不超出盒模型取每个角半径两个维度中的最小值实现只支持单一半径椭圆角半径会以最小维度值近似然后调用 Electron 侧的实现builder_.addPath(electron::DrawSmoothRoundRect( box.x(), box.y(), box.width(), box.height(), smoothness, min_radius(radii.TopLeft()), min_radius(radii.TopRight()), min_radius(radii.BottomRight()), min_radius(radii.BottomLeft())));3. Electron 侧的几何算法核心绘制函数是 shell/renderer/electron_smooth_round_rect.cc 中的DrawSmoothRoundRect其接口声明在 shell/renderer/electron_smooth_round_rect.h。头文件注释给出了语义约定smoothness 取值 0.0–1.0对应 0%–100%决定每个角可以“吃掉”多少边长消耗量随该角半径缩放边长不足时平滑度会动态缩放回退与圆角半径的回退机制类似每个角的半径可独立传入且半径应已被平衡每边上Radius1 Radius2 Length椭圆角半径elliptical radii当前不受支持。算法的几何思路在源码注释中有一段完整的 ASCII 图解源码注释其思路可概括为普通圆角中直线边与四分之一圆弧的交点是曲率突变点。目标是在该交点两侧“拓出”一段额外空间构造一条让曲率从直线平滑过渡到圆弧的曲线这段过渡曲线用两段三次贝塞尔曲线 中间一段圆弧实现。每个贝塞尔的四个控制点中第一个锚定直线边、最后一个锚定圆弧第三个由“边延长线与圆弧切线的交点”唯一确定第二个则只受“落在边延长线上”的约束、可自由选取一个角消耗多少边长由LengthForCornerSmoothness(smoothness, radius) (1 smoothness) * radius决定源码即平滑度从 0 到 1 时角落消耗从1×radius增长到2×radius。对于“同一条边上的两个角都要求平滑”的情况函数ConstrainSmoothness源码负责约束若两角的消耗总和超过边长则按半径比例r1/(r1r2)分配可用边长反推出每个角各自的有效平滑度并保证结果不小于 0。这正对应官方文档中“元素尺寸过小则平滑度渐进回退”的表述。影响范围边框、轮廓、阴影与裁剪官方文档声明该规则“影响目标元素上边框、外框线与阴影的形状”。仓库的测试夹具 spec/fixtures/api/corner-smoothing/shape/test.html 用一整页样本覆盖了这些渲染路径每个平滑度档位0/30/60/100/非法值都会渲染同一套 8 种元素纯背景圆角background-color的黑色方块img图片的圆角裁切实线 / 虚线 / 双线边框border-style: solid / dashed / doubleoverflow: clip子内容的圆角裁剪box-shadow带 offset、spread 的偏移阴影四角不同半径的多个border-radius值border-radius: 0 0 r1 r2。这说明平滑轮廓不仅作用于背景填充还贯穿了边框绘制、图片裁剪、阴影路径与内容裁剪等多条绘制分支——这与实现上“在ContouredRect这一共用几何描述中注入平滑度”的方案一致所有以该轮廓为输入的路径构建都会自动获得平滑角。控制可用性disableBlinkFeatures该规则由 Blink 运行时特性开关ElectronCSSCornerSmoothing控制。补丁在runtime_enabled_features.json5中注册了这一开关补丁片段状态为stable。开发者可以按窗口粒度通过webPreferences.disableBlinkFeatures将其禁用文档原例const myWindow new BrowserWindow({ // [...] webPreferences: { disableBlinkFeatures: ElectronCSSCornerSmoothing // Disables the -electron-corner-smoothing CSS rule } })禁用后该 CSS 规则不再可用元素会按普通border-radius圆角渲染。这一机制同样被测试所依赖测试用同一个页面分别以“可用 / 不可用”两种偏好创建窗口并对照各自的参考截图断言结果见下节。测试验证像素级截图对比该功能的回归测试是 spec/api-corner-smoothing-spec.ts思路是“渲染页面 →webContents.capturePage()截图 → 与参考图做平均全局像素差比较”比较函数compareImages计算两张位图逐像素 RGB 差的均值容忍阈值COMPARISON_TOLERANCE 2.5注释说明实测匹配图差异约 1.3、不匹配图差异至少约 7.3shape用例加载 shape/test.html分别以disableBlinkFeatures: ElectronCSSCornerSmoothing不可用与未禁用可用两种方式创建 800×600 窗口截图对照expected-false.png/expected-true.pngsystem-ui用例加载 system-ui-keyword/test.html页面并排渲染0%、system-ui、100%三个 256×256 圆角方块border-radius: 48px截图按process.platform对照expected-darwin.png、expected-win32.png、expected-linux.png——这也直接验证了上文SmoothnessFromLength的平台分支darwin 参考图应呈现 60% 平滑形态而 win32 与 linux 参考图应一致且等同于 0%。测试失败时会把实际截图作为 artifact 输出corner-rounding-expected-*.png方便人工比对角部曲线差异是排查渲染回归的实用入口。限制与注意事项仅 Electron 可用浏览器中该规则无效不要把它写进跨环境复用的样式代码实验性、可能迁移官方文档明确其为 experimental且失效列表中已声明与上游corner-shape属性的关联见 css_properties.json5 补丁配置长期项目中建议将其收敛在独立样式文件中便于未来迁移不可动画Animatable: No不能通过 CSS transition/animation 平滑改变平滑度椭圆角半径不受支持DrawSmoothRoundRect只接受单一半径头文件声明Blink 侧会以两维度半径的最小值近似传入负值非法、超界钳制负百分比解析失败落回0%超过 100% 的值渲染时被钳制为 100%小尺寸回退与border-radius一样边长不足时平滑度会按ConstrainSmoothness的比例规则自动收缩无需额外处理。延伸阅读官方 API 文档docs/api/corner-smoothing-css.md实现补丁patches/chromium/feat_corner_smoothing_css_rule_and_blink_painting.patch几何绘制实现shell/renderer/electron_smooth_round_rect.cc、shell/renderer/electron_smooth_round_rect.h回归测试spec/api-corner-smoothing-spec.ts、测试夹具 spec/fixtures/api/corner-smoothing/【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考