From d6c36c47f855ac3fd998cedc422a6d91ecbf10f8 Mon Sep 17 00:00:00 2001 From: Stanisław Zagórowski Date: Thu, 5 Oct 2023 20:52:47 +0200 Subject: front: awesome background --- front/src/app.css | 41 +++++++++++++ front/src/app.tsx | 3 + front/src/components/animated_bg.tsx | 114 +++++++++++++++++++++++++++++++++++ front/src/components/navbar.css | 7 ++- front/src/pages/games.tsx | 2 +- front/src/pages/home.tsx | 26 ++++---- front/src/pages/projects.tsx | 14 ++--- 7 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 front/src/components/animated_bg.tsx (limited to 'front/src') diff --git a/front/src/app.css b/front/src/app.css index b4086a2..b16cfea 100644 --- a/front/src/app.css +++ b/front/src/app.css @@ -24,6 +24,25 @@ filter: drop-shadow(0 0 2em #673ab8aa); } +/* fade in */ +@keyframes fade-in { + 0% { + opacity: 0; + transform: translateY(1em); + } + 60% { + transform: translateY(-0.2em); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.main-info > * { + animation: fade-in 0.2s ease-in; +} + .main-info { text-align: center; } @@ -64,7 +83,21 @@ color: #e5c07b; } +.back-shadows { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: -1; + background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, var(--color-bg) 10%, var(--color-bg) 90%, rgba(0, 0, 0, 0) 100%); +} + @media (max-width: 480px) { + .back-shadows { + margin: auto; + max-width: 80%; + } .main-info-title { font-size: 32pt; } @@ -75,6 +108,10 @@ } @media (max-width: 1150px) and (min-width: 480px) { + .back-shadows { + margin: auto; + max-width: 60%; + } .main-info-title { font-size: 42pt; } @@ -85,6 +122,10 @@ } @media (min-width: 1150px) { + .back-shadows { + margin: auto; + max-width: 40%; + } .main-info-title { font-size: 42pt; } diff --git a/front/src/app.tsx b/front/src/app.tsx index 5ba8e6f..ba081c9 100644 --- a/front/src/app.tsx +++ b/front/src/app.tsx @@ -6,6 +6,7 @@ import Home from './pages/home' import { Router, Route, CustomHistory } from 'preact-router'; import Projects from './pages/projects'; import { HashHistory, createHashHistory } from 'history'; +import { AnimatedBg } from './components/animated_bg'; const hashHistoryAdapter = (hashHistory: HashHistory): CustomHistory => { return { @@ -21,6 +22,7 @@ export function App() { return ( <> +
@@ -28,6 +30,7 @@ export function App() { +
) diff --git a/front/src/components/animated_bg.tsx b/front/src/components/animated_bg.tsx new file mode 100644 index 0000000..6a8ab3a --- /dev/null +++ b/front/src/components/animated_bg.tsx @@ -0,0 +1,114 @@ +import { Shaders, Node, GLSL } from "gl-react"; +import { Surface } from "gl-react-dom"; +import React from "preact/compat"; +import { PropsWithChildren } from "preact/compat"; + +const shaders = Shaders.create({ + letters: { + frag: GLSL` +precision highp float; +varying vec2 uv; +uniform vec3 color; +uniform sampler2D t; +uniform float time; +uniform vec2 tiles; +uniform float symbol_count; + +vec2 map_to_symbol_uv(vec2 image_coord, float symbol_index) { + float symbol_width = 1.0 / symbol_count; + float symbol_height = 1.0; + float symbol_x = symbol_index * symbol_width; + return vec2(symbol_x + image_coord.x * symbol_width, image_coord.y * symbol_height); +} + +vec2 tile_index(vec2 p, vec2 tiles) { + return vec2(floor(p.x * tiles.x), floor(p.y * tiles.y)); +} + +vec2 tilefy (vec2 p, vec2 tiles) { + return vec2(fract(p.x * tiles.x), fract(p.y * tiles.y)); +} + +float randf(float n) { + return fract(sin(n) * 43758.5453123); +} + +void main() { + vec2 tile = tile_index(uv, tiles); + float tilerand = randf(tile.x + tile.y * tiles.x); + float v = tilerand + randf(floor(tilerand * time)); + float diff = fract(tilerand * time); + float s = floor(v * 9.0); + vec2 tp = tilefy(uv, tiles); + vec2 tp_center = vec2(0.5, 0.5); + float d = distance(tp, tp_center); + float scale = min(sin(diff * 3.1415) * 1.2, 1.0); + tp = tp_center + (tp - tp_center) / scale; + if (tp.x < 0.0 || tp.x > 1.0 || tp.y < 0.0 || tp.y > 1.0) { + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + vec2 p = map_to_symbol_uv(tp, mod(s, symbol_count)); + vec4 c = texture2D(t, p); + c.rgb *= color; + c.a *= uv.y * 4.0; + gl_FragColor = vec4(c.rgb * c.a, c.a); +} +` + } +}); + +const fps = 60; + +const AnimatedBgInternal = ({ tick }: { tick: number }) => { + const t = "/assets/images/symbols.png"; + + return ( +
+ + + +
+ ); +} + +// a higher order component that provides a tick prop +// that updates every 1/refreshRate seconds +// +// accepts a JSX component as an argument +const timeLoop = ( + C: (props: PropsWithChildren<{ tick: number }>) => React.JSX.Element, + { refreshRate }: { refreshRate: number } +) => { + return class TimeLoop extends React.Component { + interval: any; + state = { tick: 0 }; + + componentDidMount() { + this.interval = setInterval(() => { + this.setState({ tick: this.state.tick + 1 }); + }, 1000 / refreshRate); + } + + componentWillUnmount() { + clearInterval(this.interval); + } + + render() { + return ; + } + }; +} + +export const AnimatedBg = timeLoop(AnimatedBgInternal, { refreshRate: fps }); diff --git a/front/src/components/navbar.css b/front/src/components/navbar.css index 466fdd6..9120052 100644 --- a/front/src/components/navbar.css +++ b/front/src/components/navbar.css @@ -1,7 +1,7 @@ /* on big screens, navbar is fixed to the top of the screen */ .navbar-container { position: fixed; - background-color: var(--color-bg); + /* gradient from top to bottom, full to transparent */ top: 0; width: 100%; z-index: 9999; @@ -16,11 +16,12 @@ } .navbar { - margin-top: 20pt; - margin-bottom: 12pt; + padding-top: 20pt; + padding-bottom: 12pt; align-items: center; justify-content: center; align-self: center; + background: linear-gradient(to bottom, var(--color-bg) 0%, var(--color-bg) 75%, rgba(0, 0, 0, 0) 100%); } .navbar-icon { diff --git a/front/src/pages/games.tsx b/front/src/pages/games.tsx index 2ff4eff..6d0d2bd 100644 --- a/front/src/pages/games.tsx +++ b/front/src/pages/games.tsx @@ -11,7 +11,7 @@ export default function Games() { Game Projects
- my game projects, mostly from game jams + games I've worked on
{ diff --git a/front/src/pages/home.tsx b/front/src/pages/home.tsx index 9b29803..df76b84 100644 --- a/front/src/pages/home.tsx +++ b/front/src/pages/home.tsx @@ -9,20 +9,20 @@ export default function Home() { aka Duckonaut, EchoDuck
- -
-

- Hello! I'm a programmer, game designer, and artist. I'm currently a student at the Warsaw University of - Technology, studying Computer Science. A list of the games I've worked on is in the games section. Other projects I've been a part of are available in the projects section. - I also enjoy some lower-level programming and learning about the inner workings of various systems. The main - technologies I use are C#, Unity - , Python, Rust and C, - although I'm also familiar with Godot, C++ - , Java and some JavaScript and TypeScript. -

+
+

+ Hello! I'm a programmer, game designer, and artist. I'm currently a student at the Warsaw University of + Technology, studying Computer Science. A list of the games I've worked on is in the games section. Other projects I've been a part of are available in the projects section. + I also enjoy some lower-level programming and learning about the inner workings of various systems. The main + technologies I use are C#, Unity + , Python, Rust and C, + although I'm also familiar with Godot, C++ + , Java and some JavaScript and TypeScript. +

+
); diff --git a/front/src/pages/projects.tsx b/front/src/pages/projects.tsx index ed68529..2753f91 100644 --- a/front/src/pages/projects.tsx +++ b/front/src/pages/projects.tsx @@ -13,14 +13,14 @@ export default function Projects() {
projects that are not games
- -
- { - projects.map((project) => ( - Project(project) - )) - } +
+ { + projects.map((project) => ( + Project(project) + )) + } +
); -- cgit v1.3.1