├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── css
└── base.css
├── favicon.ico
├── img
├── 1.avif
├── 1.png
├── 10.avif
├── 10.png
├── 11.avif
├── 11.png
├── 12.avif
├── 12.png
├── 13.avif
├── 13.png
├── 14.avif
├── 14.png
├── 15.avif
├── 15.png
├── 2.avif
├── 2.png
├── 3.avif
├── 3.png
├── 4.avif
├── 4.png
├── 5.avif
├── 5.png
├── 6.avif
├── 6.png
├── 7.avif
├── 7.png
├── 8.avif
├── 8.png
├── 9.avif
└── 9.png
├── index.html
├── index2.html
└── js
└── vanilla-tilt.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache
3 | .parcel-cache
4 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2009 - 2021 [Codrops](https://tympanus.net/codrops)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 3D Perspective Glitch Hover Effect
2 |
3 | A fun hover effect that shows a pixelated image with a glitch animation as seen on [buōy's website](https://buoy.work/gallery/).
4 |
5 | 
6 |
7 | [Article on Codrops](https://tympanus.net/codrops/?p=64948)
8 |
9 | [Demo](http://tympanus.net/Development/GlitchPerspective/)
10 |
11 |
12 | ## Installation
13 |
14 | Install dependencies:
15 |
16 | ```
17 | npm install
18 | ```
19 |
20 | Compile the code for development and start a local server:
21 |
22 | ```
23 | npm start
24 | ```
25 |
26 | Create the build:
27 |
28 | ```
29 | npm run build
30 | ```
31 |
32 | ## Credits
33 |
34 | - Images from [Unsplash](https://unsplash.com/)
35 |
36 | ## Misc
37 |
38 | Follow Codrops: [Twitter](http://www.twitter.com/codrops), [Facebook](http://www.facebook.com/codrops), [GitHub](https://github.com/codrops), [Instagram](https://www.instagram.com/codropsss/)
39 |
40 | ## License
41 | [MIT](LICENSE)
42 |
43 | Made with :blue_heart: by [Codrops](http://www.codrops.com)
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/css/base.css:
--------------------------------------------------------------------------------
1 | *,
2 | *::after,
3 | *::before {
4 | box-sizing: border-box;
5 | }
6 |
7 | :root {
8 | font-size: 16px;
9 | --color-text: #000;
10 | --color-bg: #3124c7;
11 | --color-link: #fff;
12 | --color-link-hover: #000;
13 | --color-label: #fff;
14 | --content-hover: #f3727e;
15 | /* Glitch variables */
16 | --gap-horizontal: 20px;
17 | --gap-vertical: 5px;
18 | --time-anim: 1s;
19 | --blend-mode-1: none;
20 | --blend-mode-2: color-dodge;
21 | --blend-mode-3: luminosity;
22 | --blend-mode-4: none;
23 | --blend-mode-5: none;
24 | --blend-color-1: #f3727e;
25 | --blend-color-2: #f3727e;
26 | --blend-color-3: #3124c7;
27 | --blend-color-4: #3124c7;
28 | --blend-color-5: #f3727e;
29 | /* Rotation variables */
30 | --rotate-time: 0.5s;
31 | --rotate-easing: cubic-bezier(0.2,1,0.3,1);
32 | /* Cover variables */
33 | --fade-out-time: 0.25s;
34 | --fade-in-time: 0.25s;
35 | --fade-out-easing: ease-out;
36 | --fade-in-easing: ease-out;
37 | }
38 |
39 | .demo-2 {
40 | --color-bg: #6d5c5b;
41 | --content-hover: #000;
42 | }
43 |
44 | body {
45 | margin: 0;
46 | color: var(--color-text);
47 | background-color: var(--color-bg);
48 | font-family: widescreen-ex, sans-serif;
49 | -webkit-font-smoothing: antialiased;
50 | -moz-osx-font-smoothing: grayscale;
51 | overflow-x: hidden;
52 | }
53 |
54 | /* Page Loader */
55 | .js .loading::before,
56 | .js .loading::after {
57 | content: '';
58 | position: fixed;
59 | z-index: 1000;
60 | }
61 |
62 | .js .loading::before {
63 | top: 0;
64 | left: 0;
65 | width: 100%;
66 | height: 100%;
67 | background: var(--color-bg);
68 | }
69 |
70 | .js .loading::after {
71 | top: 50%;
72 | left: 50%;
73 | width: 60px;
74 | height: 60px;
75 | margin: -30px 0 0 -30px;
76 | border-radius: 50%;
77 | opacity: 0.4;
78 | background: var(--color-link);
79 | animation: loaderAnim 0.7s linear infinite alternate forwards;
80 |
81 | }
82 |
83 | @keyframes loaderAnim {
84 | to {
85 | opacity: 1;
86 | transform: scale3d(0.5,0.5,1);
87 | }
88 | }
89 |
90 | a {
91 | text-decoration: none;
92 | color: var(--color-link);
93 | outline: none;
94 | cursor: pointer;
95 | }
96 |
97 | a:hover {
98 | color: var(--color-link-hover);
99 | outline: none;
100 | }
101 |
102 | /* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */
103 | a:focus {
104 | /* Provide a fallback style for browsers
105 | that don't support :focus-visible */
106 | outline: none;
107 | background: lightgrey;
108 | }
109 |
110 | a:focus:not(:focus-visible) {
111 | /* Remove the focus indicator on mouse-focus for browsers
112 | that do support :focus-visible */
113 | background: transparent;
114 | }
115 |
116 | a:focus-visible {
117 | /* Draw a very noticeable focus style for
118 | keyboard-focus on browsers that do support
119 | :focus-visible */
120 | outline: 2px solid red;
121 | background: transparent;
122 | }
123 |
124 | .unbutton {
125 | background: none;
126 | border: 0;
127 | padding: 0;
128 | margin: 0;
129 | font: inherit;
130 | cursor: pointer;
131 | }
132 |
133 | .unbutton:focus {
134 | outline: none;
135 | }
136 |
137 | .frame {
138 | padding: 1rem 2rem;
139 | text-transform: uppercase;
140 | }
141 |
142 | .frame__title-main {
143 | font-size: 1rem;
144 | margin: 0;
145 | font-weight: normal;
146 | }
147 |
148 | .frame__title-back {
149 | position: relative;
150 | display: flex;
151 | align-items: flex-end;
152 | margin-bottom: 0.15rem;
153 | }
154 |
155 | .frame__title-back span {
156 | display: none;
157 | }
158 |
159 | .frame__title-back svg {
160 | fill: var(--color-text);
161 | }
162 |
163 | .frame__title-prev {
164 | margin: 0 2rem 0 0;
165 | }
166 |
167 | .frame__demo {
168 | margin: 0 1rem 0 0;
169 | }
170 |
171 | .frame__demo--current {
172 | color: var(--color-link-hover);
173 | }
174 |
175 | .intro {
176 | padding: 10vh 2rem 10vh;
177 | margin-bottom: 2rem;
178 | }
179 |
180 | .intro__title {
181 | grid-area: title;
182 | font-family: widescreen-ex, sans-serif;
183 | font-weight: 800;
184 | font-size: clamp(2rem,12vw,10rem);
185 | line-height: 1;
186 | margin: 0;
187 | }
188 |
189 | .intro__title span {
190 | text-transform: uppercase;
191 | -webkit-text-stroke: 1px #000;
192 | text-stroke: 1px #000;
193 | -webkit-text-fill-color: transparent;
194 | text-fill-color: transparent;
195 | color: transparent;
196 | text-shadow: -10px 10px 0 #000;
197 | }
198 |
199 | .intro__title em {
200 | font-family: park-lane, serif;
201 | font-weight: 300;
202 | font-style: normal;
203 | display: block;
204 | margin: -2.5vw 0 0 0;
205 | text-transform: uppercase;
206 | font-size: clamp(2rem,10vw,10rem);
207 | -webkit-text-stroke: 1px #000;
208 | text-stroke: 1px #000;
209 | -webkit-text-fill-color: var(--color-bg);
210 | text-fill-color: var(--color-bg);
211 | color: var(--color-bg);
212 | }
213 |
214 | .intro__description {
215 | margin: 1.75vw 0 0 0;
216 | grid-area: desc;
217 | font-weight: 500;
218 | font-size: clamp(1rem, 2vw, 1.25rem);
219 | max-width: 350px;
220 | }
221 |
222 | .intro__button {
223 | grid-area: button;
224 | border: 1px solid var(--color-text);
225 | background: var(--color-bg);
226 | box-shadow: 1px 2px 0 #000;
227 | font-size: 1.25rem;
228 | padding: 1rem 2rem;
229 | border-radius: 1.25rem;
230 | justify-self: end;
231 | font-weight: bold;
232 | text-transform: uppercase;
233 | margin-top: 1rem;
234 | }
235 |
236 | .intro__button:hover,
237 | .intro__button:focus {
238 | transform: translate3d(1px,2px,0);
239 | box-shadow: 0px 0px 0 #000;
240 | }
241 |
242 | .content {
243 | display: grid;
244 | grid-gap: 1.5rem;
245 | margin: 0 auto;
246 | padding-bottom: 30vh;
247 | grid-template-columns: repeat(auto-fill, minmax(350px,1fr));
248 | }
249 |
250 | .item {
251 | aspect-ratio: 0.8;
252 | cursor: pointer;
253 | display: grid;
254 | grid-template-columns: 100%;
255 | grid-template-rows: 100%;
256 | perspective: 1000px;
257 | overflow: hidden;
258 | position: relative;
259 | margin: 0;
260 | }
261 |
262 | .demo-2 .item {
263 | overflow: visible;
264 | }
265 |
266 | .demo-2 .item--oh {
267 | overflow: hidden;
268 | }
269 |
270 | .item__img {
271 | grid-area: 1 / 1 / -1 / -1;
272 | position: relative;
273 | opacity: 0;
274 | width: 100%;
275 | height: 100%;
276 | }
277 |
278 | .item:hover .item__img {
279 | opacity: 1;
280 | transition: transform var(--rotate-time) var(--rotate-easing);
281 | transform: translateZ(-200px) rotateX(60deg) rotateY(0) rotateZ(-35deg);
282 | }
283 |
284 | .glitch {
285 | display: grid;
286 | place-items: center;
287 | }
288 |
289 | .glitch__img {
290 | grid-area: 1 / 1 / -1 / -1;
291 | background-image: var(--img);
292 | background-position: 50% 50%;
293 | background-size: cover;
294 | image-rendering: pixelated;
295 | width: 100%;
296 | height: 100%;
297 | background-color: var(--blend-color-1);
298 | transform: translate3d(0,0,0);
299 | background-blend-mode: var(--blend-mode-1);
300 | }
301 |
302 | .glitch__img:nth-child(2) {
303 | background-color: var(--blend-color-2);
304 | background-blend-mode: var(--blend-mode-2);
305 | }
306 |
307 | .glitch__img:nth-child(3) {
308 | background-color: var(--blend-color-3);
309 | background-blend-mode: var(--blend-mode-3);
310 | }
311 |
312 | .glitch__img:nth-child(4) {
313 | background-color: var(--blend-color-4);
314 | background-blend-mode: var(--blend-mode-4);
315 | }
316 |
317 | .glitch__img:nth-child(5) {
318 | background-color: var(--blend-color-5);
319 | background-blend-mode: var(--blend-mode-5);
320 | }
321 |
322 | /* Hide all images except the first one */
323 | .glitch__img:nth-child(n+2) {
324 | opacity: 0;
325 | }
326 |
327 | /* Hovers */
328 |
329 | /* On hover we show the 2nd, 3rd, 4th and 5th image*/
330 | .item:hover .glitch__img:nth-child(n+2) {
331 | opacity: 1;
332 | }
333 |
334 | /* Hover animations for horizontal case */
335 | .item:hover .glitch__img:nth-child(2) {
336 | transform: translate3d(var(--gap-horizontal),0,0);
337 | animation: glitch-anim-1-horizontal var(--time-anim) infinite linear alternate;
338 | }
339 |
340 | .item:hover .glitch__img:nth-child(3) {
341 | transform: translate3d(calc(-1 * var(--gap-horizontal)),0,0);
342 | animation: glitch-anim-2-horizontal var(--time-anim) infinite linear alternate;
343 | }
344 |
345 | .item:hover .glitch__img:nth-child(4) {
346 | transform: translate3d(0, calc(-1 * var(--gap-vertical)), 0) scale3d(-1,-1,1);
347 | animation: glitch-anim-3-horizontal var(--time-anim) infinite linear alternate;
348 | }
349 |
350 | /* Hover flash animation on last image */
351 | .item:hover .glitch__img:nth-child(5) {
352 | animation: glitch-anim-flash 0.5s steps(1,end) infinite;
353 | }
354 |
355 | /* Animations */
356 |
357 | /* Horizontal */
358 | @keyframes glitch-anim-1-horizontal {
359 | 0% {
360 | -webkit-clip-path: polygon(0 2%, 100% 2%, 100% 5%, 0 5%);
361 | clip-path: polygon(0 2%, 100% 2%, 100% 5%, 0 5%);
362 | }
363 | 10% {
364 | -webkit-clip-path: polygon(0 15%, 100% 15%, 100% 15%, 0 15%);
365 | clip-path: polygon(0 15%, 100% 15%, 100% 15%, 0 15%);
366 | }
367 | 20% {
368 | -webkit-clip-path: polygon(0 10%, 100% 10%, 100% 20%, 0 20%);
369 | clip-path: polygon(0 10%, 100% 10%, 100% 20%, 0 20%);
370 | }
371 | 30% {
372 | -webkit-clip-path: polygon(0 1%, 100% 1%, 100% 2%, 0 2%);
373 | clip-path: polygon(0 1%, 100% 1%, 100% 2%, 0 2%);
374 | }
375 | 40% {
376 | -webkit-clip-path: polygon(0 33%, 100% 33%, 100% 33%, 0 33%);
377 | clip-path: polygon(0 33%, 100% 33%, 100% 33%, 0 33%);
378 | }
379 | 50% {
380 | -webkit-clip-path: polygon(0 44%, 100% 44%, 100% 44%, 0 44%);
381 | clip-path: polygon(0 44%, 100% 44%, 100% 44%, 0 44%);
382 | }
383 | 60% {
384 | -webkit-clip-path: polygon(0 50%, 100% 50%, 100% 20%, 0 20%);
385 | clip-path: polygon(0 50%, 100% 50%, 100% 20%, 0 20%);
386 | }
387 | 70% {
388 | -webkit-clip-path: polygon(0 70%, 100% 70%, 100% 70%, 0 70%);
389 | clip-path: polygon(0 70%, 100% 70%, 100% 70%, 0 70%);
390 | }
391 | 80% {
392 | -webkit-clip-path: polygon(0 80%, 100% 80%, 100% 80%, 0 80%);
393 | clip-path: polygon(0 80%, 100% 80%, 100% 80%, 0 80%);
394 | }
395 | 90% {
396 | -webkit-clip-path: polygon(0 50%, 100% 50%, 100% 55%, 0 55%);
397 | clip-path: polygon(0 50%, 100% 50%, 100% 55%, 0 55%);
398 | }
399 | 100% {
400 | -webkit-clip-path: polygon(0 70%, 100% 70%, 100% 80%, 0 80%);
401 | clip-path: polygon(0 70%, 100% 70%, 100% 80%, 0 80%);
402 | }
403 | }
404 |
405 | @keyframes glitch-anim-2-horizontal {
406 | 0% {
407 | -webkit-clip-path: polygon(0 25%, 100% 25%, 100% 30%, 0 30%);
408 | clip-path: polygon(0 25%, 100% 25%, 100% 30%, 0 30%);
409 | }
410 | 15% {
411 | -webkit-clip-path: polygon(0 3%, 100% 3%, 100% 3%, 0 3%);
412 | clip-path: polygon(0 3%, 100% 3%, 100% 3%, 0 3%);
413 | }
414 | 22% {
415 | -webkit-clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
416 | clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
417 | }
418 | 31% {
419 | -webkit-clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
420 | clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
421 | }
422 | 45% {
423 | -webkit-clip-path: polygon(0 40%, 100% 40%, 100% 40%, 0 40%);
424 | clip-path: polygon(0 40%, 100% 40%, 100% 40%, 0 40%);
425 | }
426 | 51% {
427 | -webkit-clip-path: polygon(0 52%, 100% 52%, 100% 59%, 0 59%);
428 | clip-path: polygon(0 52%, 100% 52%, 100% 59%, 0 59%);
429 | }
430 | 63% {
431 | -webkit-clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
432 | clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
433 | }
434 | 76% {
435 | -webkit-clip-path: polygon(0 75%, 100% 75%, 100% 75%, 0 75%);
436 | clip-path: polygon(0 75%, 100% 75%, 100% 75%, 0 75%);
437 | }
438 | 81% {
439 | -webkit-clip-path: polygon(0 65%, 100% 65%, 100% 40%, 0 40%);
440 | clip-path: polygon(0 65%, 100% 65%, 100% 40%, 0 40%);
441 | }
442 | 94% {
443 | -webkit-clip-path: polygon(0 45%, 100% 45%, 100% 50%, 0 50%);
444 | clip-path: polygon(0 45%, 100% 45%, 100% 50%, 0 50%);
445 | }
446 | 100% {
447 | -webkit-clip-path: polygon(0 14%, 100% 14%, 100% 33%, 0 33%);
448 | clip-path: polygon(0 14%, 100% 14%, 100% 33%, 0 33%);
449 | }
450 | }
451 |
452 | @keyframes glitch-anim-3-horizontal {
453 | 0% {
454 | -webkit-clip-path: polygon(0 1%, 100% 1%, 100% 3%, 0 3%);
455 | clip-path: polygon(0 1%, 100% 1%, 100% 3%, 0 3%);
456 | }
457 | 5% {
458 | -webkit-clip-path: polygon(0 10%, 100% 10%, 100% 9%, 0 9%);
459 | clip-path: polygon(0 10%, 100% 10%, 100% 9%, 0 9%);
460 | }
461 | 10% {
462 | -webkit-clip-path: polygon(0 5%, 100% 5%, 100% 6%, 0 6%);
463 | clip-path: polygon(0 5%, 100% 5%, 100% 6%, 0 6%);
464 | }
465 | 25% {
466 | -webkit-clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
467 | clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
468 | }
469 | 27% {
470 | -webkit-clip-path: polygon(0 10%, 100% 10%, 100% 10%, 0 10%);
471 | clip-path: polygon(0 10%, 100% 10%, 100% 10%, 0 10%);
472 | }
473 | 30% {
474 | -webkit-clip-path: polygon(0 30%, 100% 30%, 100% 25%, 0 25%);
475 | clip-path: polygon(0 30%, 100% 30%, 100% 25%, 0 25%);
476 | }
477 | 33% {
478 | -webkit-clip-path: polygon(0 15%, 100% 15%, 100% 16%, 0 16%);
479 | clip-path: polygon(0 15%, 100% 15%, 100% 16%, 0 16%);
480 | }
481 | 37% {
482 | -webkit-clip-path: polygon(0 40%, 100% 40%, 100% 39%, 0 39%);
483 | clip-path: polygon(0 40%, 100% 40%, 100% 39%, 0 39%);
484 | }
485 | 40% {
486 | -webkit-clip-path: polygon(0 20%, 100% 20%, 100% 21%, 0 21%);
487 | clip-path: polygon(0 20%, 100% 20%, 100% 21%, 0 21%);
488 | }
489 | 45% {
490 | -webkit-clip-path: polygon(0 60%, 100% 60%, 100% 55%, 0 55%);
491 | clip-path: polygon(0 60%, 100% 60%, 100% 55%, 0 55%);
492 | }
493 | 50% {
494 | -webkit-clip-path: polygon(0 30%, 100% 30%, 100% 31%, 0 31%);
495 | clip-path: polygon(0 30%, 100% 30%, 100% 31%, 0 31%);
496 | }
497 | 53% {
498 | -webkit-clip-path: polygon(0 70%, 100% 70%, 100% 69%, 0 69%);
499 | clip-path: polygon(0 70%, 100% 70%, 100% 69%, 0 69%);
500 | }
501 | 57% {
502 | -webkit-clip-path: polygon(0 40%, 100% 40%, 100% 41%, 0 41%);
503 | clip-path: polygon(0 40%, 100% 40%, 100% 41%, 0 41%);
504 | }
505 | 60% {
506 | -webkit-clip-path: polygon(0 80%, 100% 80%, 100% 75%, 0 75%);
507 | clip-path: polygon(0 80%, 100% 80%, 100% 75%, 0 75%);
508 | }
509 | 65% {
510 | -webkit-clip-path: polygon(0 50%, 100% 50%, 100% 51%, 0 51%);
511 | clip-path: polygon(0 50%, 100% 50%, 100% 51%, 0 51%);
512 | }
513 | 70% {
514 | -webkit-clip-path: polygon(0 90%, 100% 90%, 100% 90%, 0 90%);
515 | clip-path: polygon(0 90%, 100% 90%, 100% 90%, 0 90%);
516 | }
517 | 73% {
518 | -webkit-clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
519 | clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
520 | }
521 | 80% {
522 | -webkit-clip-path: polygon(0 100%, 100% 100%, 100% 99%, 0 99%);
523 | clip-path: polygon(0 100%, 100% 100%, 100% 99%, 0 99%);
524 | }
525 | 100% {
526 | -webkit-clip-path: polygon(0 70%, 100% 70%, 100% 71%, 0 71%);
527 | clip-path: polygon(0 70%, 100% 70%, 100% 71%, 0 71%);
528 | }
529 | }
530 |
531 | /* Vertical */
532 | @keyframes glitch-anim-1-vertical {
533 | 0% {
534 | -webkit-clip-path: polygon(2% 0, 5% 0, 5% 100%, 2% 100%);
535 | clip-path: polygon(2% 0, 5% 0, 5% 100%, 2% 100%);
536 | }
537 | 10% {
538 | -webkit-clip-path: polygon(15% 0, 15% 0, 15% 100%, 15% 100%);
539 | clip-path: polygon(15% 0, 15% 0, 15% 100%, 15% 100%);
540 | }
541 | 20% {
542 | -webkit-clip-path: polygon(10% 0, 20% 0, 20% 100%, 10% 100%);
543 | clip-path: polygon(10% 0, 20% 0, 20% 100%, 10% 100%);
544 | }
545 | 30% {
546 | -webkit-clip-path: polygon(1% 0, 2% 0, 2% 100%, 1% 100%);
547 | clip-path: polygon(1% 0, 2% 0, 2% 100%, 1% 100%);
548 | }
549 | 40% {
550 | -webkit-clip-path: polygon(33% 0, 33% 0, 33% 100%, 33% 100%);
551 | clip-path: polygon(33% 0, 33% 0, 33% 100%, 33% 100%);
552 | }
553 | 50% {
554 | -webkit-clip-path: polygon(44% 0, 44% 0, 44% 100%, 44% 100%);
555 | clip-path: polygon(44% 0, 44% 0, 44% 100%, 44% 100%);
556 | }
557 | 60% {
558 | -webkit-clip-path: polygon(50% 0, 20% 0, 20% 100%, 50% 100%);
559 | clip-path: polygon(50% 0, 20% 0, 20% 100%, 50% 100%);
560 | }
561 | 70% {
562 | -webkit-clip-path: polygon(70% 0, 70% 0, 70% 100% 70%, 70% 100%);
563 | clip-path: polygon(70% 0, 70% 0, 70% 100% 70%, 70% 100%);
564 | }
565 | 80% {
566 | -webkit-clip-path: polygon(80% 0, 80% 0, 80% 100% 80%, 80% 100%);
567 | clip-path: polygon(80% 0, 80% 0, 80% 100% 80%, 80% 100%);
568 | }
569 | 90% {
570 | -webkit-clip-path: polygon(50% 0, 55% 0, 55% 100%, 50% 100%);
571 | clip-path: polygon(50% 0, 55% 0, 55% 100%, 50% 100%);
572 | }
573 | 100% {
574 | -webkit-clip-path: polygon(70% 0, 80% 0, 80% 100%, 70% 100%);
575 | clip-path: polygon(70% 0, 80% 0, 80% 100%, 70% 100%);
576 | }
577 | }
578 |
579 | @keyframes glitch-anim-2-vertical {
580 | 0% {
581 | -webkit-clip-path: polygon(25% 0, 30% 0, 30% 100%, 25% 100%);
582 | clip-path: polygon(25% 0, 30% 0, 30% 100%, 25% 100%);
583 | }
584 | 15% {
585 | -webkit-clip-path: polygon(3% 0, 3% 0, 3% 100%, 3% 100%);
586 | clip-path: polygon(3% 0, 3% 0, 3% 100%, 3% 100%);
587 | }
588 | 22% {
589 | -webkit-clip-path: polygon(5% 0, 20% 0, 20% 100%, 5% 100%);
590 | clip-path: polygon(5% 0, 20% 0, 20% 100%, 5% 100%);
591 | }
592 | 31% {
593 | -webkit-clip-path: polygon(20% 0, 20% 0, 20% 100%, 20% 100%);
594 | clip-path: polygon(20% 0, 20% 0, 20% 100%, 20% 100%);
595 | }
596 | 45% {
597 | -webkit-clip-path: polygon(40% 0, 40% 0, 40% 100%, 40% 100%);
598 | clip-path: polygon(40% 0, 40% 0, 40% 100%, 40% 100%);
599 | }
600 | 51% {
601 | -webkit-clip-path: polygon(52% 0, 59% 0, 59% 100%, 52% 100%);
602 | clip-path: polygon(52% 0, 59% 0, 59% 100%, 52% 100%);
603 | }
604 | 63% {
605 | -webkit-clip-path: polygon(60% 0, 60% 0, 60% 100%, 60% 100%);
606 | clip-path: polygon(60% 0, 60% 0, 60% 100%, 60% 100%);
607 | }
608 | 76% {
609 | -webkit-clip-path: polygon(75% 0, 75% 0, 75% 100%, 75% 100%);
610 | clip-path: polygon(75% 0, 75% 0, 75% 100%, 75% 100%);
611 | }
612 | 81% {
613 | -webkit-clip-path: polygon(65% 0, 40% 0, 40% 100%, 65% 100%);
614 | clip-path: polygon(65% 0, 40% 0, 40% 100%, 65% 100%);
615 | }
616 | 94% {
617 | -webkit-clip-path: polygon(45% 0, 50% 0, 50% 100%, 45% 100%);
618 | clip-path: polygon(45% 0, 50% 0, 50% 100%, 45% 100%);
619 | }
620 | 100% {
621 | -webkit-clip-path: polygon(14% 0, 33% 0, 33% 100%, 14% 100%);
622 | clip-path: polygon(14% 0, 33% 0, 33% 100%, 14% 100%);
623 | }
624 | }
625 |
626 | @keyframes glitch-anim-3-vertical {
627 | 0% {
628 | -webkit-clip-path: polygon(1% 0, 3% 0, 3% 100%, 1% 100%);
629 | clip-path: polygon(1% 0, 3% 0, 3% 100%, 1% 100%);
630 | }
631 | 5% {
632 | -webkit-clip-path: polygon(10% 0, 9% 0, 9% 100%, 10% 100%);
633 | clip-path: polygon(10% 0, 9% 0, 9% 100%, 10% 100%);
634 | }
635 | 10% {
636 | -webkit-clip-path: polygon(5% 0, 6% 0 6% 100%, 5% 100%);
637 | clip-path: polygon(5% 0, 6% 0 6% 100%, 5% 100%);
638 | }
639 | 25% {
640 | -webkit-clip-path: polygon(20% 0, 20% 0, 20% 100%, 20% 100%);
641 | clip-path: polygon(20% 0, 20% 0, 20% 100%, 20% 100%);
642 | }
643 | 27% {
644 | -webkit-clip-path: polygon(10% 0, 10% 0, 10% 100%, 10% 100%);
645 | clip-path: polygon(10% 0, 10% 0, 10% 100%, 10% 100%);
646 | }
647 | 30% {
648 | -webkit-clip-path: polygon(30% 0, 25% 0, 25% 100%, 30% 100%);
649 | clip-path: polygon(30% 0, 25% 0, 25% 100%, 30% 100%);
650 | }
651 | 33% {
652 | -webkit-clip-path: polygon(15% 0, 16% 0, 16% 100%, 15% 100%);;
653 | clip-path: polygon(15% 0, 16% 0, 16% 100%, 15% 100%);
654 | }
655 | 37% {
656 | -webkit-clip-path: polygon(40% 0, 39% 0, 39% 100%, 40% 100%);;
657 | clip-path: polygon(40% 0, 39% 0, 39% 100%, 40% 100%);
658 | }
659 | 40% {
660 | -webkit-clip-path: polygon(20% 0, 21% 0, 21% 100%, 20% 100%);
661 | clip-path: polygon(20% 0, 21% 0, 21% 100%, 20% 100%);
662 | }
663 | 45% {
664 | -webkit-clip-path: polygon(60% 0, 55% 0, 55% 100%, 60% 100%);
665 | clip-path: polygon(60% 0, 55% 0, 55% 100%, 60% 100%);
666 | }
667 | 50% {
668 | -webkit-clip-path: polygon(30% 0, 31% 0, 31% 100%, 30% 100%);
669 | clip-path: polygon(30% 0, 31% 0, 31% 100%, 30% 100%);
670 | }
671 | 53% {
672 | -webkit-clip-path: polygon(70% 0, 69% 0, 69% 100%, 70% 100%);
673 | clip-path: polygon(70% 0, 69% 0, 69% 100%, 70% 100%);
674 | }
675 | 57% {
676 | -webkit-clip-path: polygon(40% 0, 41% 0, 41% 100%, 40% 100%);
677 | clip-path: polygon(40% 0, 41% 0, 41% 100%, 40% 100%);
678 | }
679 | 60% {
680 | -webkit-clip-path: polygon(80% 0, 75% 0, 75% 100%, 80% 100%);
681 | clip-path: polygon(80% 0, 75% 0, 75% 100%, 80% 100%);
682 | }
683 | 65% {
684 | -webkit-clip-path: polygon(50% 0, 51% 0, 51% 100%, 50% 100%);
685 | clip-path: polygon(50% 0, 51% 0, 51% 100%, 50% 100%);
686 | }
687 | 70% {
688 | -webkit-clip-path: polygon(90% 0, 90% 0, 90% 100%, 90% 100%);
689 | clip-path: polygon(90% 0, 90% 0, 90% 100%, 90% 100%);
690 | }
691 | 73% {
692 | -webkit-clip-path: polygon(60% 0, 60% 0, 60% 100%, 60% 100%);
693 | clip-path: polygon(60% 0, 60% 0, 60% 100%, 60% 100%);
694 | }
695 | 80% {
696 | -webkit-clip-path: polygon(100% 0, 99% 0, 99% 100%, 100% 100%);
697 | clip-path: polygon(100% 0, 99% 0, 99% 100%, 100% 100%);
698 | }
699 | 100% {
700 | -webkit-clip-path: polygon(70% 0, 71% 0, 71% 100%, 70% 100%);
701 | clip-path: polygon(70% 0, 71% 0, 71% 100%, 70% 100%);
702 | }
703 | }
704 |
705 | /* Flash */
706 | @keyframes glitch-anim-flash {
707 | 0% {
708 | opacity: 0.2;
709 | transform: translate3d(var(--gap-horizontal), var(--gap-vertical), 0);
710 | }
711 | 33%, 100% {
712 | opacity: 0;
713 | transform: translate3d(0,0,0);
714 | }
715 | }
716 |
717 | .item__cover {
718 | grid-area: 1 / 1 / -1 / -1;
719 | background-size: cover;
720 | background-position: 50% 50%;
721 | position: relative;
722 | transition: opacity var(--fade-in-time) var(--fade-in-easing);
723 | pointer-events: none;
724 | }
725 |
726 | .item__cover::after {
727 | content: '';
728 | position: absolute;
729 | width: 100%;
730 | height: 100%;
731 | background: linear-gradient(0deg,rgb(54 58 199 / 38%), rgba(0,0,0,0.2));
732 | }
733 |
734 | .item:hover .item__cover {
735 | opacity: 0;
736 | transition: opacity var(--fade-out-time) var(--fade-out-easing);
737 | }
738 |
739 | .item__content {
740 | display: flex;
741 | flex-direction: column;
742 | pointer-events: none;
743 | padding: 1.5rem;
744 | position: relative;
745 | grid-area: 1 / 1 / -1 / -1;
746 | color: var(--color-label);
747 | }
748 |
749 | .item__content-title {
750 | font-family: park-lane, serif;
751 | font-weight: 300;
752 | font-style: normal;
753 | font-size: clamp(3rem,4vw,5rem);
754 | line-height: 1;
755 | margin: 0;
756 | }
757 |
758 | .item:hover .item__content-title,
759 | .item:hover .item__content-label {
760 | color: var(--content-hover);
761 | }
762 |
763 | .item__content-label {
764 | margin: auto 0 0;
765 | }
766 |
767 | blockquote {
768 | font-weight: 500;
769 | font-size: clamp(1rem, 2vw, 1.25rem);
770 | }
771 |
772 | @media screen and (min-width: 53em) {
773 | .frame {
774 | text-align: center;
775 | display: grid;
776 | grid-template-columns: auto auto;
777 | grid-template-rows: auto auto;
778 | grid-template-areas: 'title sponsor' 'demos demos';
779 | grid-row-gap: 1rem;
780 | align-content: space-between;
781 | }
782 | .frame__title {
783 | grid-area: title;
784 | display: grid;
785 | grid-auto-flow: column;
786 | grid-template-columns: auto auto 1fr;
787 | align-items: start;
788 | justify-items: flex-start;
789 | }
790 | .frame__demos {
791 | grid-area: demos;
792 | justify-self: end;
793 | }
794 | .frame__demo {
795 | margin: 0 0 0 1rem;
796 | }
797 | .intro {
798 | display: grid;
799 | grid-column-gap: 1rem;
800 | grid-template-areas: 'title desc'
801 | 'title button';
802 | justify-content: space-between;
803 | align-items: start;
804 | text-align: right;
805 | }
806 | }
807 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/favicon.ico
--------------------------------------------------------------------------------
/img/1.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/1.avif
--------------------------------------------------------------------------------
/img/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/1.png
--------------------------------------------------------------------------------
/img/10.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/10.avif
--------------------------------------------------------------------------------
/img/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/10.png
--------------------------------------------------------------------------------
/img/11.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/11.avif
--------------------------------------------------------------------------------
/img/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/11.png
--------------------------------------------------------------------------------
/img/12.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/12.avif
--------------------------------------------------------------------------------
/img/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/12.png
--------------------------------------------------------------------------------
/img/13.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/13.avif
--------------------------------------------------------------------------------
/img/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/13.png
--------------------------------------------------------------------------------
/img/14.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/14.avif
--------------------------------------------------------------------------------
/img/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/14.png
--------------------------------------------------------------------------------
/img/15.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/15.avif
--------------------------------------------------------------------------------
/img/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/15.png
--------------------------------------------------------------------------------
/img/2.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/2.avif
--------------------------------------------------------------------------------
/img/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/2.png
--------------------------------------------------------------------------------
/img/3.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/3.avif
--------------------------------------------------------------------------------
/img/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/3.png
--------------------------------------------------------------------------------
/img/4.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/4.avif
--------------------------------------------------------------------------------
/img/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/4.png
--------------------------------------------------------------------------------
/img/5.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/5.avif
--------------------------------------------------------------------------------
/img/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/5.png
--------------------------------------------------------------------------------
/img/6.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/6.avif
--------------------------------------------------------------------------------
/img/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/6.png
--------------------------------------------------------------------------------
/img/7.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/7.avif
--------------------------------------------------------------------------------
/img/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/7.png
--------------------------------------------------------------------------------
/img/8.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/8.avif
--------------------------------------------------------------------------------
/img/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/8.png
--------------------------------------------------------------------------------
/img/9.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/9.avif
--------------------------------------------------------------------------------
/img/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/GlitchPerspective/80f9295118011ad55691398d2cec220ecf8c8f74/img/9.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 3D Perspective Glitch Hover Effect | Demo 1 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
33 |
34 |
35 | Techno
36 | workshop
37 |
38 |
39 | Techno Workshop is a collective of the weirdest creative minds. We share art and inspiration and create design contests to showcase futile but cute additions to the consumer world.
40 |
41 |
Create with us
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | Wallace MacKenzie
55 | Uplift, 2001
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Gunnar Redsocks
69 | The Fashion Drop, 2003
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Frankie Tankie
83 | Constant Ink, 2010
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | Helder Brunckhorst
97 | Happy Space, 2011
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Bolder Da Mouth
111 | Freedom Press, 2012
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | Marie Sockamoodle
125 | Fashion House, 2013
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | Walter Meckage
139 | The Hotel Room, 2019
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | Kelly Braylor
153 | Chique, 2020
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | Fundo Constanza
167 | Love Affair, 2015
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | Bernie Kunst
181 | Decadence, 2017
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | Sandra M. Lester
195 | Drifters, 2018
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | Mister DonGold
209 | The Shift, 2021
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 | Laura Murdoch
223 | Trendphile, 2017
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 | John Van Hoff
237 | The Lace, 2018
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 | Armin Harbinger
251 | Fringe Punch, 2022
252 |
253 |
254 |
255 |
256 | The disruption of everyday reality, effects on instinct
257 | rational, irrational, expression, depression, to be persuaded.
258 | Assessments, values, from glancing in a mirror and the wider
259 | significance of commentaries, refrains, classifieds, link to chaos!
260 | The exploitation and denial of confirmation
261 | Pre-conceptions, non-threatening; bright lights.
262 |
263 | Enamour encore by Sunny Jetsun
264 |
265 |
266 |
267 |
268 |
269 |
--------------------------------------------------------------------------------
/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 3D Perspective Glitch Hover Effect | Demo 2 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
33 |
34 |
35 | Techno
36 | workshop
37 |
38 |
39 | Techno Workshop is a collective of the weirdest creative minds. We share art and inspiration and create design contests to showcase futile but cute additions to the consumer world.
40 |
41 |
Create with us
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | Wallace MacKenzie
55 | Uplift, 2001
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Gunnar Redsocks
69 | The Fashion Drop, 2003
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Frankie Tankie
83 | Constant Ink, 2010
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | Helder Brunckhorst
97 | Happy Space, 2011
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Bolder Da Mouth
111 | Freedom Press, 2012
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | Marie Sockamoodle
125 | Fashion House, 2013
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | Walter Meckage
139 | The Hotel Room, 2019
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | Kelly Braylor
153 | Chique, 2020
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | Fundo Constanza
167 | Love Affair, 2015
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | Bernie Kunst
181 | Decadence, 2017
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | Sandra M. Lester
195 | Drifters, 2018
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | Mister DonGold
209 | The Shift, 2021
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 | Laura Murdoch
223 | Trendphile, 2017
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 | John Van Hoff
237 | The Lace, 2018
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 | Armin Harbinger
251 | Fringe Punch, 2022
252 |
253 |
254 |
255 |
256 | The disruption of everyday reality, effects on instinct
257 | rational, irrational, expression, depression, to be persuaded.
258 | Assessments, values, from glancing in a mirror and the wider
259 | significance of commentaries, refrains, classifieds, link to chaos!
260 | The exploitation and denial of confirmation
261 | Pre-conceptions, non-threatening; bright lights.
262 |
263 | Enamour encore by Sunny Jetsun
264 |
265 |
266 |
267 |
268 |
269 |
270 |
--------------------------------------------------------------------------------
/js/vanilla-tilt.js:
--------------------------------------------------------------------------------
1 | var VanillaTilt = (function () {
2 | 'use strict';
3 |
4 | /**
5 | * Created by Sergiu Șandor (micku7zu) on 1/27/2017.
6 | * Original idea: https://github.com/gijsroge/tilt.js
7 | * MIT License.
8 | * Version 1.7.2
9 | */
10 |
11 | class VanillaTilt {
12 | constructor(element, settings = {}) {
13 | if (!(element instanceof Node)) {
14 | throw ("Can't initialize VanillaTilt because " + element + " is not a Node.");
15 | }
16 |
17 | this.width = null;
18 | this.height = null;
19 | this.clientWidth = null;
20 | this.clientHeight = null;
21 | this.left = null;
22 | this.top = null;
23 |
24 | // for Gyroscope sampling
25 | this.gammazero = null;
26 | this.betazero = null;
27 | this.lastgammazero = null;
28 | this.lastbetazero = null;
29 |
30 | this.transitionTimeout = null;
31 | this.updateCall = null;
32 | this.event = null;
33 |
34 | this.updateBind = this.update.bind(this);
35 | this.resetBind = this.reset.bind(this);
36 |
37 | this.element = element;
38 | this.settings = this.extendSettings(settings);
39 |
40 | this.reverse = this.settings.reverse ? -1 : 1;
41 | this.glare = VanillaTilt.isSettingTrue(this.settings.glare);
42 | this.glarePrerender = VanillaTilt.isSettingTrue(this.settings["glare-prerender"]);
43 | this.fullPageListening = VanillaTilt.isSettingTrue(this.settings["full-page-listening"]);
44 | this.gyroscope = VanillaTilt.isSettingTrue(this.settings.gyroscope);
45 | this.gyroscopeSamples = this.settings.gyroscopeSamples;
46 |
47 | this.elementListener = this.getElementListener();
48 |
49 | if (this.glare) {
50 | this.prepareGlare();
51 | }
52 |
53 | if (this.fullPageListening) {
54 | this.updateClientSize();
55 | }
56 |
57 | this.addEventListeners();
58 | this.reset();
59 | this.updateInitialPosition();
60 | }
61 |
62 | static isSettingTrue(setting) {
63 | return setting === "" || setting === true || setting === 1;
64 | }
65 |
66 | /**
67 | * Method returns element what will be listen mouse events
68 | * @return {Node}
69 | */
70 | getElementListener() {
71 | if (this.fullPageListening) {
72 | return window.document;
73 | }
74 |
75 | if (typeof this.settings["mouse-event-element"] === "string") {
76 | const mouseEventElement = document.querySelector(this.settings["mouse-event-element"]);
77 |
78 | if (mouseEventElement) {
79 | return mouseEventElement;
80 | }
81 | }
82 |
83 | if (this.settings["mouse-event-element"] instanceof Node) {
84 | return this.settings["mouse-event-element"];
85 | }
86 |
87 | return this.element;
88 | }
89 |
90 | /**
91 | * Method set listen methods for this.elementListener
92 | * @return {Node}
93 | */
94 | addEventListeners() {
95 | this.onMouseEnterBind = this.onMouseEnter.bind(this);
96 | this.onMouseMoveBind = this.onMouseMove.bind(this);
97 | this.onMouseLeaveBind = this.onMouseLeave.bind(this);
98 | this.onWindowResizeBind = this.onWindowResize.bind(this);
99 | this.onDeviceOrientationBind = this.onDeviceOrientation.bind(this);
100 |
101 | this.elementListener.addEventListener("mouseenter", this.onMouseEnterBind);
102 | this.elementListener.addEventListener("mouseleave", this.onMouseLeaveBind);
103 | this.elementListener.addEventListener("mousemove", this.onMouseMoveBind);
104 |
105 | if (this.glare || this.fullPageListening) {
106 | window.addEventListener("resize", this.onWindowResizeBind);
107 | }
108 |
109 | if (this.gyroscope) {
110 | window.addEventListener("deviceorientation", this.onDeviceOrientationBind);
111 | }
112 | }
113 |
114 | /**
115 | * Method remove event listeners from current this.elementListener
116 | */
117 | removeEventListeners() {
118 | this.elementListener.removeEventListener("mouseenter", this.onMouseEnterBind);
119 | this.elementListener.removeEventListener("mouseleave", this.onMouseLeaveBind);
120 | this.elementListener.removeEventListener("mousemove", this.onMouseMoveBind);
121 |
122 | if (this.gyroscope) {
123 | window.removeEventListener("deviceorientation", this.onDeviceOrientationBind);
124 | }
125 |
126 | if (this.glare || this.fullPageListening) {
127 | window.removeEventListener("resize", this.onWindowResizeBind);
128 | }
129 | }
130 |
131 | destroy() {
132 | clearTimeout(this.transitionTimeout);
133 | if (this.updateCall !== null) {
134 | cancelAnimationFrame(this.updateCall);
135 | }
136 |
137 | this.reset();
138 |
139 | this.removeEventListeners();
140 | this.element.vanillaTilt = null;
141 | delete this.element.vanillaTilt;
142 |
143 | this.element = null;
144 | }
145 |
146 | onDeviceOrientation(event) {
147 | if (event.gamma === null || event.beta === null) {
148 | return;
149 | }
150 |
151 | this.updateElementPosition();
152 |
153 | if (this.gyroscopeSamples > 0) {
154 | this.lastgammazero = this.gammazero;
155 | this.lastbetazero = this.betazero;
156 |
157 | if (this.gammazero === null) {
158 | this.gammazero = event.gamma;
159 | this.betazero = event.beta;
160 | } else {
161 | this.gammazero = (event.gamma + this.lastgammazero) / 2;
162 | this.betazero = (event.beta + this.lastbetazero) / 2;
163 | }
164 |
165 | this.gyroscopeSamples -= 1;
166 | }
167 |
168 | const totalAngleX = this.settings.gyroscopeMaxAngleX - this.settings.gyroscopeMinAngleX;
169 | const totalAngleY = this.settings.gyroscopeMaxAngleY - this.settings.gyroscopeMinAngleY;
170 |
171 | const degreesPerPixelX = totalAngleX / this.width;
172 | const degreesPerPixelY = totalAngleY / this.height;
173 |
174 | const angleX = event.gamma - (this.settings.gyroscopeMinAngleX + this.gammazero);
175 | const angleY = event.beta - (this.settings.gyroscopeMinAngleY + this.betazero);
176 |
177 | const posX = angleX / degreesPerPixelX;
178 | const posY = angleY / degreesPerPixelY;
179 |
180 | if (this.updateCall !== null) {
181 | cancelAnimationFrame(this.updateCall);
182 | }
183 |
184 | this.event = {
185 | clientX: posX + this.left,
186 | clientY: posY + this.top,
187 | };
188 |
189 | this.updateCall = requestAnimationFrame(this.updateBind);
190 | }
191 |
192 | onMouseEnter() {
193 | this.updateElementPosition();
194 | this.element.style.willChange = "transform";
195 | this.setTransition();
196 | }
197 |
198 | onMouseMove(event) {
199 | if (this.updateCall !== null) {
200 | cancelAnimationFrame(this.updateCall);
201 | }
202 |
203 | this.event = event;
204 | this.updateCall = requestAnimationFrame(this.updateBind);
205 | }
206 |
207 | onMouseLeave() {
208 | this.setTransition();
209 |
210 | if (this.settings.reset) {
211 | requestAnimationFrame(this.resetBind);
212 | }
213 | }
214 |
215 | reset() {
216 | this.event = {
217 | clientX: this.left + this.width / 2,
218 | clientY: this.top + this.height / 2
219 | };
220 |
221 | if (this.element && this.element.style) {
222 | this.element.style.transform = `perspective(${this.settings.perspective}px) ` +
223 | `rotateX(0deg) ` +
224 | `rotateY(0deg) ` +
225 | `scale3d(1, 1, 1)`;
226 | }
227 |
228 | this.resetGlare();
229 | }
230 |
231 | resetGlare() {
232 | if (this.glare) {
233 | this.glareElement.style.transform = "rotate(180deg) translate(-50%, -50%)";
234 | this.glareElement.style.opacity = "0";
235 | }
236 | }
237 |
238 | updateInitialPosition() {
239 | if (this.settings.startX === 0 && this.settings.startY === 0) {
240 | return;
241 | }
242 |
243 | this.onMouseEnter();
244 |
245 | if (this.fullPageListening) {
246 | this.event = {
247 | clientX: (this.settings.startX + this.settings.max) / (2 * this.settings.max) * this.clientWidth,
248 | clientY: (this.settings.startY + this.settings.max) / (2 * this.settings.max) * this.clientHeight
249 | };
250 | } else {
251 | this.event = {
252 | clientX: this.left + ((this.settings.startX + this.settings.max) / (2 * this.settings.max) * this.width),
253 | clientY: this.top + ((this.settings.startY + this.settings.max) / (2 * this.settings.max) * this.height)
254 | };
255 | }
256 |
257 |
258 | let backupScale = this.settings.scale;
259 | this.settings.scale = 1;
260 | this.update();
261 | this.settings.scale = backupScale;
262 | this.resetGlare();
263 | }
264 |
265 | getValues() {
266 | let x, y;
267 |
268 | if (this.fullPageListening) {
269 | x = this.event.clientX / this.clientWidth;
270 | y = this.event.clientY / this.clientHeight;
271 | } else {
272 | x = (this.event.clientX - this.left) / this.width;
273 | y = (this.event.clientY - this.top) / this.height;
274 | }
275 |
276 | x = Math.min(Math.max(x, 0), 1);
277 | y = Math.min(Math.max(y, 0), 1);
278 |
279 | let tiltX = (this.reverse * (this.settings.max - x * this.settings.max * 2)).toFixed(2);
280 | let tiltY = (this.reverse * (y * this.settings.max * 2 - this.settings.max)).toFixed(2);
281 | let angle = Math.atan2(this.event.clientX - (this.left + this.width / 2), -(this.event.clientY - (this.top + this.height / 2))) * (180 / Math.PI);
282 |
283 | return {
284 | tiltX: tiltX,
285 | tiltY: tiltY,
286 | percentageX: x * 100,
287 | percentageY: y * 100,
288 | angle: angle
289 | };
290 | }
291 |
292 | updateElementPosition() {
293 | let rect = this.element.getBoundingClientRect();
294 |
295 | this.width = this.element.offsetWidth;
296 | this.height = this.element.offsetHeight;
297 | this.left = rect.left;
298 | this.top = rect.top;
299 | }
300 |
301 | update() {
302 | let values = this.getValues();
303 |
304 | this.element.style.transform = "perspective(" + this.settings.perspective + "px) " +
305 | "rotateX(" + (this.settings.axis === "x" ? 0 : values.tiltY) + "deg) " +
306 | "rotateY(" + (this.settings.axis === "y" ? 0 : values.tiltX) + "deg) " +
307 | "scale3d(" + this.settings.scale + ", " + this.settings.scale + ", " + this.settings.scale + ")";
308 |
309 | if (this.glare) {
310 | this.glareElement.style.transform = `rotate(${values.angle}deg) translate(-50%, -50%)`;
311 | this.glareElement.style.opacity = `${values.percentageY * this.settings["max-glare"] / 100}`;
312 | }
313 |
314 | this.element.dispatchEvent(new CustomEvent("tiltChange", {
315 | "detail": values
316 | }));
317 |
318 | this.updateCall = null;
319 | }
320 |
321 | /**
322 | * Appends the glare element (if glarePrerender equals false)
323 | * and sets the default style
324 | */
325 | prepareGlare() {
326 | // If option pre-render is enabled we assume all html/css is present for an optimal glare effect.
327 | if (!this.glarePrerender) {
328 | // Create glare element
329 | const jsTiltGlare = document.createElement("div");
330 | jsTiltGlare.classList.add("js-tilt-glare");
331 |
332 | const jsTiltGlareInner = document.createElement("div");
333 | jsTiltGlareInner.classList.add("js-tilt-glare-inner");
334 |
335 | jsTiltGlare.appendChild(jsTiltGlareInner);
336 | this.element.appendChild(jsTiltGlare);
337 | }
338 |
339 | this.glareElementWrapper = this.element.querySelector(".js-tilt-glare");
340 | this.glareElement = this.element.querySelector(".js-tilt-glare-inner");
341 |
342 | if (this.glarePrerender) {
343 | return;
344 | }
345 |
346 | Object.assign(this.glareElementWrapper.style, {
347 | "position": "absolute",
348 | "top": "0",
349 | "left": "0",
350 | "width": "100%",
351 | "height": "100%",
352 | "overflow": "hidden",
353 | "pointer-events": "none"
354 | });
355 |
356 | Object.assign(this.glareElement.style, {
357 | "position": "absolute",
358 | "top": "50%",
359 | "left": "50%",
360 | "pointer-events": "none",
361 | "background-image": `linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%)`,
362 | "transform": "rotate(180deg) translate(-50%, -50%)",
363 | "transform-origin": "0% 0%",
364 | "opacity": "0",
365 | });
366 |
367 | this.updateGlareSize();
368 | }
369 |
370 | updateGlareSize() {
371 | if (this.glare) {
372 | const glareSize = (this.element.offsetWidth > this.element.offsetHeight ? this.element.offsetWidth : this.element.offsetHeight) * 2;
373 |
374 | Object.assign(this.glareElement.style, {
375 | "width": `${glareSize}px`,
376 | "height": `${glareSize}px`,
377 | });
378 | }
379 | }
380 |
381 | updateClientSize() {
382 | this.clientWidth = window.innerWidth
383 | || document.documentElement.clientWidth
384 | || document.body.clientWidth;
385 |
386 | this.clientHeight = window.innerHeight
387 | || document.documentElement.clientHeight
388 | || document.body.clientHeight;
389 | }
390 |
391 | onWindowResize() {
392 | this.updateGlareSize();
393 | this.updateClientSize();
394 | }
395 |
396 | setTransition() {
397 | clearTimeout(this.transitionTimeout);
398 | this.element.style.transition = this.settings.speed + "ms " + this.settings.easing;
399 | if (this.glare) this.glareElement.style.transition = `opacity ${this.settings.speed}ms ${this.settings.easing}`;
400 |
401 | this.transitionTimeout = setTimeout(() => {
402 | this.element.style.transition = "";
403 | if (this.glare) {
404 | this.glareElement.style.transition = "";
405 | }
406 | }, this.settings.speed);
407 |
408 | }
409 |
410 | /**
411 | * Method return patched settings of instance
412 | * @param {boolean} settings.reverse - reverse the tilt direction
413 | * @param {number} settings.max - max tilt rotation (degrees)
414 | * @param {startX} settings.startX - the starting tilt on the X axis, in degrees. Default: 0
415 | * @param {startY} settings.startY - the starting tilt on the Y axis, in degrees. Default: 0
416 | * @param {number} settings.perspective - Transform perspective, the lower the more extreme the tilt gets
417 | * @param {string} settings.easing - Easing on enter/exit
418 | * @param {number} settings.scale - 2 = 200%, 1.5 = 150%, etc..
419 | * @param {number} settings.speed - Speed of the enter/exit transition
420 | * @param {boolean} settings.transition - Set a transition on enter/exit
421 | * @param {string|null} settings.axis - What axis should be disabled. Can be X or Y
422 | * @param {boolean} settings.glare - What axis should be disabled. Can be X or Y
423 | * @param {number} settings.max-glare - the maximum "glare" opacity (1 = 100%, 0.5 = 50%)
424 | * @param {boolean} settings.glare-prerender - false = VanillaTilt creates the glare elements for you, otherwise
425 | * @param {boolean} settings.full-page-listening - If true, parallax effect will listen to mouse move events on the whole document, not only the selected element
426 | * @param {string|object} settings.mouse-event-element - String selector or link to HTML-element what will be listen mouse events
427 | * @param {boolean} settings.reset - false = If the tilt effect has to be reset on exit
428 | * @param {gyroscope} settings.gyroscope - Enable tilting by deviceorientation events
429 | * @param {gyroscopeSensitivity} settings.gyroscopeSensitivity - Between 0 and 1 - The angle at which max tilt position is reached. 1 = 90deg, 0.5 = 45deg, etc..
430 | * @param {gyroscopeSamples} settings.gyroscopeSamples - How many gyroscope moves to decide the starting position.
431 | */
432 | extendSettings(settings) {
433 | let defaultSettings = {
434 | reverse: false,
435 | max: 15,
436 | startX: 0,
437 | startY: 0,
438 | perspective: 1000,
439 | easing: "cubic-bezier(.03,.98,.52,.99)",
440 | scale: 1,
441 | speed: 300,
442 | transition: true,
443 | axis: null,
444 | glare: false,
445 | "max-glare": 1,
446 | "glare-prerender": false,
447 | "full-page-listening": false,
448 | "mouse-event-element": null,
449 | reset: true,
450 | gyroscope: true,
451 | gyroscopeMinAngleX: -45,
452 | gyroscopeMaxAngleX: 45,
453 | gyroscopeMinAngleY: -45,
454 | gyroscopeMaxAngleY: 45,
455 | gyroscopeSamples: 10
456 | };
457 |
458 | let newSettings = {};
459 | for (var property in defaultSettings) {
460 | if (property in settings) {
461 | newSettings[property] = settings[property];
462 | } else if (this.element.hasAttribute("data-tilt-" + property)) {
463 | let attribute = this.element.getAttribute("data-tilt-" + property);
464 | try {
465 | newSettings[property] = JSON.parse(attribute);
466 | } catch (e) {
467 | newSettings[property] = attribute;
468 | }
469 |
470 | } else {
471 | newSettings[property] = defaultSettings[property];
472 | }
473 | }
474 |
475 | return newSettings;
476 | }
477 |
478 | static init(elements, settings) {
479 | if (elements instanceof Node) {
480 | elements = [elements];
481 | }
482 |
483 | if (elements instanceof NodeList) {
484 | elements = [].slice.call(elements);
485 | }
486 |
487 | if (!(elements instanceof Array)) {
488 | return;
489 | }
490 |
491 | elements.forEach((element) => {
492 | if (!("vanillaTilt" in element)) {
493 | element.vanillaTilt = new VanillaTilt(element, settings);
494 | }
495 | });
496 | }
497 | }
498 |
499 | if (typeof document !== "undefined") {
500 | /* expose the class to window */
501 | window.VanillaTilt = VanillaTilt;
502 |
503 | /**
504 | * Auto load
505 | */
506 | VanillaTilt.init(document.querySelectorAll("[data-tilt]"));
507 | }
508 |
509 | return VanillaTilt;
510 |
511 | }());
--------------------------------------------------------------------------------