├── .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 |
--------------------------------------------------------------------------------