├── .gitignore ├── src ├── assets │ └── fonts │ │ ├── Arvo-Bold.ttf │ │ ├── Arvo-Italic.ttf │ │ ├── Arvo-Regular.ttf │ │ ├── Arvo-BoldItalic.ttf │ │ ├── LibreBaskerville-Bold.ttf │ │ ├── LibreBaskerville-Italic.ttf │ │ └── LibreBaskerville-Regular.ttf ├── scripts │ ├── entity.js │ ├── effects.js │ └── main.js ├── styles │ ├── fonts.css │ └── mobile.css └── index.html └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .parcel-cache 3 | dist -------------------------------------------------------------------------------- /src/assets/fonts/Arvo-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/Arvo-Bold.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Arvo-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/Arvo-Italic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Arvo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/Arvo-Regular.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Arvo-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/Arvo-BoldItalic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/LibreBaskerville-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/LibreBaskerville-Bold.ttf -------------------------------------------------------------------------------- /src/assets/fonts/LibreBaskerville-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/LibreBaskerville-Italic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/LibreBaskerville-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARE/iama.re/main/src/assets/fonts/LibreBaskerville-Regular.ttf -------------------------------------------------------------------------------- /src/scripts/entity.js: -------------------------------------------------------------------------------- 1 | export function entity(...effects) { 2 | const element = document.createElement('div') 3 | const context = {} 4 | 5 | element.classList.add('entity') 6 | 7 | for (let effect of effects) { 8 | effect(element, context) 9 | } 10 | 11 | document.querySelector('.wrapper').appendChild(element) 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iama.re", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/index.html", 6 | "scripts": { 7 | "start": "parcel serve src/index.html", 8 | "build": "parcel build src/index.html" 9 | }, 10 | "keywords": [], 11 | "author": "Artur Wojciechowski", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "parcel": "^2.0.0-beta.1" 15 | }, 16 | "prettier": { 17 | "semi": false, 18 | "singleQuote": true 19 | }, 20 | "browserslist": [ 21 | "last 2 Chrome version" 22 | ], 23 | "dependencies": { 24 | "destyle.css": "^1.0.15" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/styles/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | src: url(../assets/fonts/Arvo-Regular.ttf); 3 | font-family: Arvo; 4 | font-weight: normal; 5 | } 6 | 7 | @font-face { 8 | src: url(../assets/fonts/Arvo-Bold.ttf); 9 | font-family: Arvo; 10 | font-weight: bold; 11 | } 12 | 13 | @font-face { 14 | src: url(../assets/fonts/Arvo-Italic.ttf); 15 | font-family: Arvo; 16 | font-weight: normal; 17 | font-style: italic; 18 | } 19 | 20 | @font-face { 21 | src: url(../assets/fonts/Arvo-BoldItalic.ttf); 22 | font-family: Arvo; 23 | font-weight: bold; 24 | font-style: italic; 25 | } 26 | 27 | @font-face { 28 | src: url(../assets/fonts/LibreBaskerville-Regular.ttf); 29 | font-family: LibreBaskerville; 30 | font-weight: normal; 31 | } 32 | 33 | @font-face { 34 | src: url(../assets/fonts/LibreBaskerville-Italic.ttf); 35 | font-family: LibreBaskerville; 36 | font-weight: normal; 37 | font-style: italic; 38 | } 39 | 40 | @font-face { 41 | src: url(../assets/fonts/LibreBaskerville-Bold.ttf); 42 | font-family: LibreBaskerville; 43 | font-weight: bold; 44 | } 45 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | - Are Wojciechowski 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 |
18 |
19 | Are 20 | Wojcie–
chowski
21 |
22 | 23 |
24 | Are 25 | Wojcie–
chowski
26 |
27 | 28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/styles/mobile.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | max-width: 100vw; 3 | height: calc(100% - 0.5px); 4 | position: relative; 5 | top: 0.5px; 6 | overflow-x: hidden; 7 | } 8 | 9 | .content { 10 | height: 400vh; 11 | } 12 | 13 | html { 14 | overflow: hidden; 15 | height: 100%; 16 | } 17 | body { 18 | height: 100%; 19 | overflow-y: scroll; 20 | -webkit-overflow-scrolling: touch; /* iOS velocity scrolling */ 21 | } 22 | 23 | body { 24 | font-family: Arvo; 25 | font-size: 16px; 26 | 27 | color: #313131; 28 | } 29 | 30 | .title { 31 | position: fixed; 32 | 33 | font-family: Anton; 34 | font-weight: bold; 35 | font-style: italic; 36 | font-size: min(20vw, 30vh); 37 | 38 | z-index: 3; 39 | 40 | right: 0.5ch; 41 | color: black; 42 | 43 | pointer-events: none; 44 | } 45 | 46 | .title span { 47 | display: block; 48 | text-align: left; 49 | } 50 | 51 | .shadow { 52 | z-index: 10; 53 | mix-blend-mode: overlay; 54 | color: white; 55 | } 56 | 57 | .entity { 58 | position: fixed; 59 | pointer-events: none; 60 | } 61 | 62 | .type-planet { 63 | border-radius: 100%; 64 | } 65 | 66 | .type-box { 67 | } 68 | 69 | .type-text { 70 | font-size: 18px; 71 | color: white; 72 | padding: 16px; 73 | mix-blend-mode: difference; 74 | } 75 | 76 | .type-text h2 { 77 | font-size: min(10vw, 10vh); 78 | font-family: Arvo; 79 | font-weight: bold; 80 | font-style: italic; 81 | 82 | padding-bottom: 32px; 83 | } 84 | 85 | .type-text p + p { 86 | padding-top: 16px; 87 | } 88 | -------------------------------------------------------------------------------- /src/scripts/effects.js: -------------------------------------------------------------------------------- 1 | export const px = (value) => (typeof value === 'number' ? `${value}px` : value) 2 | export const deg = (value) => 3 | typeof value === 'number' ? `${value}deg` : value 4 | 5 | const scrollHandlers = [] 6 | 7 | const wrapper = document.querySelector('.wrapper') 8 | 9 | wrapper.addEventListener('scroll', () => { 10 | for (let h of scrollHandlers) { 11 | h() 12 | } 13 | }) 14 | 15 | export const reset = () => { 16 | scrollHandlers.splice(0, scrollHandlers.length) 17 | } 18 | 19 | export const parallax = (value) => (entity, ctx) => { 20 | entity.style.top = px(ctx.y + wrapper.scrollTop * -value) 21 | 22 | scrollHandlers.push(() => { 23 | entity.style.top = px(ctx.y + wrapper.scrollTop * -value) 24 | }) 25 | } 26 | 27 | export const oscillate = (fn) => (entity, ctx) => { 28 | entity.style.left = px(ctx.x) 29 | 30 | scrollHandlers.push(() => { 31 | entity.style.left = px(ctx.x + fn(wrapper.scrollTop)) 32 | }) 33 | } 34 | 35 | const IH = window.innerHeight 36 | 37 | export const onScroll = (o) => (entity, ctx) => { 38 | const cb = () => { 39 | for (let [key, fn] of Object.entries(o)) { 40 | entity.style[key] = fn((wrapper.scrollTop / IH) * 360, ctx) 41 | } 42 | } 43 | 44 | cb() 45 | 46 | scrollHandlers.push(cb) 47 | } 48 | 49 | export const type = (name) => (entity) => { 50 | entity.classList.add(`type-${name}`) 51 | } 52 | 53 | export const initialPosition = (x, y) => (entity, ctx) => { 54 | ctx.x = x 55 | ctx.y = y 56 | 57 | entity.style.top = px(y) 58 | entity.style.left = px(x) 59 | } 60 | 61 | export const size = (x, y) => (entity) => { 62 | if (y === undefined) { 63 | y = x 64 | } 65 | 66 | entity.style.width = px(x) 67 | entity.style.height = px(y) 68 | } 69 | 70 | export const background = (value) => (entity) => { 71 | entity.style.background = value 72 | } 73 | 74 | export const linearGradient = (...entries) => 75 | `linear-gradient(${entries.map(deg).join(',')})` 76 | 77 | export const zIndex = (value) => (entity) => { 78 | entity.style.zIndex = value 79 | } 80 | 81 | export const text = (value) => (entity) => { 82 | entity.innerHTML = value 83 | } 84 | 85 | export const rotate = (value) => (entity) => { 86 | entity.style.transform += ` rotate(${deg(value)})` 87 | } 88 | -------------------------------------------------------------------------------- /src/scripts/main.js: -------------------------------------------------------------------------------- 1 | import { entity } from './entity.js' 2 | 3 | import { 4 | parallax, 5 | type, 6 | initialPosition, 7 | size, 8 | background, 9 | linearGradient, 10 | zIndex, 11 | text, 12 | rotate, 13 | oscillate, 14 | onScroll, 15 | px, 16 | reset, 17 | } from './effects.js' 18 | 19 | const LOWEST = 1 20 | const LOW = 5 21 | const HIGH = 15 22 | 23 | const IW = window.innerWidth 24 | const IH = window.innerHeight 25 | 26 | const vw = (perc) => (IW / 100) * perc 27 | const vh = (perc) => (IH / 100) * perc 28 | 29 | const rad = (value) => (value / 180) * Math.PI 30 | 31 | entity( 32 | type('planet'), 33 | initialPosition(vw(10), vh(70)), 34 | size(vw(50)), 35 | background( 36 | linearGradient(135, 'rgba(8, 255, 235, 1) 0%', 'rgba(0, 108, 255, 1) 100%') 37 | ), 38 | parallax(1.2), 39 | zIndex(HIGH) 40 | ) 41 | 42 | entity( 43 | type('planet'), 44 | initialPosition(vw(30), vh(70) + vw(20)), 45 | size(vw(10)), 46 | background( 47 | linearGradient(135, 'rgba(255,255,255,1) 0%', 'rgba(138,138,138,1) 100%') 48 | ), 49 | parallax(1.3), 50 | zIndex(HIGH), 51 | onScroll({ 52 | left: (t, ctx) => px(ctx.x + Math.sin(rad((t + 180) / 2)) * vw(45)), 53 | zIndex: (t) => { 54 | return HIGH + (Math.cos(rad((t + 180) / 2)) < 0 ? -1 : 1) 55 | }, 56 | }) 57 | ) 58 | 59 | entity( 60 | type('box'), 61 | initialPosition(vw(9), 100), 62 | size(vw(70), vh(68)), 63 | background( 64 | linearGradient(135, 'rgba(18, 11, 144, 1) 0%', 'rgba(125, 0, 166, 1) 100%') 65 | ), 66 | zIndex(LOW), 67 | parallax(1) 68 | ) 69 | 70 | entity( 71 | type('box'), 72 | initialPosition(vw(15), vh(120)), 73 | size(vw(80), vh(50)), 74 | zIndex(LOW), 75 | background( 76 | linearGradient(135, 'rgba(221,255,27,1) 0%', 'rgba(253,29,29,1) 100%') 77 | ), 78 | parallax(1) 79 | ) 80 | 81 | entity( 82 | type('planet'), 83 | initialPosition(vw(5), vh(220)), 84 | size(vw(20)), 85 | zIndex(LOW), 86 | background( 87 | linearGradient(135, 'rgba(255,255,255,1) 0%', 'rgba(253,29,29,1) 100%') 88 | ), 89 | parallax(2) 90 | ) 91 | 92 | entity( 93 | type('planet'), 94 | initialPosition(vw(5), vh(220) + vw(5)), 95 | size(vw(10)), 96 | zIndex(LOW), 97 | background( 98 | linearGradient(135, 'rgba(255,255,255,1) 0%', 'rgba(253,29,29,1) 100%') 99 | ), 100 | parallax(2), 101 | onScroll({ 102 | left: (t, ctx) => px(ctx.x + Math.sin(rad(-t + 90)) * vw(40)), 103 | test: (t) => console.log(t), 104 | }) 105 | ) 106 | 107 | entity( 108 | type('planet'), 109 | initialPosition(vw(5), vh(220) + vw(7.5)), 110 | size(vw(5)), 111 | zIndex(LOW), 112 | background( 113 | linearGradient(135, 'rgba(255,255,255,1) 0%', 'rgba(253,29,29,1) 100%') 114 | ), 115 | parallax(2), 116 | onScroll({ 117 | left: (t, ctx) => px(ctx.x + Math.sin(rad(-t + 90)) * vw(80)), 118 | }) 119 | ) 120 | 121 | for (let i = 0; i < 14; i++) { 122 | entity( 123 | type('planet'), 124 | initialPosition(vw(30), vh(220 + i * 10)), 125 | size(vw(40)), 126 | zIndex(LOW), 127 | background( 128 | linearGradient(135, `hsl(120, 100%, 50%) 0%`, `hsl(250, 100%, 50%) 100%`) 129 | ), 130 | onScroll({ 131 | left: (t, ctx) => px(ctx.x + Math.sin(rad(-t + 90 + i * 30)) * vw(30)), 132 | }), 133 | parallax(1.5) 134 | ) 135 | } 136 | 137 | entity( 138 | type('box'), 139 | initialPosition(vw(0), vh(960)), 140 | size(vw(100), vh(30)), 141 | zIndex(LOW), 142 | background( 143 | linearGradient(135, 'rgba(221,27,255,1) 0%', 'rgba(253,29,29,1) 100%') 144 | ), 145 | parallax(3) 146 | ) 147 | 148 | entity( 149 | type('text'), 150 | initialPosition(vw(20), vh(360)), 151 | size(vw(60)), 152 | zIndex(HIGH), 153 | text(` 154 |

Contact: me@iama.re

155 | `), 156 | parallax(1) 157 | ) 158 | 159 | entity( 160 | type('planet'), 161 | initialPosition(vw(-30), vh(220)), 162 | size(vw(160)), 163 | background( 164 | 'radial-gradient(circle, rgba(255,0,0,1) 0%, rgba(255,255,0,0.7183659585674158) 100%' 165 | ), 166 | parallax(0.5), 167 | zIndex(LOWEST) 168 | ) 169 | --------------------------------------------------------------------------------