Compare commits

...

2 Commits

Author SHA1 Message Date
徐涛
7fba372d08 调整M3的导出格式。 2025-03-07 10:41:44 +08:00
徐涛
f3f259fd1c 增加构建M3各个色盘的能力。 2025-03-07 09:42:24 +08:00
4 changed files with 149 additions and 7 deletions

View File

@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::str::FromStr;
pub use baseline::M3BaselineColors;
@ -5,6 +6,7 @@ pub use color_set::M3ColorSet;
use palette::{IntoColor, Lch, Srgb};
use serde::Serialize;
pub use surface::M3SurfaceSet;
pub use swatch::M3PaletteSwatch;
pub use tonal_palette::TonalPalette;
use crate::convert::map_lch_to_srgb_hex;
@ -15,6 +17,7 @@ use super::SchemeExport;
mod baseline;
mod color_set;
mod surface;
mod swatch;
mod tonal_palette;
#[derive(Debug, Clone, Serialize)]
@ -23,6 +26,7 @@ pub struct MaterialDesign3Scheme {
pub black: String,
pub light_baseline: M3BaselineColors,
pub dark_baseline: M3BaselineColors,
pub swatches: HashMap<String, M3PaletteSwatch>,
}
impl MaterialDesign3Scheme {
@ -43,11 +47,20 @@ impl MaterialDesign3Scheme {
let nv = TonalPalette::from_hue_and_chroma(source_hue, (source.chroma / 6.0).min(8.0));
let e = TonalPalette::from_hue_and_chroma(error.hue.into_positive_degrees(), 84.0);
let mut swatches = HashMap::new();
swatches.insert("primary".to_string(), M3PaletteSwatch::new(&p));
swatches.insert("secondary".to_string(), M3PaletteSwatch::new(&s));
swatches.insert("tertiary".to_string(), M3PaletteSwatch::new(&t));
swatches.insert("error".to_string(), M3PaletteSwatch::new(&e));
swatches.insert("neutral".to_string(), M3PaletteSwatch::new(&n));
swatches.insert("neutral_variant".to_string(), M3PaletteSwatch::new(&nv));
Ok(Self {
white: map_lch_to_srgb_hex(&Lch::new(100.0, 0.0, 0.0)),
black: map_lch_to_srgb_hex(&Lch::new(0.0, 0.0, 0.0)),
light_baseline: M3BaselineColors::new(&p, &s, &t, &n, &nv, &e, false),
dark_baseline: M3BaselineColors::new(&p, &s, &t, &n, &nv, &e, true),
swatches,
})
}
@ -64,15 +77,21 @@ impl MaterialDesign3Scheme {
let palette = TonalPalette::from_hue_and_chroma(hue, custom_color.chroma);
self.light_baseline.add_custom_set(name.clone(), &palette);
self.dark_baseline.add_custom_set(name.clone(), &palette);
self.swatches.insert(name, M3PaletteSwatch::new(&palette));
Ok(())
}
pub fn full_custom(light_baseline: M3BaselineColors, dark_baseline: M3BaselineColors) -> Self {
pub fn full_custom(
light_baseline: M3BaselineColors,
dark_baseline: M3BaselineColors,
swatches: HashMap<String, M3PaletteSwatch>,
) -> Self {
Self {
white: map_lch_to_srgb_hex(&Lch::new(100.0, 0.0, 0.0)),
black: map_lch_to_srgb_hex(&Lch::new(0.0, 0.0, 0.0)),
light_baseline,
dark_baseline,
swatches,
}
}
}
@ -85,6 +104,9 @@ impl SchemeExport for MaterialDesign3Scheme {
css_variables.push(format!("--color-black: #{};", self.black));
css_variables.extend(self.light_baseline.to_css_variables());
css_variables.extend(self.dark_baseline.to_css_variables());
for (name, swatch) in &self.swatches {
css_variables.extend(swatch.to_css_variables(name));
}
css_variables.join("\n")
}
@ -96,6 +118,9 @@ impl SchemeExport for MaterialDesign3Scheme {
scss_variables.push(format!("$color-black: #{};", self.black));
scss_variables.extend(self.light_baseline.to_scss_variables());
scss_variables.extend(self.dark_baseline.to_scss_variables());
for (name, swatch) in &self.swatches {
scss_variables.extend(swatch.to_scss_variables(name));
}
scss_variables.join("\n")
}
@ -111,8 +136,7 @@ impl SchemeExport for MaterialDesign3Scheme {
self.light_baseline
.to_javascript_object_fields()
.into_iter()
.map(|s| format!(" {}", s))
.collect::<Vec<String>>(),
.map(|s| format!(" {}", s)),
);
js_object.push(" },".to_string());
js_object.push(" dark: {".to_string());
@ -120,10 +144,19 @@ impl SchemeExport for MaterialDesign3Scheme {
self.dark_baseline
.to_javascript_object_fields()
.into_iter()
.map(|s| format!(" {}", s))
.collect::<Vec<String>>(),
.map(|s| format!(" {}", s)),
);
js_object.push(" },".to_string());
js_object.push(" swatches: {".to_string());
for (name, swatch) in &self.swatches {
js_object.extend(
swatch
.to_javascript_object_fields(name)
.into_iter()
.map(|s| format!(" {}", s)),
);
}
js_object.push(" }".to_string());
js_object.push("}".to_string());
js_object.join("\n")

View File

@ -0,0 +1,74 @@
use std::collections::HashMap;
use serde::Serialize;
use crate::convert::map_lch_to_srgb_hex;
use super::TonalPalette;
static SWATCH_TONES: [u8; 18] = [
0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 95, 98, 99, 100,
];
#[derive(Debug, Clone, Serialize)]
pub struct M3PaletteSwatch(HashMap<u8, String>);
impl M3PaletteSwatch {
pub fn new(palette: &TonalPalette) -> Self {
let mut swatch = HashMap::new();
for &tone in SWATCH_TONES.iter() {
let color = palette.tone(tone as f32);
swatch.insert(tone, map_lch_to_srgb_hex(&color));
}
Self(swatch)
}
pub fn to_css_variables(&self, name: &str) -> Vec<String> {
let mut variable_lines = Vec::new();
let name = name.replace('_', "-").to_lowercase();
for &tone in SWATCH_TONES.iter() {
let color = self.0.get(&tone).unwrap();
variable_lines.push(format!("--color-swatch-{}-{}: #{};", name, tone, color));
}
variable_lines
}
pub fn to_scss_variables(&self, name: &str) -> Vec<String> {
let mut variable_lines = Vec::new();
let name = name.replace('_', "-").to_lowercase();
for &tone in SWATCH_TONES.iter() {
let color = self.0.get(&tone).unwrap();
variable_lines.push(format!("$color-swatch-{}-{}: #{};", name, tone, color));
}
variable_lines
}
pub fn to_javascript_object_fields(&self, name: &str) -> Vec<String> {
let mut js_object = Vec::new();
let name = name
.split('_')
.enumerate()
.map(|(i, part)| {
if i == 0 {
part.to_string()
} else {
let mut c = part.chars();
c.next().unwrap().to_uppercase().collect::<String>() + c.as_str()
}
})
.collect::<String>();
js_object.push(format!("{}: {{", name));
for &tone in SWATCH_TONES.iter() {
let color = self.0.get(&tone).unwrap();
js_object.push(format!(" {}: '#{}',", tone, color));
}
js_object.push("},".to_string());
js_object
}
}

View File

@ -7,7 +7,7 @@ use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
use crate::{cond, convert::map_lch_to_srgb_hex, errors};
use super::material_design_3::{M3BaselineColors, M3ColorSet, M3SurfaceSet};
use super::material_design_3::{M3BaselineColors, M3ColorSet, M3PaletteSwatch, M3SurfaceSet};
pub use constants::Variant;
mod constants;
@ -147,6 +147,40 @@ pub fn build_baseline(scheme: &DynamicScheme) -> M3BaselineColors {
)
}
pub fn build_swatches(scheme: &DynamicScheme) -> HashMap<String, M3PaletteSwatch> {
let mut swatches = HashMap::new();
swatches.insert(
"primary".to_string(),
M3PaletteSwatch::new(&scheme.primary_palette),
);
swatches.insert(
"secondary".to_string(),
M3PaletteSwatch::new(&scheme.secondary_palette),
);
swatches.insert(
"tertiary".to_string(),
M3PaletteSwatch::new(&scheme.tertiary_palette),
);
swatches.insert(
"error".to_string(),
M3PaletteSwatch::new(&scheme.error_palette),
);
swatches.insert(
"neutral".to_string(),
M3PaletteSwatch::new(&scheme.neutral_palette),
);
swatches.insert(
"neutral_variant".to_string(),
M3PaletteSwatch::new(&scheme.neutral_variant_palette),
);
for (name, palette) in &scheme.custom_palettes {
swatches.insert(name.clone(), M3PaletteSwatch::new(palette));
}
swatches
}
pub fn build_dynamic_scheme(
source_color: &str,
error_color: Option<String>,

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use material_design_2::MaterialDesign2Scheme;
use material_design_3::MaterialDesign3Scheme;
use material_design_3_dynamic::{build_baseline, build_dynamic_scheme, Variant};
use material_design_3_dynamic::{build_baseline, build_dynamic_scheme, build_swatches, Variant};
use q_style::{QScheme, SchemeSetting};
use swatch_style::{SwatchEntry, SwatchSchemeSetting};
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
@ -180,6 +180,7 @@ pub fn generate_material_design_3_dynamic_scheme(
let scheme = MaterialDesign3Scheme::full_custom(
build_baseline(&light_scheme),
build_baseline(&dark_scheme),
build_swatches(&light_scheme),
);
Ok(serde_wasm_bindgen::to_value(&(