跳至主要内容

宽色域 Color 的迁移指南

摘要

#

dart:ui 中的 Color 类 API 正在发生变化,以支持 宽色域色彩空间

上下文

#

Flutter 引擎 已经支持宽色域颜色,并与 Impeller 配合使用,并且该支持现在正在 添加到框架中

Flutter 支持的 iOS 设备渲染到更大的颜色数组,特别是在 DisplayP3 色彩空间中。此更改后,Flutter 框架可以在 iOS Impeller 上渲染所有这些颜色,并且 Color 类将为未来的色彩空间或颜色组件位深度的更改做好更好的准备。

更改说明

#

Color 的更改

  1. 添加了一个枚举字段,用于指定其 ColorSpace
  2. 添加了使用归一化浮点颜色组件的 API。
  3. 删除了使用 8 位无符号整数颜色组件的 API,这些组件可能导致数据丢失。

ColorSpace 的更改

  1. 添加了一个 displayP3 属性。

迁移指南

#

8 位无符号整数构造函数

#

Color.fromARGB 等构造函数保持不变并继续支持。要利用 Display P3 颜色,必须使用新的 Color.from 构造函数,该构造函数采用归一化浮点颜色组件。

dart
// Before
final magenta = Color.fromARGB(0xff, 0xff, 0x0, 0xff);
// After
final magenta = Color.from(alpha: 1.0, red: 1.0, green: 0.0, blue: 1.0)

Color 的实现者

#

正在向 Color 添加新的方法,因此任何implements Color 的类都将中断,并且必须实现新的方法,如 Color.aColor.b。最终,实现者应该迁移以利用新的 API。在短期内,这些方法可以很容易地实现,而无需更改类的底层结构。

例如

dart
class Foo implements Color {
  int _red;

  @override
  double get r => _red * 255.0;
}

色彩空间支持

#

使用 Color 并对颜色组件执行任何类型的计算的客户端现在应该首先检查颜色空间组件,然后再执行计算。为此,您可以使用新的 Color.withValues 方法执行颜色空间转换。

迁移示例

dart
// Before
double redRatio(Color x, Color y) => x.red / y.red;

// After
double redRatio(Color x, Color y) {
  final xPrime = x.withValues(colorSpace: ColorSpace.extendedSRGB);
  final yPrime = y.withValues(colorSpace: ColorSpace.extendedSRGB);
  return xPrime.r / yPrime.r;
}

在不调整颜色空间的情况下对颜色组件执行计算可能会导致细微的意外结果。在上面的示例中,当使用不同的颜色空间与调整后的颜色空间计算时,redRatio 将存在 0.09 的差异。

访问颜色组件

#

如果您的应用程序曾经访问过 Color 组件,请考虑利用浮点组件。在短期内,您可以轻松地缩放组件本身。

dart
extension IntColorComponents on Color {
  int get intAlpha => this.a ~/ 255;
  int get intRed => this.r ~/ 255;
  int get intGreen => this.g ~/ 255;
  int get intBlue => this.b ~/ 255;
}

不透明度

#

以前,Color 具有“不透明度”的概念,它出现在 opacitywithOpacity() 方法中。不透明度作为一种使用浮点值与 Color 通信其 alpha 通道的方式引入。现在 alpha 是一个浮点值,不透明度是冗余的,并且 opacitywithOpacity 已弃用,并计划删除。

opacity 迁移

#
dart
// Before
final x = color.opacity;
// After
final x = color.a;

withOpacity 迁移

#
dart
// Before
final x = color.withOpacity(0.0);
// After
final x = color.withValues(alpha: 0.0);

相等性

#

一旦 Color 将其颜色组件存储为浮点数,相等性就会略有不同。在计算颜色时,可能存在微小的值差异,这些差异可以被认为是相等的。为了适应这一点,请使用 closeTo 匹配器或 isColorSameAs 匹配器。

dart
// Before
expect(calculateColor(), const Color(0xffff00ff));
// After
expect(calculateColor(), isSameColorAs(const Color(0xffff00ff)));

时间线

#

阶段 1 - 新 API 引入,旧 API 弃用

#

发布到稳定版:待定 PR:: PR 54737

阶段 2 - 旧 API 移除

#

发布到稳定版:待定

参考

#

相关 PR