Add a 'randomize colors' button to mandala and creature pages. (#68)
The random colors are currently terrible! Maneesh will help us make them better. :) Also, there is some annoying code duplication going on here between the creature and mandala pages, but I really wanted to add the button to both and also want to eat dinner soon, so I am filing #67 and saving the refactoring for later.pull/72/head
rodzic
5e74ce34ea
commit
2c53e5caab
|
@ -28,6 +28,7 @@ import { ColorWidget } from "../color-widget";
|
|||
import { NumericSlider } from "../numeric-slider";
|
||||
import { DEFAULT_BG_COLOR } from "../colors";
|
||||
import { Checkbox } from "../checkbox";
|
||||
import { createRandomColorPalette } from "../random-colors";
|
||||
|
||||
/** Symbols that can be the "root" (i.e., main body) of a creature. */
|
||||
const ROOT_SYMBOLS = SvgVocabulary.items.filter(
|
||||
|
@ -192,6 +193,11 @@ export const CreaturePage: React.FC<{}> = () => {
|
|||
rng: new Random(randomSeed),
|
||||
randomlyInvert,
|
||||
});
|
||||
const randomizeColors = () => {
|
||||
const [bgColor, stroke, fill] = createRandomColorPalette(3);
|
||||
setBgColor(bgColor);
|
||||
setSymbolCtx({ ...symbolCtx, stroke, fill });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -199,6 +205,11 @@ export const CreaturePage: React.FC<{}> = () => {
|
|||
<SymbolContextWidget ctx={symbolCtx} onChange={setSymbolCtx}>
|
||||
<ColorWidget label="Background" value={bgColor} onChange={setBgColor} />{" "}
|
||||
</SymbolContextWidget>
|
||||
<div className="thingy">
|
||||
<button accessKey="c" onClick={randomizeColors}>
|
||||
Randomize <u>c</u>olors!
|
||||
</button>
|
||||
</div>
|
||||
<div className="thingy">
|
||||
<NumericSlider
|
||||
label="Random creature complexity"
|
||||
|
|
|
@ -29,6 +29,7 @@ import { Random } from "../random";
|
|||
import { PointWithNormal } from "../specs";
|
||||
import { getAttachmentTransforms } from "../attach";
|
||||
import { Checkbox } from "../checkbox";
|
||||
import { createRandomColorPalette } from "../random-colors";
|
||||
|
||||
type ExtendedMandalaCircleParams = MandalaCircleParams & {
|
||||
scaling: number;
|
||||
|
@ -268,6 +269,12 @@ export const MandalaPage: React.FC<{}> = () => {
|
|||
|
||||
const circle2SymbolCtx = invertCircle2 ? swapColors(symbolCtx) : symbolCtx;
|
||||
|
||||
const randomizeColors = () => {
|
||||
const [bgColor, stroke, fill] = createRandomColorPalette(3);
|
||||
setBgColor(bgColor);
|
||||
setBaseSymbolCtx({ ...baseSymbolCtx, stroke, fill });
|
||||
};
|
||||
|
||||
const circles = [
|
||||
<ExtendedMandalaCircle key="first" {...circle1} {...symbolCtx} />,
|
||||
];
|
||||
|
@ -293,6 +300,11 @@ export const MandalaPage: React.FC<{}> = () => {
|
|||
onChange={setBgColor}
|
||||
/>{" "}
|
||||
</SymbolContextWidget>
|
||||
<div className="thingy">
|
||||
<button accessKey="c" onClick={randomizeColors}>
|
||||
Randomize <u>c</u>olors!
|
||||
</button>
|
||||
</div>
|
||||
<fieldset>
|
||||
<legend>First circle</legend>
|
||||
<ExtendedMandalaCircleParamsWidget
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { clampedByteToHex, createRandomColorPalette } from "./random-colors";
|
||||
|
||||
describe("clampedByteToHex", () => {
|
||||
it("clamps values over 255 to 255", () => {
|
||||
expect(clampedByteToHex(500)).toBe("ff");
|
||||
});
|
||||
|
||||
it("clamps values under 0 to 0", () => {
|
||||
expect(clampedByteToHex(-50)).toBe("00");
|
||||
});
|
||||
|
||||
it("zero-pads values", () => {
|
||||
expect(clampedByteToHex(10)).toBe("0a");
|
||||
});
|
||||
|
||||
it("works with numbers that don't need zero-padding", () => {
|
||||
expect(clampedByteToHex(22)).toBe("16");
|
||||
});
|
||||
});
|
||||
|
||||
test("createRandomColorPalette() works", () => {
|
||||
const palette = createRandomColorPalette(3);
|
||||
expect(palette).toHaveLength(3);
|
||||
for (let color of palette) {
|
||||
expect(color).toMatch(/^\#[0-9a-f]{6}$/);
|
||||
}
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import { Random } from "./random";
|
||||
import { range } from "./util";
|
||||
|
||||
/**
|
||||
* Clamp the given number to be between 0 and 255, then
|
||||
* convert it to hexadecimal.
|
||||
*/
|
||||
export function clampedByteToHex(value: number): string {
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
} else if (value > 255) {
|
||||
value = 255;
|
||||
}
|
||||
let hex = value.toString(16);
|
||||
if (hex.length === 1) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
function createRandomColor(rng: Random): string {
|
||||
const rgb = range(3).map(() => rng.inRange({ min: 0, max: 255, step: 1 }));
|
||||
return "#" + rgb.map(clampedByteToHex).join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random color palette with the given number of
|
||||
* entries, optionally using the given random number generator.
|
||||
*
|
||||
* The return value is an Array of strings, where each string is
|
||||
* a color hex hash (e.g. `#ff0000`).
|
||||
*/
|
||||
export function createRandomColorPalette(
|
||||
numEntries: number,
|
||||
rng: Random = new Random()
|
||||
): string[] {
|
||||
return range(numEntries).map(() => createRandomColor(rng));
|
||||
}
|
Ładowanie…
Reference in New Issue