css-doodle/src/shapes.js

203 lines
3.8 KiB
JavaScript

import { minmax } from './utils';
const { cos, sin, sqrt, pow, PI } = Math;
const DEG = PI / 180;
function polygon(option, fn) {
if (typeof arguments[0] == 'function') {
fn = option;
option = {};
}
if (!fn) {
fn = t => [ cos(t), sin(t) ];
}
var split = option.split || 120;
var scale = option.scale || 1;
var start = DEG * (option.start || 0);
var deg = option.deg ? (option.deg * DEG) : (PI / (split / 2));
var points = [];
for (var i = 0; i < split; ++i) {
var t = start + deg * i;
var [x, y] = fn(t);
points.push(
((x * 50 * scale) + 50 + '% ') +
((y * 50 * scale) + 50 + '%')
);
}
return `polygon(${ points.join(',') })`;
}
function rotate(x, y, deg) {
var rad = DEG * deg;
return [
x * cos(rad) - y * sin(rad),
y * cos(rad) + x * sin(rad)
];
}
export function circle() {
return 'circle(49%)';
}
export function triangle() {
return polygon({ split: 3, start: -90 }, t => [
cos(t) * 1.1,
sin(t) * 1.1 + .2
]);
}
export function rhombus() {
return polygon({ split: 4 });
}
export function pentagon() {
return polygon({ split: 5, start: 54 });
}
export function hexgon() {
return polygon({ split: 6, start: 30 });
}
export function hexagon() {
return polygon({ split: 6, start: 30 });
}
export function heptagon() {
return polygon({ split: 7, start: -90});
}
export function octagon() {
return polygon({ split: 8});
}
export function star() {
return polygon({ split: 5, start: 54, deg: 144 });
}
export function diamond() {
return 'polygon(50% 5%, 80% 50%, 50% 95%, 20% 50%)';
}
export function cross() {
return `polygon(
5% 35%, 35% 35%, 35% 5%, 65% 5%,
65% 35%, 95% 35%, 95% 65%, 65% 65%,
65% 95%, 35% 95%, 35% 65%, 5% 65%
)`;
}
export function clover(k = 3) {
k = minmax(k, 3, 5);
if (k == 4) k = 2;
return polygon({ split: 240 }, t => {
var x = cos(k * t) * cos(t);
var y = cos(k * t) * sin(t);
if (k == 3) x -= .2;
if (k == 2) {
x /= 1.1;
y /= 1.1;
}
return [x, y];
});
}
export function hypocycloid(k = 3) {
k = minmax(k, 3, 6);
var m = 1 - k;
return polygon({ scale: 1 / k }, t => {
var x = m * cos(t) + cos(m * (t - PI));
var y = m * sin(t) + sin(m * (t - PI));
if (k == 3) {
x = x * 1.1 - .6;
y = y * 1.1
}
return [x, y];
});
}
export function astroid() {
return hypocycloid(4);
}
export function infinity() {
return polygon(t => {
var a = .7 * sqrt(2) * cos(t);
var b = (pow(sin(t), 2) + 1);
return [
a / b,
a * sin(t) / b
]
});
}
export function heart() {
return polygon(t => {
var x = .75 * pow(sin(t), 3);
var y =
cos(1 * t) * (13 / 18)
- cos(2 * t) * (5 / 18)
- cos(3 * t) / 18
- cos(4 * t) / 18;
return rotate(
x * 1.2,
(y + .2) * 1.1,
180
);
});
}
export function bean() {
return polygon(t => {
var [a, b] = [pow(sin(t), 3), pow(cos(t), 3)];
return rotate(
(a + b) * cos(t) * 1.3 - .45,
(a + b) * sin(t) * 1.3 - .45,
-90
);
});
}
export function bicorn() {
return polygon(t => rotate(
cos(t),
pow(sin(t), 2) / (2 + sin(t)) - .5,
180
));
}
export function pear() {
return polygon(t => [
sin(t),
(1 + sin(t)) * cos(t) / 1.4
]);
}
export function fish() {
return polygon(t => [
cos(t) - pow(sin(t), 2) / sqrt(2),
sin(2 * t) / 2
]);
}
export function whale() {
return polygon({ split: 240 }, t => {
var r = 3.4 * (pow(sin(t), 2) - .5) * cos(t);
return rotate(
cos(t) * r + .75,
sin(t) * r * 1.2,
180
);
});
}
export function bud(n = 3) {
n = minmax(n, 3, 10);
return polygon({ split: 240 }, t => [
((1 + .2 * cos(n * t)) * cos(t)) * .8,
((1 + .2 * cos(n * t)) * sin(t)) * .8
]);
}