schmelczer-dev/src/page/background/blob.ts
2020-11-17 20:52:59 +01:00

97 lines
2.5 KiB
TypeScript

import { Vec2 } from './vec2';
import { Vec3 } from './vec3';
import { mixColors } from '../../helper/mix-colors';
import { Random } from '../../helper/random';
import { Animation } from './animation';
import { PageBackground } from './background';
export class Blob {
private static readonly DARK_COLORS = ['#2c477a'];
private static readonly LIGHT_COLORS = ['#fff9e0', '#ffd6d6'];
private static readonly ROTATION = (-20 / 180) * Math.PI;
private static readonly CREATOR_RANDOM = new Random(51);
private static colorPickerRandom = new Random(132);
private static isDarkThemed = false;
public static changeTheme(isDarkThemed: boolean) {
Blob.colorPickerRandom = new Random(132);
Blob.isDarkThemed = isDarkThemed;
}
public readonly z = Blob.CREATOR_RANDOM.randomInInterval(
PageBackground.Z_MIN,
PageBackground.Z_MAX
);
private color: Animation<string>;
private readonly positionQ = new Vec2(
Blob.CREATOR_RANDOM.next,
Blob.CREATOR_RANDOM.next
);
private _positionScale = new Vec2(0, 0);
private _positionOffset = new Vec2(0, 0);
private readonly _size = new Vec2(140, Blob.CREATOR_RANDOM.randomInInterval(260, 740));
public constructor() {
this.decideColor();
}
public decideColor() {
const target = mixColors(
Blob.isDarkThemed ? '#242638' : '#ffffff',
Blob.colorPickerRandom.choose(
Blob.isDarkThemed ? Blob.DARK_COLORS : Blob.LIGHT_COLORS
),
(this.z - PageBackground.Z_MIN) / (PageBackground.Z_MAX - PageBackground.Z_MIN)
);
this.color = new Animation<string>(
this.color ? this.color.value : target,
target,
250,
(f, t, q) => mixColors(f, t, 1 - q)
);
}
public step(value) {
this.color?.step(value);
}
public get topLeft(): Vec3 {
return Vec3.from(
this.positionQ.multiply(this._positionScale).add(this._positionOffset),
this.z
);
}
public get size(): Vec2 {
return this._size;
}
public set positionScale(value: Vec2) {
this._positionScale = value;
}
public set positionOffset(value: Vec2) {
this._positionOffset = value;
}
public draw(ctx: CanvasRenderingContext2D, position: Vec2, size: Vec2) {
ctx.save();
ctx.translate(position.x, position.y);
ctx.rotate(Blob.ROTATION);
ctx.beginPath();
ctx.arc(0, size.x / 2, size.x / 2, Math.PI, 0);
ctx.arc(0, size.y - size.x / 2, size.x / 2, 0, Math.PI);
ctx.closePath();
ctx.fillStyle = this.color.value;
ctx.fill();
ctx.restore();
}
}