Shared/Colors Additions #145

Open
opened 2025-03-18 15:37:12 +01:00 by sora-ext · 1 comment

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#030B12" d="M0 000h100v400H000z"/> <path fill="#0C1D2E" d="M100 0h100v400H100z"/> <path fill="#203A53" d="M200 0h100v400H200z"/> <path fill="#425F7C" d="M300 0h100v400H300z"/> <path fill="#93A9BE" d="M400 0h100v400H400z"/> <path fill="#B6C5D5" d="M500 0h100v400H500z"/> <path fill="#D6DFE8" d="M600 0h100v400H600z"/> <path fill="#F0F3F7" d="M700 0h100v400H700z"/> </svg>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#1C1103" d="M0 000h100v400H000z"/> <path fill="#47300E" d="M100 0h100v400H100z"/> <path fill="#805D2B" d="M200 0h100v400H200z"/> <path fill="#BF985F" d="M300 0h100v400H300z"/> <path fill="#FFE6C1" d="M400 0h100v400H400z"/> <path fill="#FFEFD7" d="M500 0h100v400H500z"/> <path fill="#FFF6EA" d="M600 0h100v400H600z"/> <path fill="#FFFCF7" d="M700 0h100v400H700z"/> </svg>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#F59331" d="M0 000h100v400H000z"/> <path fill="#F5F531" d="M100 0h100v400H100z"/> <path fill="#93F531" d="M200 0h100v400H200z"/> <path fill="#31F593" d="M300 0h100v400H300z"/> <path fill="#3193F5" d="M400 0h100v400H400z"/> <path fill="#9331F5" d="M500 0h100v400H500z"/> <path fill="#F53193" d="M600 0h100v400H600z"/> <path fill="#F53131" d="M700 0h100v400H700z"/> </svg>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#F5B97D" d="M0 000h100v400H000z"/> <path fill="#F5F57D" d="M100 0h100v400H100z"/> <path fill="#B9F57D" d="M200 0h100v400H200z"/> <path fill="#7DF5B9" d="M300 0h100v400H300z"/> <path fill="#7DB9F5" d="M400 0h100v400H400z"/> <path fill="#B97DF5" d="M500 0h100v400H500z"/> <path fill="#F57DB9" d="M600 0h100v400H600z"/> <path fill="#F57D7D" d="M700 0h100v400H700z"/> </svg>

`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#030B12" d="M0 000h100v400H000z"/> <path fill="#0C1D2E" d="M100 0h100v400H100z"/> <path fill="#203A53" d="M200 0h100v400H200z"/> <path fill="#425F7C" d="M300 0h100v400H300z"/> <path fill="#93A9BE" d="M400 0h100v400H400z"/> <path fill="#B6C5D5" d="M500 0h100v400H500z"/> <path fill="#D6DFE8" d="M600 0h100v400H600z"/> <path fill="#F0F3F7" d="M700 0h100v400H700z"/> </svg>` `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#1C1103" d="M0 000h100v400H000z"/> <path fill="#47300E" d="M100 0h100v400H100z"/> <path fill="#805D2B" d="M200 0h100v400H200z"/> <path fill="#BF985F" d="M300 0h100v400H300z"/> <path fill="#FFE6C1" d="M400 0h100v400H400z"/> <path fill="#FFEFD7" d="M500 0h100v400H500z"/> <path fill="#FFF6EA" d="M600 0h100v400H600z"/> <path fill="#FFFCF7" d="M700 0h100v400H700z"/> </svg>` `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#F59331" d="M0 000h100v400H000z"/> <path fill="#F5F531" d="M100 0h100v400H100z"/> <path fill="#93F531" d="M200 0h100v400H200z"/> <path fill="#31F593" d="M300 0h100v400H300z"/> <path fill="#3193F5" d="M400 0h100v400H400z"/> <path fill="#9331F5" d="M500 0h100v400H500z"/> <path fill="#F53193" d="M600 0h100v400H600z"/> <path fill="#F53131" d="M700 0h100v400H700z"/> </svg>` `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400"> <path fill="#F5B97D" d="M0 000h100v400H000z"/> <path fill="#F5F57D" d="M100 0h100v400H100z"/> <path fill="#B9F57D" d="M200 0h100v400H200z"/> <path fill="#7DF5B9" d="M300 0h100v400H300z"/> <path fill="#7DB9F5" d="M400 0h100v400H400z"/> <path fill="#B97DF5" d="M500 0h100v400H500z"/> <path fill="#F57DB9" d="M600 0h100v400H600z"/> <path fill="#F57D7D" d="M700 0h100v400H700z"/> </svg>`
Author
import chroma from 'chroma-js';
import simpleColorConverter from 'simple-color-converter';

