Optimize parallax

This commit is contained in:
Schmelczer András 2019-12-25 22:30:44 +01:00
parent 5a87d2db71
commit da9d0a1136
15 changed files with 135 additions and 207 deletions

View file

@ -1,25 +1,23 @@
import { html } from "../../model/misc";
import "./background.scss";
import { fixedSeedRandom } from "../../framework/helper";
export const generate = (
count: number,
probability: number,
width: number,
color: string,
translateZ: number
color?: () => string,
height?: () => number,
transform?: () => string
): html => `
<section class="background">
${new Array(count)
.fill(0, 0, count)
.map(_ =>
fixedSeedRandom() < probability
? `<div style="width: ${width}px; height: ${width *
(fixedSeedRandom() + 0.1) *
10}px; background-color: ${color}; transform: translateZ(${translateZ}px) rotate(-20deg);"
></div>`
: `<div class="gap"></div>`
)
.join("")}
${
count > 0
? new Array(count)
.fill(0, 0, count)
.map(
_ =>
`<div style="background-color: ${color()}; height: ${height()}px; transform: ${transform()}"></div>`
)
.join("")
: ""
}
</section>
`;

View file

@ -5,19 +5,15 @@
position: absolute;
left: 0;
top: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
margin-top: -20vh;
width: 400%;
z-index: -1;
transform-style: preserve-3d;
overflow: hidden;
div {
border-radius: 10000px;
margin: 10vh 10vw;
&.gap {
visibility: hidden;
}
position: absolute;
left: 0;
top: 0;
width: 100px;
}
}

View file

@ -1,34 +1,82 @@
import { PageElement } from "../../framework/page-element";
import { generate } from "./background.html";
import { createElement } from "../../framework/helper";
import {
choose,
createElement,
randomFactory,
randomInInterval,
sum
} from "../../framework/helper";
import { PageEvent, PageEventType } from "../../framework/page-event";
export class PageBackground extends PageElement {
public constructor(
private speed: number,
count: number,
width: number,
probability: number,
color: string,
translateZ: number
) {
private colors = ["#fff9e077", "#ffd6d677"];
private blobSize = 150; // with margin
private perspective = 5;
public constructor() {
super();
this.setElement(
createElement(generate(count, probability, width, color, translateZ))
);
this.setElement(createElement(generate(0)));
}
protected handleEvent(event: PageEvent, parent: PageElement) {
if (event.type === PageEventType.onLoad) {
window.addEventListener("resize", this.resize.bind(this, parent));
this.resize(parent);
window.addEventListener("load", this.resize.bind(this, parent));
} else if (event.type === PageEventType.onBodyDimensionsChanged) {
this.resize(parent);
}
}
private resize(parent: PageElement) {
const width = parent.getElement().clientWidth;
const height = parent.getElement().clientHeight;
const siblings: Array<HTMLElement> = Array.prototype.slice
.call(parent.getElement().children)
.filter(e => e !== this.getElement());
const width = document.body.clientWidth;
const height = sum(
siblings.map(c => {
const computedStyle = window.getComputedStyle(c);
return (
c.clientHeight +
parseInt(computedStyle.marginTop) +
parseInt(computedStyle.marginBottom) +
parseInt(computedStyle.borderTopWidth) +
parseInt(computedStyle.borderBottomWidth)
);
})
);
const random = randomFactory(42);
const count = Math.round((width * height) / this.blobSize ** 2);
const randomWithKnownZ = (z: number, bound: number): number => {
const l = (bound * (this.perspective + z)) / this.perspective;
return randomInInterval(-(l / 2 - bound / 2), l / 2 + bound / 2, random);
};
this.setElement(
createElement(
generate(
count,
() => choose(this.colors, random),
() => randomInInterval(150, 750, random),
() => {
const z = randomInInterval(-5, -15, random);
return `
translateX(${randomWithKnownZ(-z, width)}px)
translateY(${randomWithKnownZ(-z, height)}px)
translateZ(${z}px)
rotate(-20deg)
`;
}
)
)
);
this.getElement().style.width = `${width}px`;
this.getElement().style.height = `${height}px`;
}
}

View file

@ -3,7 +3,7 @@ import { html } from "../../model/misc";
import "./footer.scss";
export const generate = ({ email, cv }: Footer, cvName: string): html => `
<footer>
<footer id="page-footer">
<a id="email" href="mailto:${email}">${email}</a>
<a id="cv" href="mailto:${cv}">${cvName}</a>
</footer>

View file

@ -1,8 +1,8 @@
@import "../../style/mixins";
@import "../../style/vars";
footer {
footer#page-footer {
@include card();
@include center-children();
margin: $normal-margin 0;
margin: $normal-margin auto;
}

View file

@ -11,8 +11,7 @@ export const create = ({ config, header, timeline, footer }: Portfolio) => {
new Page(
[
new PageBackground(0.1, 200, 140, 0.4, "#fff9e0aa", -15),
new PageBackground(0.15, 300, 80, 0.3, "#ffd6d6aa", -10),
new PageBackground(),
new PageHeader(header, config.aPictureOf),
new PageTimeline(timeline, config.showMore, config.showLess),
new PageFooter(footer, config.cvName),