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

View File

@ -1,6 +1,7 @@
use linked_hash_map::LinkedHashMap;
use palette::Oklch;
use serde::{ser::SerializeMap, Serialize};
use serde::Serialize;
use serde_json::Value;
use crate::convert::map_oklch_to_srgb_hex;
@ -17,9 +18,9 @@ impl Swatch {
}
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 {
l: request_lightness.clamp(10.0, 98.0),
l: request_lightness.clamp(0.1, 0.98),
..self.0.clone()
}
}
@ -81,13 +82,15 @@ impl Serialize for Swatch {
where
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 {
let color = self.get_hex(l);
state.serialize_entry(&format!("{l:02}"), &color)?;
}
state.end()
swatch_object.serialize(serializer)
}
}