const toPantone = (v) => new simpleColorConverter({ hex: chroma.oklch(v).hex(), to: 'pantone' }).color
const Max = Math.max
const Min = Math.min

function gaussianCurve(points, mean = 0.5, sigma = 0.15) {
    const x = Array.from({ length: points + 1 }, (_, i) => i / (points));
    const invertedGaussianWeights = x.map(value => 1 - Math.exp(-Math.pow(value - mean, 2) / (2 * Math.pow(sigma, 2))));
    const weightSum = invertedGaussianWeights.reduce((sum, weight) => sum + weight, 0);
    const normalizedWeights = invertedGaussianWeights.map(weight => weight / weightSum);
    const cumulativeWeights = normalizedWeights.reduce((acc, weight) => {
        acc.push((acc[acc.length - 1] || 0) + weight);
        return acc;
    }, []);
    const min = Min(...cumulativeWeights);
    const max = Max(...cumulativeWeights);
    return cumulativeWeights.map(value => (value - min) / (max - min));
}

const lerp = (a, b, x) => (a * (1 - x) + b * x)

function getMax(l, c, h, step = 0.01) {
    for (let i = 1; i >= 0; i -= step)
        if (!chroma.oklch([l == null ? i : l, c == null ? i : c, h == null ? i : h]).clipped())
            return i
    return 0;
}

function getMin(l, c, h, step = 0.01) {
    for (let i = 0; i <= 1; i += step)
        if (!chroma.oklch([l == null ? i : l, c == null ? i : c, h == null ? i : h]).clipped())
            return i
    return 1;
}

function blendHue(a, b, weight = 0.02) {
    let mult = (((a - b + 360) % 360) < 180) ? -1 : 1;
    return (a + mult * b * weight + 360) % 360;
}

function generatePalette(primaryColor, bHs, over = 0) {
    if (!chroma.valid(primaryColor)) throw "Invalid Primary Color"
    const color = chroma(primaryColor).oklch()
    const pL = color[0] + 0.05 * over;
    const pC = color[1] - 0.02 * over;
    const pH = color[2];

    const pLp = Min(1, pL / getMax(null, pC, pH))
    const pCp = Min(1, pC / getMax(pL, null, pH))

    const palette = bHs.map(bH => {
        const h = blendHue(bH + pH, pH, 0.05);
        let l = pLp * getMax(null, pC, h) || pL
        let c = pCp * getMax(l, null, h) || pC
        for (let itr = 0; itr < 100; ++itr) {
            l = pLp * getMax(null, c, h) || pL
            c = pCp * getMax(l, null, h) || pC
        }
        return chroma.oklch([l, c, h]).oklch();
    });

    return palette;
}

function generateGrayScale(primaryColor, c) {
    if (!chroma.valid(primaryColor)) throw "Invalid Primary Color"
    const color = chroma(primaryColor).oklch()
    const pH = (color[2] + (c ? 180 : 0)) % 360;
    let bLs = gaussianCurve(12, 0.99, 0.05)
    const palette = bLs.map(bL => {
        const h = pH
        const c = lerp(getMin(bL, null, pH), getMax(bL, null, pH), 0.33)
        const l = Min(Max(bL, getMin(null, c, pH)), getMax(null, c, pH))

        return chroma.oklch([l, c, h]).oklch();
    });
    return palette;
}


const primaryColor = "#e14299";
const baseHues = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330];
let output = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 ${5 * 100}">`
for (let i = 0; i < 2; ++i) {
    output += `<g transform="translate(000 ${i * 100})">`
    const palette = generateGrayScale(primaryColor, i == 0);
    for (let j in palette) {
        output += `<path fill="${chroma.oklch(palette[j]).css('oklch')}" pantone="${toPantone(palette[j])}" d="M${j * 100} 0h100v100H${j * 100}z" />`
    }
    output += `</g > `
}
for (let i = 2; i < 6; ++i) {
    output += `<g transform="translate(000 ${i * 100})">`
    const palette = generatePalette(primaryColor, baseHues, (i - 2) * 2);
    for (let j in palette) {
        output += `<path fill="${chroma.oklch(palette[j]).css('oklch')}" pantone="${toPantone(palette[j])}" d="M${j * 100} 0h100v100H${j * 100}z" />`
    }
    output += `</g > `
}
output += `</svg > `

