diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1b04fa9..61ebb65 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,21 +2,21 @@ - - - - + + - + + + + - - - + + - - + + - - - - + - + + + + @@ -103,7 +103,8 @@ - + + diff --git a/src/content/hu.js b/src/content/hu.js deleted file mode 100644 index a71fc99..0000000 --- a/src/content/hu.js +++ /dev/null @@ -1,94 +0,0 @@ -/*{ - "header": { - "name": "Schmelczer András", - "picture": "/static/me.jpg", - "about": [ - "Mind a szoftverfejlesztés, mind pedig a design fontos számomra. Élvezem a problémák megoldását. Motivál, hogy hasznos és érdekes projektekben vegyek részt. Szeretek tanulni.", - - "2017-ben kezdtem tanulmányaimat a Budapesti Műszaki és Gazdaságtudományi Egyetem mérnökinformatikus szakán. Azóta is minden félévemet kiváló eredménnyel zártam. Tavaly csatlakoztam a Simonyi Károly Szakkollégium schdesign köréhez. Korábban a Pécsi Tudományegyetem Gyakorló Gimnáziumába jártam, mialatt angol komplex C1-es nyelvvizsgát is szereztem.", - - "Az alábbiakban összeszedtem pár izgalmasabb projektemet. A képekből természetesen csak a megoldások megjelenítés részét lehet látni. Emellett azonban igyekeztem a háttérben zajló folyamatokról is írni, hiszen az igazi kihívások általában ott rejlenek." - ] - }, - "timeline": [ - { - "date": "2018 október - november", - "title": "Atomreaktor hűtőrendszerének szimulációja", - "picture": "/static/process-simulator.jpg", - "description": "Egy csőrendszerben lévő víz hőmérsékletének és áramlásának dinamikus számítása.", - "more": [ - "A reaktorok (vízmelegítők), szivattyúk, hőcserélők adataiból és a csőrendszer felépítéséből kiszámolja az alkalmazás, hogy melyik időpillanatban hol, mennyi víz folyik, és az milyen meleg.", - "Ezt egy érdekes gráfelméleti algoritmussal, illetve egy mátrix ügyes manipulálásával éri el.", - "A szimuláció backendje python Flask-ben lett írva. Ezzel kommunikálni egy REST API-n keresztül lehet. A megjelenítés HTML5 canvas segítségével történik." - ] - }, - { - "date": "2018 október - november", - "title": "Gráf szerkesztő alkalmazás", - "picture": "/static/process-simulator-input.jpg", - "description": "A fentebb látható szoftverhez tartozó csőrendszert lehet vele létrehozni.", - "more": [ - "A grafikus és felhasználóbarát szerkesztőprogram a végeredményt megfelelő JSON formátumba alakítja, amit a szimulátor már könnyedén fel tud dolgozni.", - "Szerkeszteni klikkeléssel, illetve drag & droppal lehetséges. Az alkalmazásban továbbá lehet a vízmelegítők, szivattyúk stb. paramétereit is beállítani.", - "Java-ban lett írva, a megjelenítést a JavaFX biztosítja." - ] - }, - { - "date": "2018 július - augusztus", - "title": "Közlekedés szimuláció", - "picture": "/static/sim.jpg", - "description": "A modellek Blenderben, a szimuláció Unityben készült.", - "more": [ - "Egy versenyhez készült program. REST API-kon keresztül lehet a lámpák színét változtatni és a szimulációt befolyásolni, (akár még tweet-et is lehet beküldeni), az autók pedig ettől függően közlekednek, esetlegesen karamboloznak és felrobbannak.", - "Az egész érdekessége, hogy egy szerver-kliens architektúrát valósít meg, a szervezés egyszerűbbé tétele végett. Izgalmas kihívás volt a netes kommunikációból fakadó laggot kompenzálni.", - "Az összes képen látható modellt és animációt én készítettem. A scriptelés C# segítségével történt." - ] - }, - { - "date": "2018 június", - "title": "Színszerkesztő", - "picture": "/static/szinezo.jpg", - "description": "Egy innovatív color grader képekhez.", - "more": [ - "Ki lehet választani bizonyos színeket, és a többi színt az előbbiektől lévő távolságának függvényében lehet módosítani, telitettséget, színezettségét változtatni.", - "Egyelőre proof of concept stádiumban van, viszont tervezem befejezni.", - "A színes gombokra való kattintással lehet az opciók közt váltani. Színes gombot a nagy körbe való kattintással lehet létrehozni (mozgatni pedig drag & droppal).", - { "type": "a", "href": "/szinezo", "text": "schmelczer.hu/szinezo" } - ] - }, - { - "date": "2017 ősz", - "title": "Platform játék", - "picture": "/static/platform.png", - "description": "Írtam egy 3D-s játékot C-ben az SDL 1.2 segítségével.", - "more": [ - "A pályák véletlenszerűen generálódnak, menthetők és rombolhatók is. A játékost repülő ellenségek üldözik.", - "Ez volt a Programozás alapjai I. tárgyhoz készített házifeladatom. Összességében egy élvezhető játék lett.", - { "type": "a", "href": "/platform", "text": "schmelczer.hu/platform" } - ] - }, - { - "date": "2016 nyár", - "title": "Fényképek", - "picture": "/static/kepek.jpg", - "description": "Csináltam egy oldalt, ahol a fényképeimet lehet megnézni.", - "link": "schmelczer.hu/kepek" - }, - { - "date": "2016 tavasz", - "title": "Zenére világító ledsorok", - "picture": "/static/LED.jpg", - "description": "Egy alkalmazást készítettem, amivel RGB ledsorok színét lehet a zene ritmusára változtatni.", - "more": [ - "Ez volt az első nagyobb projektem, ez természetesen a megvalósítás minőségén is érezhető. Ettől független büszke vagyok a végeredményre.", - "Pythonban lett írva, amivel egy webes frontenden keresztül lehet kommunikálni. Továbbá beépítésre került egy zenelejátszó is a programba.", - "A működő rendszerről készítettem egy videót, ami alább tekinthető meg.", - { "type": "video", "src": "static/led720.mp4" } - ] - } - ], - "footer": { - "email": "andras.schmelczer@schdesign.hu" - } -} -*/ diff --git a/src/framework/helper.ts b/src/framework/helper.ts index d50eb1a..fffea07 100644 --- a/src/framework/helper.ts +++ b/src/framework/helper.ts @@ -10,3 +10,17 @@ export const randomFactory = seed => () => ((2 ** 31 - 1) & (seed = Math.imul(48271, seed))) / 2 ** 31; export const fixedSeedRandom = randomFactory(42); + +export const choose = ( + list: Array, + random: () => number = fixedSeedRandom +): T => list[randomInInterval(0, list.length, random)]; + +export const randomInInterval = ( + aClosed: number, + bOpen: number, + random: () => number = fixedSeedRandom +): number => Math.floor((bOpen - aClosed) * random()) + aClosed; + +export const sum = (list: ArrayLike): number => + Array.prototype.reduce.call(list, (a, sum) => a + sum, 0); diff --git a/src/framework/page-element.ts b/src/framework/page-element.ts index 421a8e4..a8c40a0 100644 --- a/src/framework/page-element.ts +++ b/src/framework/page-element.ts @@ -9,6 +9,7 @@ export abstract class PageElement { } protected setElement(value: HTMLElement) { + this.getElement()?.parentElement?.replaceChild(value, this.getElement()); this.element = value; } diff --git a/src/framework/page.ts b/src/framework/page.ts index 433d426..102e93a 100644 --- a/src/framework/page.ts +++ b/src/framework/page.ts @@ -12,7 +12,7 @@ export class Page extends PageElement { { type: PageEventType.eventGeneratorChanged, data: this }, this ); - rootElement.append(...children.map(e => e.getElement())); + rootElement.append(...children.map(e => e.getElement()).filter(e => e)); this.giveEvent({ type: PageEventType.onLoad }, this); } } diff --git a/src/index.ts b/src/index.ts index 6fb0ee9..3992cd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,6 @@ import "./static/no-change/og-image.jpg"; import "./styles.scss"; import { create } from "./page/index"; -import { portfolio } from "./content/en"; +import { portfolio } from "./portfolio"; create(portfolio); diff --git a/src/page/background/background.html.ts b/src/page/background/background.html.ts index b80e02a..d7350f4 100644 --- a/src/page/background/background.html.ts +++ b/src/page/background/background.html.ts @@ -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 => `
- ${new Array(count) - .fill(0, 0, count) - .map(_ => - fixedSeedRandom() < probability - ? `
` - : `
` - ) - .join("")} + ${ + count > 0 + ? new Array(count) + .fill(0, 0, count) + .map( + _ => + `
` + ) + .join("") + : "" + }
`; diff --git a/src/page/background/background.scss b/src/page/background/background.scss index caaf7cd..a48d3b0 100644 --- a/src/page/background/background.scss +++ b/src/page/background/background.scss @@ -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; } } diff --git a/src/page/background/background.ts b/src/page/background/background.ts index 20628b1..17ed789 100644 --- a/src/page/background/background.ts +++ b/src/page/background/background.ts @@ -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 = 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`; } } diff --git a/src/page/footer/footer.html.ts b/src/page/footer/footer.html.ts index 9073eea..0571d8f 100644 --- a/src/page/footer/footer.html.ts +++ b/src/page/footer/footer.html.ts @@ -3,7 +3,7 @@ import { html } from "../../model/misc"; import "./footer.scss"; export const generate = ({ email, cv }: Footer, cvName: string): html => ` -