Merge branch 'feature/color-parameter-sliders' of https://github.com/corinna000/mystic-symbolic into corinna000-feature/color-parameter-sliders
commit
aaf8d2e1f8
|
@ -60,17 +60,18 @@ const EYE_CREATURE = (
|
|||
);
|
||||
|
||||
const RandomColorSampling: React.FC<{}> = () => {
|
||||
const [paletteConfig, setPaletteConfig] = useState({})
|
||||
const [paletteAlg, setPaletteAlg] = useState<RandomPaletteAlgorithm>(
|
||||
DEFAULT_RANDOM_PALETTE_ALGORITHM
|
||||
);
|
||||
const [seed, setSeed] = useState(Date.now());
|
||||
const NUM_COLORS = 100;
|
||||
const rng = new Random(seed);
|
||||
const palette = createRandomColorPalette(NUM_COLORS, rng, paletteAlg);
|
||||
const palette = createRandomColorPalette(NUM_COLORS, rng, paletteAlg, paletteConfig);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} />
|
||||
<PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} onPaletteConfigChange={setPaletteConfig} />
|
||||
<div className="thingy">
|
||||
<div style={{ fontSize: 0 }}>
|
||||
{range(NUM_COLORS).map((i) => (
|
||||
|
|
|
@ -1,22 +1,55 @@
|
|||
import React from "react";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {
|
||||
RandomPaletteAlgorithm,
|
||||
RANDOM_PALETTE_ALGORITHMS,
|
||||
RANDOM_PALETTE_ALGORITHMS, PaletteAlgorithmConfig,
|
||||
} from "./random-colors";
|
||||
|
||||
export type PaletteAlgorithmWidgetProps = {
|
||||
value: RandomPaletteAlgorithm;
|
||||
onChange: (value: RandomPaletteAlgorithm) => void;
|
||||
onPaletteConfigChange: (value: PaletteAlgorithmConfig) => void;
|
||||
};
|
||||
|
||||
export const PaletteAlgorithmWidget: React.FC<PaletteAlgorithmWidgetProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
onPaletteConfigChange = () => {}
|
||||
}) => {
|
||||
const id = "algorithm";
|
||||
const [paletteConfig, setPaletteConfig] = useState<PaletteAlgorithmConfig>({
|
||||
hue: 120,
|
||||
hueInterval: 15,
|
||||
saturation: 50,
|
||||
valueMin: 20,
|
||||
valueMax: 80,
|
||||
});
|
||||
useEffect(() => {
|
||||
onPaletteConfigChange(paletteConfig);
|
||||
}, [paletteConfig])
|
||||
|
||||
return (
|
||||
<div className="flex-widget thingy">
|
||||
{value === "threevals" && (
|
||||
<div className="flex-widget thingy">
|
||||
<label>Hue {paletteConfig.hue}</label>
|
||||
<input type="range" min="0" max="360" value={paletteConfig.hue}
|
||||
onChange={(e) => setPaletteConfig({...paletteConfig, hue: Number(e.target.value) }) } />
|
||||
<label>Hue Interval {paletteConfig.hueInterval}</label>
|
||||
<input type="range" min="0" max="120" value={paletteConfig.hueInterval}
|
||||
onChange={(e) => setPaletteConfig({...paletteConfig, hueInterval: Number(e.target.value) }) }
|
||||
/>
|
||||
<label>Value min {paletteConfig.valueMin}</label>
|
||||
<input type="range" min="0" max="100" value={paletteConfig.valueMin}
|
||||
onChange={(e) => setPaletteConfig({...paletteConfig, valueMin: Number(e.target.value) }) }
|
||||
/>
|
||||
<label>Value Max {paletteConfig.valueMax}</label>
|
||||
<input type="range" min="0" max="100" value={paletteConfig.valueMax}
|
||||
onChange={(e) => setPaletteConfig({...paletteConfig, valueMax: Number(e.target.value) }) }
|
||||
/>
|
||||
<label>Saturation {paletteConfig.saturation}</label>
|
||||
<input type="range" min="0" max="100" value={paletteConfig.saturation}
|
||||
onChange={(e) => setPaletteConfig({...paletteConfig, saturation: Number(e.target.value) }) }
|
||||
/></div>)}
|
||||
<label htmlFor={id}>Palette algorithm: </label>
|
||||
<select
|
||||
id={id}
|
||||
|
|
|
@ -4,8 +4,18 @@ import * as colorspaces from "colorspaces";
|
|||
import { ColorTuple, hsluvToHex } from "hsluv";
|
||||
import { clampedBytesToRGBColor } from "./color-util";
|
||||
|
||||
type RandomPaletteGenerator = (numEntries: number, rng: Random) => string[];
|
||||
//type ColorFunction = (rng: Random) => string[];
|
||||
export interface PaletteAlgorithmConfig {
|
||||
valueMin?: number,
|
||||
valueMax?: number,
|
||||
hue?: number,
|
||||
hueInterval?: number
|
||||
saturation?: number
|
||||
}
|
||||
|
||||
type RandomPaletteGenerator = (numEntries: number, rng: Random, config: PaletteAlgorithmConfig) => string[];
|
||||
// type ColorFunction = (rng: Random) => string[];
|
||||
// type ColorFunctionConfig = () => string[];
|
||||
|
||||
|
||||
export type RandomPaletteAlgorithm = "RGB" | "CIELUV" | "threevals";
|
||||
// | "randgrey"
|
||||
|
@ -80,23 +90,21 @@ function createRandGrey(rng: Random): string[] {
|
|||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function create3V180(angle1: number): ColorFunction {
|
||||
return (rng: Random): string[] => {
|
||||
let Ls = [25, 50, 75];
|
||||
function create3Vconfig() {
|
||||
return (rng: Random, config: PaletteAlgorithmConfig): string[] => {
|
||||
const LMin = config.valueMin ? config.valueMin : 25;
|
||||
const LMax = config.valueMax? config.valueMax: 75;
|
||||
let Ls = [LMin, 50, LMax];
|
||||
|
||||
//Now we have 3 lightness values, pick a random hue and sat
|
||||
let h1 = rng.inInterval({ min: 0, max: 360 }),
|
||||
h2 = 360 * (((h1 + angle1) / 360) % 1),
|
||||
h3 = 360 * (((h1 + 180) / 360) % 1);
|
||||
let h1 = config.hue ? config.hue : rng.inInterval({ min: 0, max: 360 }),
|
||||
h2 = 360 * (((h1 + (config.hueInterval ? config.hueInterval : 120)) / 360) % 1),
|
||||
h3 = 360 * (((h2 + (config.hueInterval ? config.hueInterval : 240)) / 360) % 1);
|
||||
|
||||
let Hs = [h1, h2, h3];
|
||||
|
||||
let Ss = [
|
||||
rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
];
|
||||
const sat = config.saturation ? config.saturation : rng.fromGaussian({ mean: 100, stddev: 40 });
|
||||
let Ss = [ sat, sat, sat ];
|
||||
Ss = Ss.map((x) => clamp(x, 0, 100));
|
||||
|
||||
//zip
|
||||
|
@ -108,41 +116,40 @@ function create3V180(angle1: number): ColorFunction {
|
|||
return hexcolors;
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
function threeVColor(rng: Random): string[] {
|
||||
let L1 = rng.inInterval({ min: 10, max: 25 });
|
||||
let L2 = rng.inInterval({ min: L1 + 25, max: 60 });
|
||||
let L3 = rng.inInterval({ min: L2 + 25, max: 85 });
|
||||
|
||||
let Ls = [L1, L2, L3];
|
||||
|
||||
let angleI = rng.inInterval({ min: 0, max: 120 });
|
||||
|
||||
//Now we have 3 lightness values, pick a random hue and sat
|
||||
let h1 = rng.inInterval({ min: 0, max: 360 }),
|
||||
h2 = h1 + angleI,
|
||||
h3 = 360 * ((((h1 + h2) / 2 + 180) / 360) % 1);
|
||||
|
||||
h2 = 360 * ((h2 / 360) % 1);
|
||||
|
||||
let Hs = [h1, h2, h3];
|
||||
|
||||
let Ss = [
|
||||
rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
];
|
||||
Ss = Ss.map((x) => clamp(x, 0, 100));
|
||||
|
||||
//zip
|
||||
let hsls = Ls.map((k, i) => [Hs[i], Ss[i], k]);
|
||||
let hexcolors = hsls.map((x) => hsluvToHex(x as ColorTuple));
|
||||
|
||||
//scramble order
|
||||
hexcolors = rng.uniqueChoices(hexcolors, hexcolors.length);
|
||||
return hexcolors;
|
||||
}
|
||||
// function threeVColor(rng: Random): string[] {
|
||||
// let L1 = rng.inInterval({ min: 10, max: 25 });
|
||||
// let L2 = rng.inInterval({ min: L1 + 25, max: 60 });
|
||||
// let L3 = rng.inInterval({ min: L2 + 25, max: 85 });
|
||||
//
|
||||
// let Ls = [L1, L2, L3];
|
||||
//
|
||||
// let angleI = rng.inInterval({ min: 0, max: 120 });
|
||||
//
|
||||
// //Now we have 3 lightness values, pick a random hue and sat
|
||||
// let h1 = rng.inInterval({ min: 0, max: 360 }),
|
||||
// h2 = h1 + angleI,
|
||||
// h3 = 360 * ((((h1 + h2) / 2 + 180) / 360) % 1);
|
||||
//
|
||||
// h2 = 360 * ((h2 / 360) % 1);
|
||||
//
|
||||
// let Hs = [h1, h2, h3];
|
||||
//
|
||||
// let Ss = [
|
||||
// rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
// rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
// rng.fromGaussian({ mean: 100, stddev: 40 }),
|
||||
// ];
|
||||
// Ss = Ss.map((x) => clamp(x, 0, 100));
|
||||
//
|
||||
// //zip
|
||||
// let hsls = Ls.map((k, i) => [Hs[i], Ss[i], k]);
|
||||
// let hexcolors = hsls.map((x) => hsluvToHex(x as ColorTuple));
|
||||
//
|
||||
// //scramble order
|
||||
// hexcolors = rng.uniqueChoices(hexcolors, hexcolors.length);
|
||||
// return hexcolors;
|
||||
// }
|
||||
|
||||
/*
|
||||
function threeVColor(rng: Random): string[] {
|
||||
|
@ -203,16 +210,16 @@ function createSimplePaletteGenerator(
|
|||
*/
|
||||
|
||||
function createTriadPaletteGenerator(
|
||||
createTriad: (rng: Random) => string[]
|
||||
createTriad: (rng: Random, config: PaletteAlgorithmConfig) => string[]
|
||||
): RandomPaletteGenerator {
|
||||
return (numEntries: number, rng: Random): string[] => {
|
||||
return (numEntries: number, rng: Random, config?): string[] => {
|
||||
let colors: string[] = [];
|
||||
let n = Math.floor(numEntries / 3) + 1;
|
||||
|
||||
if (numEntries == 3) {
|
||||
colors = colors.concat(createTriad(rng));
|
||||
colors = colors.concat(createTriad(rng, config));
|
||||
} else {
|
||||
for (let i = 0; i < n; i++) colors = colors.concat(createTriad(rng));
|
||||
for (let i = 0; i < n; i++) colors = colors.concat(createTriad(rng, config));
|
||||
colors = colors.slice(0, numEntries);
|
||||
}
|
||||
|
||||
|
@ -225,7 +232,8 @@ const PALETTE_GENERATORS: {
|
|||
} = {
|
||||
RGB: createSimplePaletteGenerator(createRandomRGBColor),
|
||||
CIELUV: createSimplePaletteGenerator(createRandomCIELUVColor),
|
||||
threevals: createTriadPaletteGenerator(threeVColor),
|
||||
threevals: createTriadPaletteGenerator(create3Vconfig()),
|
||||
// threevals: createTriadPaletteGenerator(threeVColor),
|
||||
//randgrey: createTriadPaletteGenerator(createRandGrey),
|
||||
//threev15: createTriadPaletteGenerator(create3V180(15)),
|
||||
//threev30: createTriadPaletteGenerator(create3V180(15)),
|
||||
|
@ -250,7 +258,8 @@ export const RANDOM_PALETTE_ALGORITHMS = Object.keys(
|
|||
export function createRandomColorPalette(
|
||||
numEntries: number,
|
||||
rng: Random = new Random(),
|
||||
algorithm: RandomPaletteAlgorithm = DEFAULT_RANDOM_PALETTE_ALGORITHM
|
||||
algorithm: RandomPaletteAlgorithm = DEFAULT_RANDOM_PALETTE_ALGORITHM,
|
||||
config: PaletteAlgorithmConfig = {},
|
||||
): string[] {
|
||||
return PALETTE_GENERATORS[algorithm](numEntries, rng);
|
||||
return PALETTE_GENERATORS[algorithm](numEntries, rng, config);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { PaletteAlgorithmWidget } from "./palette-algorithm-widget";
|
|||
import { Random } from "./random";
|
||||
import {
|
||||
createRandomColorPalette,
|
||||
DEFAULT_RANDOM_PALETTE_ALGORITHM,
|
||||
DEFAULT_RANDOM_PALETTE_ALGORITHM, PaletteAlgorithmConfig,
|
||||
RandomPaletteAlgorithm,
|
||||
} from "./random-colors";
|
||||
import { SvgCompositionContext } from "./svg-composition-context";
|
||||
|
@ -14,12 +14,14 @@ type SvgCompositionColors = Pick<
|
|||
>;
|
||||
|
||||
function createRandomCompositionColors(
|
||||
alg: RandomPaletteAlgorithm
|
||||
alg: RandomPaletteAlgorithm,
|
||||
config?: PaletteAlgorithmConfig
|
||||
): SvgCompositionColors {
|
||||
const [background, stroke, fill] = createRandomColorPalette(
|
||||
3,
|
||||
undefined,
|
||||
alg
|
||||
alg,
|
||||
config
|
||||
);
|
||||
return { background, stroke, fill };
|
||||
}
|
||||
|
@ -34,10 +36,11 @@ export const RandomizerWidget: React.FC<RandomizerWidgetProps> = (props) => {
|
|||
const [paletteAlg, setPaletteAlg] = useState<RandomPaletteAlgorithm>(
|
||||
DEFAULT_RANDOM_PALETTE_ALGORITHM
|
||||
);
|
||||
const [paletteConfig, setPaletteConfig] = useState({})
|
||||
const [randType, setRandType] = useState<RandType>("colors and symbols");
|
||||
const randomize = () => {
|
||||
if (randType === "colors" || randType === "colors and symbols") {
|
||||
props.onColorsChange(createRandomCompositionColors(paletteAlg));
|
||||
props.onColorsChange(createRandomCompositionColors(paletteAlg, paletteConfig));
|
||||
}
|
||||
if (randType === "symbols" || randType === "colors and symbols") {
|
||||
props.onSymbolsChange(new Random(Date.now()));
|
||||
|
@ -63,7 +66,7 @@ export const RandomizerWidget: React.FC<RandomizerWidgetProps> = (props) => {
|
|||
{makeRadio("symbols")}
|
||||
{makeRadio("colors and symbols")}
|
||||
{randType !== "symbols" && (
|
||||
<PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} />
|
||||
<PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} onPaletteConfigChange={setPaletteConfig} />
|
||||
)}
|
||||
{props.children}
|
||||
<button accessKey="r" onClick={randomize}>
|
||||
|
|
Plik diff jest za duży
Load Diff
Ładowanie…
Reference in New Issue