Add dark mode
This commit is contained in:
parent
48a55a4a97
commit
073f087e52
40 changed files with 864 additions and 531 deletions
|
|
@ -2,7 +2,5 @@ import { html } from '../../model/misc';
|
|||
import './background.scss';
|
||||
|
||||
export const generate = (): html => `
|
||||
<section id="background-container">
|
||||
<section id="background"></section>
|
||||
</section>
|
||||
<div class="background-element"></div>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,43 +1,39 @@
|
|||
@import '../../style/vars';
|
||||
@import '../../style/mixins';
|
||||
|
||||
#background-container {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
@include responsive() using ($vars) {
|
||||
div.background-element {
|
||||
position: -webkit-sticky;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 100px;
|
||||
width: 140px;
|
||||
|
||||
z-index: -1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
perspective: 5px;
|
||||
perspective-origin: center center;
|
||||
overflow: hidden;
|
||||
overflow: visible !important; // IE11 fix for disappearing elements
|
||||
|
||||
#background {
|
||||
overflow: hidden;
|
||||
will-change: width, height;
|
||||
transition: height $long-transition-time, width $long-transition-time;
|
||||
transform-style: flat;
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
& {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
position: -webkit-sticky;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 100px;
|
||||
width: 140px;
|
||||
@media print {
|
||||
& {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
transition: transform $long-transition-time, opacity $long-transition-time;
|
||||
will-change: transform, opacity;
|
||||
animation: fade-in 1s linear;
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
transition: transform map_get($vars, $long-transition-time),
|
||||
opacity map_get($vars, $long-transition-time);
|
||||
will-change: transform, opacity;
|
||||
animation: fade-in 1s linear;
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { PageElement } from '../../framework/page-element';
|
||||
import { PageEvent, PageEventType } from '../../framework/page-event';
|
||||
import { createElement } from '../../framework/helper/create-element';
|
||||
import { Blob } from './blob';
|
||||
import { generate } from './background.html';
|
||||
import { Random } from '../../framework/helper/random';
|
||||
import { getHeight } from '../../framework/helper/get-height';
|
||||
import { sum } from '../../framework/helper/sum';
|
||||
|
|
@ -12,7 +10,7 @@ export class PageBackground extends PageElement {
|
|||
private readonly blobSpacing = 350;
|
||||
|
||||
public constructor(private start: PageElement, private end: PageElement) {
|
||||
super(createElement(generate()));
|
||||
super();
|
||||
Blob.initialize(10, 30, 5);
|
||||
}
|
||||
|
||||
|
|
@ -21,37 +19,33 @@ export class PageBackground extends PageElement {
|
|||
this.bindListeners(parent);
|
||||
} else if (event.type === PageEventType.onBodyDimensionsChanged) {
|
||||
this.resize(parent, event.data?.deltaHeight);
|
||||
} else if (event.type === PageEventType.pageThemeChanged) {
|
||||
Blob.changeTheme(event.data);
|
||||
this.blobs.forEach(b => b.decideColor());
|
||||
}
|
||||
}
|
||||
|
||||
private bindListeners(parent: PageElement) {
|
||||
window.addEventListener('resize', () => this.resize(parent));
|
||||
window.addEventListener('load', () => this.resize(parent));
|
||||
parent.element.addEventListener(
|
||||
'scroll',
|
||||
() => (this.element.scrollTop = parent.element.scrollTop)
|
||||
);
|
||||
}
|
||||
|
||||
private resize(parent: PageElement, heightChange?: number) {
|
||||
const siblings: Array<HTMLElement> = this.getSiblings(parent);
|
||||
const siblings: Array<HTMLElement> = PageBackground.getSiblings(parent);
|
||||
|
||||
const width = parent.element.clientWidth;
|
||||
const width = document.body.clientWidth;
|
||||
let height = sum(siblings.map(getHeight));
|
||||
if (heightChange) {
|
||||
height += heightChange;
|
||||
}
|
||||
|
||||
this.query('#background').style.width = `${width}px`;
|
||||
this.query('#background').style.height = `${height}px`;
|
||||
|
||||
const requiredBlobCount = Math.round(
|
||||
(width * height) / this.blobSpacing ** 2
|
||||
);
|
||||
|
||||
while (requiredBlobCount > this.blobs.length) {
|
||||
const blob = new Blob();
|
||||
this.query('#background').appendChild(blob.htmlElement);
|
||||
parent.element.appendChild(blob.htmlElement);
|
||||
this.blobs.push(blob);
|
||||
}
|
||||
|
||||
|
|
@ -74,9 +68,9 @@ export class PageBackground extends PageElement {
|
|||
});
|
||||
}
|
||||
|
||||
private getSiblings(parent: PageElement): Array<HTMLElement> {
|
||||
private static getSiblings(parent: PageElement): Array<HTMLElement> {
|
||||
return Array.prototype.slice
|
||||
.call(parent.element.children)
|
||||
.filter(e => e !== this.element);
|
||||
.filter((e: HTMLElement) => !e.classList.contains('background-element'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
import { mixColors } from '../../framework/helper/mix-colors';
|
||||
import { createElement } from '../../framework/helper/create-element';
|
||||
import { Random } from '../../framework/helper/random';
|
||||
import { generate } from './background.html';
|
||||
|
||||
export class Blob {
|
||||
private static readonly creatorRandom = new Random(44);
|
||||
private static readonly colors = ['#fff9e0', '#ffd6d6'];
|
||||
private static colorPickerRandom = new Random(132);
|
||||
private static readonly lightColors = ['#fff9e0', '#ffd6d6'];
|
||||
private static readonly darkColors = ['#2C477A'];
|
||||
private static isDarkThemed = false;
|
||||
private static zMin: number;
|
||||
private static zMax: number;
|
||||
private static perspective: number;
|
||||
|
|
@ -14,25 +18,36 @@ export class Blob {
|
|||
Blob.perspective = perspective;
|
||||
}
|
||||
|
||||
public static changeTheme(isDarkThemed: boolean) {
|
||||
Blob.colorPickerRandom = new Random(132);
|
||||
Blob.isDarkThemed = isDarkThemed;
|
||||
}
|
||||
|
||||
private readonly z = Blob.creatorRandom.randomInInterval(
|
||||
Blob.zMin,
|
||||
Blob.zMax
|
||||
);
|
||||
|
||||
private readonly element: HTMLElement = createElement('<div></div>');
|
||||
private readonly element: HTMLElement = createElement(generate());
|
||||
constructor() {
|
||||
this.element.style.backgroundColor = mixColors(
|
||||
'#ffffff',
|
||||
Blob.creatorRandom.choose(Blob.colors),
|
||||
(this.z - Blob.zMin) / (Blob.zMax - Blob.zMin)
|
||||
);
|
||||
this.element.style.zIndex = (-this.z).toString();
|
||||
this.decideColor();
|
||||
this.element.style.zIndex = Math.round(-this.z).toString();
|
||||
this.element.style.height = `${Blob.creatorRandom.randomInInterval(
|
||||
160,
|
||||
740
|
||||
)}px`;
|
||||
}
|
||||
|
||||
public decideColor() {
|
||||
this.element.style.backgroundColor = mixColors(
|
||||
Blob.isDarkThemed ? '#242638 ' : '#ffffff',
|
||||
Blob.colorPickerRandom.choose(
|
||||
Blob.isDarkThemed ? Blob.darkColors : Blob.lightColors
|
||||
),
|
||||
(this.z - Blob.zMin) / (Blob.zMax - Blob.zMin)
|
||||
);
|
||||
}
|
||||
|
||||
get htmlElement(): HTMLElement {
|
||||
return this.element;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue