如何从普通Color对象中获取最接近的MaterialColor色值?
从普通Color对象获取最接近MaterialColor的实现方案
实现原理
通过计算目标颜色与所有材质色之间的色彩差异,取差异最小的材质色作为匹配结果。推荐使用加权RGB距离计算,相比普通欧氏距离更贴合人眼对色彩的感知敏感度(人眼对绿色敏感度最高,红色次之,蓝色最低)。
加权距离计算公式:
距离 = √[2*(R差值)² + 4*(G差值)² + 3*(B差值)²]
实现步骤
- 第一步:整理所有需要参与匹配的MaterialColor样本列表,Flutter预置的MaterialColor主色样本可直接使用下方列表,若需要匹配材质色的所有深浅档位(如shade100、shade900),可将所有档位的色值也加入匹配样本。
- 第二步:实现色彩距离计算逻辑,遍历所有样本计算与目标颜色的距离。
- 第三步:取距离最小的样本作为最终匹配结果。
代码示例(Dart/Flutter)
1. 定义MaterialColor样本列表
import 'package:flutter/material.dart'; import 'dart:math' as math; // 所有Flutter预置的MaterialColor主色 final List<MaterialColor> primaryMaterialColors = [ Colors.red, Colors.pink, Colors.purple, Colors.deepPurple, Colors.indigo, Colors.blue, Colors.lightBlue, Colors.cyan, Colors.teal, Colors.green, Colors.lightGreen, Colors.lime, Colors.yellow, Colors.amber, Colors.orange, Colors.deepOrange, Colors.brown, Colors.grey, Colors.blueGrey, ];
2. 实现匹配方法
MaterialColor getNearestMaterialColor(Color targetColor) { double minDistance = double.infinity; late MaterialColor nearestMatchedColor; for (final materialColor in primaryMaterialColors) { // 此处取材质色的500档位作为基准值,如需匹配全档位可遍历materialColor的所有shade final currentSwatchColor = materialColor.shade500; final rDiff = targetColor.red - currentSwatchColor.red; final gDiff = targetColor.green - currentSwatchColor.green; final bDiff = targetColor.blue - currentSwatchColor.blue; // 计算加权距离 final currentDistance = math.sqrt( 2 * (rDiff * rDiff) + 4 * (gDiff * gDiff) + 3 * (bDiff * bDiff) ); if (currentDistance < minDistance) { minDistance = currentDistance; nearestMatchedColor = materialColor; } } return nearestMatchedColor; }
3. 调用测试
void main() { final Color someColor = const Color(0xFF212122); final matchedMaterialColor = getNearestMaterialColor(someColor); // 输出结果为Colors.grey,对应shade900值就是0xFF212121 print(matchedMaterialColor); }
优化方案
如果对匹配精度要求更高,可以将RGB色值转换为LAB色彩空间后再计算距离,匹配结果会更贴合人眼的实际色彩感知。
内容的提问来源于stack exchange,提问作者iDecode
相关产品推荐
相关产品推荐

