99 lines
2.3 KiB
TypeScript
99 lines
2.3 KiB
TypeScript
|
import { JSX } from "preact";
|
||
|
import { Main, render_and_copy } from "./common.tsx";
|
||
|
|
||
|
const Bar = ({
|
||
|
color,
|
||
|
animation_time,
|
||
|
side,
|
||
|
}: {
|
||
|
color: string;
|
||
|
animation_time: number;
|
||
|
side: "left" | "right";
|
||
|
}): JSX.Element => (
|
||
|
<div class="bar">
|
||
|
<div
|
||
|
class="bar-inner"
|
||
|
style={{
|
||
|
transform: `translateX(${side == "left" ? -100 : 100}%)`,
|
||
|
backgroundColor: color,
|
||
|
animation: `${animation_time}s alternate-reverse ease infinite spin`,
|
||
|
outline: `1px solid ${color}`,
|
||
|
}}
|
||
|
></div>
|
||
|
</div>
|
||
|
);
|
||
|
|
||
|
function coprime(a: number, b: number): boolean {
|
||
|
if (a == b) return false;
|
||
|
for (let i = 2; i < Math.min(a, b); i++) {
|
||
|
if (a % i == 0 && b % i == 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
function next_coprime(ns: number[]): number {
|
||
|
if (ns.length == 0) return 2;
|
||
|
|
||
|
for (let a = ns.at(-1) ?? 0; ; a++) {
|
||
|
let good = true;
|
||
|
for (const b of ns) {
|
||
|
if (!coprime(a, b)) good = false;
|
||
|
}
|
||
|
if (good) return a;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function gen_coprimes(to: number): number[] {
|
||
|
if (to <= 0) return [];
|
||
|
if (to == 1) return [2];
|
||
|
|
||
|
const xs = gen_coprimes(to - 1);
|
||
|
return [...xs, next_coprime(xs)];
|
||
|
}
|
||
|
|
||
|
const BarPair = ({
|
||
|
color,
|
||
|
animation_time,
|
||
|
num_bars,
|
||
|
}: {
|
||
|
color: string;
|
||
|
animation_time: number;
|
||
|
num_bars: number;
|
||
|
}): JSX.Element => (
|
||
|
<div class="bar-pair" style={{ height: `${(1 / num_bars) * 100}%` }}>
|
||
|
<Bar color={color} animation_time={animation_time} side="left" />
|
||
|
<Bar color={color} animation_time={animation_time} side="right" />
|
||
|
</div>
|
||
|
);
|
||
|
|
||
|
const Bars = ({ colors }: { colors: string[] }): JSX.Element => (
|
||
|
<Main>
|
||
|
{...colors.map((c, i) => (
|
||
|
<BarPair
|
||
|
color={c}
|
||
|
animation_time={2 ** i * 0.1}
|
||
|
num_bars={colors.length}
|
||
|
/>
|
||
|
))}
|
||
|
</Main>
|
||
|
);
|
||
|
|
||
|
render_and_copy(
|
||
|
<Bars
|
||
|
colors={[
|
||
|
"#FF6961",
|
||
|
"#FFB347",
|
||
|
"#FFFF99",
|
||
|
"#77DD77",
|
||
|
"#ADD8E6",
|
||
|
"#B19CD9",
|
||
|
"rgb(var(--color-longan))",
|
||
|
"rgb(var(--color-mango))",
|
||
|
"rgb(var(--color-strawberry))",
|
||
|
"rgb(var(--color-cherry))",
|
||
|
]}
|
||
|
/>
|
||
|
);
|