console.log(output)
``` import chroma from 'chroma-js'; import simpleColorConverter from 'simple-color-converter'; const toPantone = (v) => new simpleColorConverter({ hex: chroma.oklch(v).hex(), to: 'pantone' }).color const Max = Math.max const Min = Math.min function gaussianCurve(points, mean = 0.5, sigma = 0.15) { const x = Array.from({ length: points + 1 }, (_, i) => i / (points)); const invertedGaussianWeights = x.map(value => 1 - Math.exp(-Math.pow(value - mean, 2) / (2 * Math.pow(sigma, 2)))); const weightSum = invertedGaussianWeights.reduce((sum, weight) => sum + weight, 0); const normalizedWeights = invertedGaussianWeights.map(weight => weight / weightSum); const cumulativeWeights = normalizedWeights.reduce((acc, weight) => { acc.push((acc[acc.length - 1] || 0) + weight); return acc; }, []); const min = Min(...cumulativeWeights); const max = Max(...cumulativeWeights); return cumulativeWeights.map(value => (value - min) / (max - min)); } const lerp = (a, b, x) => (a * (1 - x) + b * x) function getMax(l, c, h, step = 0.01) { for (let i = 1; i >= 0; i -= step) if (!chroma.oklch([l == null ? i : l, c == null ? i : c, h == null ? i : h]).clipped()) return i return 0; } function getMin(l, c, h, step = 0.01) { for (let i = 0; i <= 1; i += step) if (!chroma.oklch([l == null ? i : l, c == null ? i : c, h == null ? i : h]).clipped()) return i return 1; } function blendHue(a, b, weight = 0.02) { let mult = (((a - b + 360) % 360) < 180) ? -1 : 1; return (a + mult * b * weight + 360) % 360; } function generatePalette(primaryColor, bHs, over = 0) { if (!chroma.valid(primaryColor)) throw "Invalid Primary Color" const color = chroma(primaryColor).oklch() const pL = color[0] + 0.05 * over; const pC = color[1] - 0.02 * over; const pH = color[2]; const pLp = Min(1, pL / getMax(null, pC, pH)) const pCp = Min(1, pC / getMax(pL, null, pH)) const palette = bHs.map(bH => { const h = blendHue(bH + pH, pH, 0.05); let l = pLp * getMax(null, pC, h) || pL let c = pCp * getMax(l, null, h) || pC for (let itr = 0; itr < 100; ++itr) { l = pLp * getMax(null, c, h) || pL c = pCp * getMax(l, null, h) || pC } return chroma.oklch([l, c, h]).oklch(); }); return palette; } function generateGrayScale(primaryColor, c) { if (!chroma.valid(primaryColor)) throw "Invalid Primary Color" const color = chroma(primaryColor).oklch() const pH = (color[2] + (c ? 180 : 0)) % 360; let bLs = gaussianCurve(12, 0.99, 0.05) const palette = bLs.map(bL => { const h = pH const c = lerp(getMin(bL, null, pH), getMax(bL, null, pH), 0.33) const l = Min(Max(bL, getMin(null, c, pH)), getMax(null, c, pH)) return chroma.oklch([l, c, h]).oklch(); }); return palette; } const primaryColor = "#e14299"; const baseHues = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]; let output = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 ${5 * 100}">` for (let i = 0; i < 2; ++i) { output += `<g transform="translate(000 ${i * 100})">` const palette = generateGrayScale(primaryColor, i == 0); for (let j in palette) { output += `<path fill="${chroma.oklch(palette[j]).css('oklch')}" pantone="${toPantone(palette[j])}" d="M${j * 100} 0h100v100H${j * 100}z" />` } output += `</g > ` } for (let i = 2; i < 6; ++i) { output += `<g transform="translate(000 ${i * 100})">` const palette = generatePalette(primaryColor, baseHues, (i - 2) * 2); for (let j in palette) { output += `<path fill="${chroma.oklch(palette[j]).css('oklch')}" pantone="${toPantone(palette[j])}" d="M${j * 100} 0h100v100H${j * 100}z" />` } output += `</g > ` } output += `</svg > ` console.log(output) ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sora/nixconfig#145
No description provided.