From 98160edc724b8fa15ba46adac93457f29a659087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schmelczer=20Andr=C3=A1s?= Date: Sat, 28 Dec 2019 17:21:35 +0100 Subject: [PATCH] quicksave --- .idea/dictionaries/Schme.xml | 1 + .idea/inspectionProfiles/Project_Default.xml | 1 - .idea/workspace.xml | 44 ++++---- .stylelintrc | 9 -- package.json | 1 + src/dummy.scss | 8 -- src/framework/helper.ts | 48 +++++++++ src/index.html | 2 + src/page/about/about.html.ts | 8 +- src/page/about/about.scss | 55 +++++----- src/page/about/about.ts | 2 +- src/page/background/background.html.ts | 20 ++-- src/page/background/background.scss | 2 + src/page/background/background.ts | 101 ++++++++++++------- src/page/content/content.scss | 6 +- src/page/footer/footer.scss | 8 +- src/page/image-viewer/image-viewer.ts | 2 +- src/page/index.ts | 10 +- src/portfolio.ts | 2 +- src/style/mixins.scss | 11 +- src/style/vars.scss | 5 +- src/styles.scss | 24 +++-- webpack.config.js | 9 +- 23 files changed, 226 insertions(+), 153 deletions(-) delete mode 100644 .stylelintrc delete mode 100644 src/dummy.scss diff --git a/.idea/dictionaries/Schme.xml b/.idea/dictionaries/Schme.xml index 899d7ff..506ae37 100644 --- a/.idea/dictionaries/Schme.xml +++ b/.idea/dictionaries/Schme.xml @@ -1,6 +1,7 @@ + ffffff opacify raleway transparentize diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index d021f04..4713612 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,6 +2,5 @@ \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d0d62e1..0ff21ba 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,29 +2,27 @@ - - - + + - - - - - + + + + + + + + - + - - - + - - - + @@ -60,17 +58,15 @@ + + + - - - - - @@ -78,6 +74,11 @@ + + + + + diff --git a/.stylelintrc b/.stylelintrc deleted file mode 100644 index 8230eb2..0000000 --- a/.stylelintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "rules": { - "at-rule-no-unknown": [ - true, { - "ignoreAtRules": ["use", "mixin", "include"] - } - ] - } -} diff --git a/package.json b/package.json index 79101c3..d9a449c 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "css-loader": "^3.4.0", "file-loader": "^5.0.2", "html-webpack-plugin": "^3.2.0", + "mini-css-extract-plugin": "^0.9.0", "node-sass": "^4.13.0", "prettier": "^1.19.1", "resolve-url-loader": "^3.1.1", diff --git a/src/dummy.scss b/src/dummy.scss deleted file mode 100644 index d13cc97..0000000 --- a/src/dummy.scss +++ /dev/null @@ -1,8 +0,0 @@ -@use "styles"; -@use "page/about/about"; -@use "page/background/background"; -@use "page/content/content"; -@use "page/footer/footer"; -@use "page/image-viewer/image-viewer"; -@use "page/timeline/timeline"; -@use "page/timeline/timeline-element/timeline-element"; diff --git a/src/framework/helper.ts b/src/framework/helper.ts index fffea07..a510213 100644 --- a/src/framework/helper.ts +++ b/src/framework/helper.ts @@ -24,3 +24,51 @@ export const randomInInterval = ( export const sum = (list: ArrayLike): number => Array.prototype.reduce.call(list, (a, sum) => a + sum, 0); + +export const getHeight = (e: HTMLElement): number => { + const computedStyle = window.getComputedStyle(e); + return ( + // ignores margin collapse + e.clientHeight + + parseInt(computedStyle.marginTop) + + parseInt(computedStyle.marginBottom) + + parseInt(computedStyle.borderTopWidth) + + parseInt(computedStyle.borderBottomWidth) + ); +}; + +export const mixColors = ( + hexColorA: string, + hexColorB: string, + qA: number +): string => { + const colorA = hexToRGB(normalizeHex(hexColorA)); + const colorB = hexToRGB(normalizeHex(hexColorB)); + const mixedColor: [number, number, number] = [ + colorA[0] * qA + colorB[0] * (1 - qA), + colorA[1] * qA + colorB[1] * (1 - qA), + colorA[2] * qA + colorB[2] * (1 - qA) + ]; + + return RGBToHex(mixedColor); +}; + +const normalizeHex = (hex: string): string => { + hex = hex.trim(); + if (hex.startsWith("#")) { + hex = hex.substr(1); + } + return hex; +}; + +const hexToRGB = (hex: string): [number, number, number] => { + const [r1, r2, g1, g2, b1, b2] = hex; + return [ + Number.parseInt(r1 + r2, 16), + Number.parseInt(g1 + g2, 16), + Number.parseInt(b1 + b2, 16) + ]; +}; + +const RGBToHex = (rgb: [number, number, number]): string => + rgb.map(n => Math.round(n).toString(16)).join(""); diff --git a/src/index.html b/src/index.html index ee92045..dd4dae9 100644 --- a/src/index.html +++ b/src/index.html @@ -13,6 +13,8 @@ + + Portfolio diff --git a/src/page/about/about.html.ts b/src/page/about/about.html.ts index 93d7fa8..7fe94d9 100644 --- a/src/page/about/about.html.ts +++ b/src/page/about/about.html.ts @@ -7,10 +7,6 @@ export const generate = ( aPictureOf: string ): html => `
-
-
- ${aPictureOf} ${name} -

${name}

-
-
+ ${aPictureOf} ${name} +

${name}

`; diff --git a/src/page/about/about.scss b/src/page/about/about.scss index b73a1f1..75b739a 100644 --- a/src/page/about/about.scss +++ b/src/page/about/about.scss @@ -2,42 +2,33 @@ @import "../../style/vars"; #about { - width: 100%; - backdrop-filter: blur($blur-radius); - padding: $normal-margin; + width: $body-width; + margin-top: $normal-margin; - .container { - width: $body-width; - margin: auto; + h1, + img { + @include title-font(); + } - header { - @include center-children(); + img { + @include square(4ch); + border-radius: 100%; + margin-right: 1.5ex; + cursor: pointer; + float: left; + } - h1, - img { - @include title-font(); - } - - img { - @include square(4ch); - border-radius: 100%; - margin-right: 1.5ex; - cursor: pointer; - } - - @media (max-width: $breakpoint-width) { - flex-direction: column; - img { - margin: 0 0 $small-margin 0; - } - h1 { - text-align: center; - } - } + @media (max-width: $breakpoint-width) { + flex-direction: column; + img { + margin: 0 0 $small-margin 0; } - - * { - text-align: justify; + h1 { + text-align: center; } } + + * { + @include main-font(); + } } diff --git a/src/page/about/about.ts b/src/page/about/about.ts index 578d31f..0e3efc3 100644 --- a/src/page/about/about.ts +++ b/src/page/about/about.ts @@ -12,6 +12,6 @@ export class PageHeader extends PageElement { super([content]); this.setElement(root); - this.query(".container").appendChild(content.getElement()); + root.appendChild(content.getElement()); } } diff --git a/src/page/background/background.html.ts b/src/page/background/background.html.ts index 9f154df..549c001 100644 --- a/src/page/background/background.html.ts +++ b/src/page/background/background.html.ts @@ -3,21 +3,26 @@ import "./background.scss"; export const generate = ( count: number, - color?: () => string, + z?: () => number, + color?: (z) => string, height?: () => number, isAnimated?: (index) => boolean, - transform?: () => string -): html => ` + transform?: (z) => string +): html => { + return `
${ count > 0 ? new Array(count) .fill(0, 0, count) + .map(_ => z()) .map( - (_, i) => ` -
` +
` ) @@ -26,3 +31,4 @@ export const generate = ( }
`; +}; diff --git a/src/page/background/background.scss b/src/page/background/background.scss index cfd25c5..3669d40 100644 --- a/src/page/background/background.scss +++ b/src/page/background/background.scss @@ -18,6 +18,8 @@ top: 0; width: 160px; + transition: transform $slow-transition-time; + &.animated { animation: fade-in 1s linear forwards; @keyframes fade-in { diff --git a/src/page/background/background.ts b/src/page/background/background.ts index b3740cb..6d57072 100644 --- a/src/page/background/background.ts +++ b/src/page/background/background.ts @@ -2,94 +2,117 @@ import { PageElement } from "../../framework/page-element"; import { generate } from "./background.html"; import { choose, + getHeight, createElement, randomFactory, randomInInterval, - sum + sum, + mixColors } from "../../framework/helper"; import { PageEvent, PageEventType } from "../../framework/page-event"; export class PageBackground extends PageElement { - private colors = ["#fff9e077", "#ffd6d677"]; - private blobSize = 150; // with margin + private colors = ["#fff9e0", "#ffd6d6"]; + private blobSpacing = 200; private perspective = 5; private currentRealHeight = 0; private currentRealWidth = 0; private currentBlobCount = 0; - public constructor() { + public constructor(private start: PageElement, private end: PageElement) { super(); this.setElement(createElement(generate(0))); } protected handleEvent(event: PageEvent, parent: PageElement) { if (event.type === PageEventType.onLoad) { - window.addEventListener("resize", this.resize.bind(this, parent)); - window.addEventListener("load", this.resize.bind(this, parent)); + this.bindListeners(parent); } else if (event.type === PageEventType.onBodyDimensionsChanged) { this.resize(parent); } } + private bindListeners(parent: PageElement) { + window.addEventListener("resize", this.resize.bind(this, parent)); + window.addEventListener("load", this.resize.bind(this, parent)); + } + private resize(parent: PageElement) { const siblings: Array = 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 ( - // ignores margin collapse - c.clientHeight + - parseInt(computedStyle.marginTop) + - parseInt(computedStyle.marginBottom) + - parseInt(computedStyle.borderTopWidth) + - parseInt(computedStyle.borderBottomWidth) - ); - }) - ); + const width = parent.getElement().clientWidth; + const height = sum(siblings.map(getHeight)); if (height > this.currentRealHeight || width > this.currentRealWidth) { this.currentRealHeight = height; this.currentRealWidth = width; - const random = randomFactory(44); + const random = randomFactory(46); - const count = Math.round((width * height) / this.blobSize ** 2); + const zMin = 20; + const zMax = 40; - 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 - ); + const count = Math.round((width * height) / this.blobSpacing ** 2); + + const randomWithKnownZ = ( + z: number, + viewportSize: number, + scrollSize: number, + startOffset = 0, + endOffset = 0 + ): number => { + const m = 1 + z / this.perspective; + + const variableOffset = (offset, q) => + offset - ((z - zMin) / (zMax - zMin)) * (offset * q); + + startOffset = variableOffset(startOffset, 0.6); + endOffset = variableOffset(endOffset, 0.2); + + const lowerBound = + viewportSize / 2 - (viewportSize / 2 - startOffset) * m; + const l = + scrollSize - + viewportSize + + (viewportSize - startOffset - endOffset) * m; + + return randomInInterval(lowerBound, lowerBound + l, random); }; this.setElement( createElement( generate( count, - () => choose(this.colors, random), + () => randomInInterval(zMin, zMax, random), + z => + "#" + + mixColors( + "#ffffff", + choose(this.colors, random), + (z - zMin) / (zMax - zMin) + ), () => randomInInterval(160, 750, random), i => i >= this.currentBlobCount, - () => { - const z = randomInInterval(-12, -25, random); - return ` - translateX(${randomWithKnownZ(-z, width)}px) - translateY(${randomWithKnownZ(-z, height)}px) - translateZ(${z}px) + z => ` + translateX(${randomWithKnownZ(z, width, width)}px) + translateY(${randomWithKnownZ( + z, + parent.getElement().clientHeight, + height, + getHeight(this.start.getElement()), + getHeight(this.end.getElement()) + )}px) + translateZ(${-z}px) rotate(-20deg) - `; - } + ` ) ) ); this.currentBlobCount = count; + console.log(count); } this.getElement().style.width = `${width}px`; this.getElement().style.height = `${height}px`; diff --git a/src/page/content/content.scss b/src/page/content/content.scss index 52ea1a3..a442235 100644 --- a/src/page/content/content.scss +++ b/src/page/content/content.scss @@ -1,10 +1,10 @@ -@use "../../style/vars"; +@import "../../style/vars"; .content { - margin-top: vars.$small-margin; + margin-top: $small-margin; * { - margin-top: vars.$line-height; + margin-top: $line-height; } p { diff --git a/src/page/footer/footer.scss b/src/page/footer/footer.scss index a79d4f4..8982263 100644 --- a/src/page/footer/footer.scss +++ b/src/page/footer/footer.scss @@ -4,10 +4,10 @@ footer#page-footer { text-align: center; - margin: $small-margin auto 0 auto; + margin: $normal-margin auto 0 auto; padding: $normal-margin $normal-margin $line-height $normal-margin; width: 100%; - backdrop-filter: blur($blur-radius); + // backdrop-filter: blur($blur-radius); h2 { @include title-font(); @@ -16,7 +16,7 @@ footer#page-footer { ul { list-style: none; display: inline-block; - margin-top: $normal-margin; + margin-top: calc(#{$small-margin} / 2 + #{$normal-margin} / 2); text-align: left; li { @@ -40,7 +40,7 @@ footer#page-footer { aside.other { @include center-children(); - margin: $normal-margin auto 0 auto; + margin: calc(2 * #{$normal-margin}) auto 0 auto; width: $body-width; h6 { diff --git a/src/page/image-viewer/image-viewer.ts b/src/page/image-viewer/image-viewer.ts index 0991ba1..82e5e8a 100644 --- a/src/page/image-viewer/image-viewer.ts +++ b/src/page/image-viewer/image-viewer.ts @@ -9,7 +9,7 @@ export class PageImageViewer extends PageElement { super(); const root = createElement(generate()); this.setElement(root); - this.query("#cancel").onclick = () => PageImageViewer.hide(root); + root.onclick = () => PageImageViewer.hide(root); } protected handleEvent(event: PageEvent, parent: PageElement) { diff --git a/src/page/index.ts b/src/page/index.ts index 9a7df0d..1653af5 100644 --- a/src/page/index.ts +++ b/src/page/index.ts @@ -8,15 +8,19 @@ import { Page } from "../framework/page"; export const create = ({ config, header, timeline, footer }: Portfolio) => { document.title = header.name; + const pageHeader = new PageHeader(header, config.aPictureOf); + const pageFooter = new PageFooter(footer); + + const bg = new PageBackground(pageHeader, pageFooter); new Page( [ new PageImageViewer(), new Page( [ - new PageBackground(), - new PageHeader(header, config.aPictureOf), + pageHeader, new PageTimeline(timeline, config.showMore, config.showLess), - new PageFooter(footer) + pageFooter, + bg ], document.body.querySelector("main"), false diff --git a/src/portfolio.ts b/src/portfolio.ts index 5b4febe..ad03244 100644 --- a/src/portfolio.ts +++ b/src/portfolio.ts @@ -1,6 +1,6 @@ import { Portfolio } from "./model/portfolio"; -import me from "./static/media/me-2.jpg"; +import me from "./static/media/me.jpg"; import forex from "./static/media/forex.gif"; import myNotes from "./static/media/my-notes.jpg"; import processSimulator from "./static/media/process-simulator.jpg"; diff --git a/src/style/mixins.scss b/src/style/mixins.scss index 40857ee..2805bb0 100644 --- a/src/style/mixins.scss +++ b/src/style/mixins.scss @@ -35,19 +35,20 @@ } @mixin title-font() { - font: 400 3.33rem "Raleway", serif; + font: 400 3.5rem "Montserrat", serif; } @mixin sub-title-font() { - font: 400 2rem "Raleway", serif; + font: 400 1.9rem "Montserrat", serif; } @mixin main-font() { - font: 400 18px "Open sans", sans-serif; - line-height: 1.5; + font: 400 1.25rem "Lato", sans-serif; + line-height: 1.6; + text-align: justify; } @mixin insignificant-font() { - font: 400 16px "Open sans", sans-serif; + font: 400 1rem "Lato", sans-serif; font-style: italic; } diff --git a/src/style/vars.scss b/src/style/vars.scss index 3b6aec6..1cedf77 100644 --- a/src/style/vars.scss +++ b/src/style/vars.scss @@ -2,6 +2,7 @@ $background-start: white; $background-end: white; $background: white; +$background-gradient: linear-gradient(90deg, #fff9e0 0, #ffd6d6 100%); $normal-text-color: #31343f; $light-text-color: #7a7d8e; @@ -21,7 +22,7 @@ $normal-margin: var(--normal-margin); $small-margin: var(--small-margin); $line-height: 2ch; -$blur-radius: 6px; +$blur-radius: 9px; $icon-size: var(--icon-size); $body-width: var(--body-width); @@ -29,7 +30,7 @@ $body-width: var(--body-width); --line-width: 3px; --normal-margin: 45px; --small-margin: 25px; - --icon-size: 25px; + --icon-size: 35px; --body-width: 765px; @media (max-width: $breakpoint-width) { diff --git a/src/styles.scss b/src/styles.scss index 2d6b622..88bf30c 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -7,6 +7,9 @@ padding: 0; box-sizing: border-box; color: $normal-text-color; + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; hyphens: auto; } @@ -20,7 +23,7 @@ } html { - background-color: $background; + background-color: white; height: 100%; } @@ -34,16 +37,19 @@ body { height: 100%; overflow-y: auto; overflow-x: hidden; + perspective-origin: center center; perspective: 5px; - &::-webkit-scrollbar-track, - &::-webkit-scrollbar { - background-color: transparent; - width: 12px; - } - &::-webkit-scrollbar-thumb { - background-color: $accent-color; - border-radius: $border-radius; + @media (min-width: $breakpoint-width) { + &::-webkit-scrollbar-track, + &::-webkit-scrollbar { + background-color: transparent; + width: 12px; + } + &::-webkit-scrollbar-thumb { + background-color: $accent-color; + border-radius: $border-radius; + } } & > * { diff --git a/webpack.config.js b/webpack.config.js index 1c3b3ae..bb72d6e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,18 +1,23 @@ const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { watchOptions: { ignored: /node_modules/ }, + devServer: { + host: "0.0.0.0" + }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ hash: true, xhtml: true, template: "./src/index.html" - }) + }), + new MiniCssExtractPlugin() ], entry: { index: "./src/index.ts" @@ -52,7 +57,7 @@ module.exports = { test: /\.scss$/i, use: [ { - loader: "style-loader" + loader: MiniCssExtractPlugin.loader }, { loader: "css-loader"