refactor(color-module): 优化序列化实现并改进颜色计算逻辑

- 使用serde_json简化Swatch和ColorSet的序列化实现
- 修改Swatch.get()方法以使用0-1范围的亮度值
- 改进search_for_common_wacg_color算法,使用平均值替代最小值
- 为ColorSet添加hover字段的序列化
This commit is contained in:
徐涛 2025-07-18 09:09:58 +08:00
parent 8a09806b8c
commit a71a635eb8
2 changed files with 30 additions and 23 deletions

View File

@ -2,8 +2,9 @@ use core::f32;
use std::sync::Arc; use std::sync::Arc;
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use palette::{color_difference::Wcag21RelativeContrast, luma::Luma, Oklch}; use palette::{Oklch, color_difference::Wcag21RelativeContrast, luma::Luma};
use serde::{ser::SerializeStruct, Serialize}; use serde::Serialize;
use serde_json::json;
use crate::{ use crate::{
convert::{map_oklch_to_luma, map_oklch_to_srgb_hex}, convert::{map_oklch_to_luma, map_oklch_to_srgb_hex},
@ -44,11 +45,11 @@ fn search_for_common_wacg_color(
for scan_lightness in (0..=100).map(|x| x as f32 / 100.0) { for scan_lightness in (0..=100).map(|x| x as f32 / 100.0) {
let new_target = neutral_swatch.get(scan_lightness); let new_target = neutral_swatch.get(scan_lightness);
let new_target_luma = map_oklch_to_luma(&new_target); let new_target_luma = map_oklch_to_luma(&new_target);
let reference_wacgs = reference_colors let reference_wacgs_sum: f32 = reference_colors
.iter() .iter()
.map(|ref_color| match_wacg(&ref_color, &new_target_luma) - minium_ratio) .map(|ref_color| match_wacg(&ref_color, &new_target_luma) - minium_ratio)
.min_by(|a, b| a.abs().total_cmp(&b.abs())) .sum();
.unwrap_or(f32::NEG_INFINITY); let reference_wacgs = reference_wacgs_sum / reference_colors.len() as f32;
if reference_wacgs.abs() < closest_match.1.abs() { if reference_wacgs.abs() < closest_match.1.abs() {
closest_match = (scan_lightness, reference_wacgs); closest_match = (scan_lightness, reference_wacgs);
} }
@ -273,19 +274,22 @@ impl Serialize for ColorSet {
S: serde::Serializer, S: serde::Serializer,
{ {
let root = map_oklch_to_srgb_hex(&self.root); let root = map_oklch_to_srgb_hex(&self.root);
let hover = map_oklch_to_srgb_hex(&self.hover);
let active = map_oklch_to_srgb_hex(&self.active); let active = map_oklch_to_srgb_hex(&self.active);
let focus = map_oklch_to_srgb_hex(&self.focus); let focus = map_oklch_to_srgb_hex(&self.focus);
let disabled = map_oklch_to_srgb_hex(&self.disabled); let disabled = map_oklch_to_srgb_hex(&self.disabled);
let on_root = map_oklch_to_srgb_hex(&self.on_root); let on_root = map_oklch_to_srgb_hex(&self.on_root);
let on_disabled = map_oklch_to_srgb_hex(&self.on_disabled); let on_disabled = map_oklch_to_srgb_hex(&self.on_disabled);
let mut state = serializer.serialize_struct("ColorSet", 6)?; let color_set_object = json!({
state.serialize_field("root", &root)?; "root": root,
state.serialize_field("active", &active)?; "hover": hover,
state.serialize_field("focus", &focus)?; "active": active,
state.serialize_field("disabled", &disabled)?; "focus": focus,
state.serialize_field("onRoot", &on_root)?; "disabled": disabled,
state.serialize_field("onDisabled", &on_disabled)?; "onRoot": on_root,
state.end() "onDisabled": on_disabled,
});
color_set_object.serialize(serializer)
} }
} }

View File

@ -1,6 +1,7 @@
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use palette::Oklch; use palette::Oklch;
use serde::{ser::SerializeMap, Serialize}; use serde::Serialize;
use serde_json::Value;
use crate::convert::map_oklch_to_srgb_hex; use crate::convert::map_oklch_to_srgb_hex;
@ -17,9 +18,9 @@ impl Swatch {
} }
pub fn get<L: Into<f32>>(&self, lightness: L) -> Oklch { pub fn get<L: Into<f32>>(&self, lightness: L) -> Oklch {
let request_lightness: f32 = lightness.into(); let request_lightness: f32 = lightness.into() / 100.0;
Oklch { Oklch {
l: request_lightness.clamp(10.0, 98.0), l: request_lightness.clamp(0.1, 0.98),
..self.0.clone() ..self.0.clone()
} }
} }
@ -81,13 +82,15 @@ impl Serialize for Swatch {
where where
S: serde::Serializer, S: serde::Serializer,
{ {
let mut state = serializer.serialize_map(Some(SWATCH_LIGHTINGS.len()))?; let swatch_object = SWATCH_LIGHTINGS
.iter()
.map(|l| {
let color = self.get_hex(*l);
let key = format!("{l:02}");
(key, color)
})
.collect::<Value>();
for l in SWATCH_LIGHTINGS { swatch_object.serialize(serializer)
let color = self.get_hex(l);
state.serialize_entry(&format!("{l:02}"), &color)?;
}
state.end()
} }
} }