From 29324fca974170fe2757f66056e30944a03146b9 Mon Sep 17 00:00:00 2001 From: Powermacintosh Date: Sat, 4 Apr 2026 21:40:15 +0300 Subject: [PATCH] =?UTF-8?q?init:=20=D0=BA=D0=BE=D0=BB=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit — Добавлен Rolling Letters Loader (текстовый барабан) — Добавлен Helix DNA Loader (3D спираль) — Добавлен Lightsaber Fight Loader (сражение на мечах) — Добавлен Pancake Cooking Loader (подбрасывание блинчика) — Добавлен Pong Game Loader (ретро-игра) — Создан общий README.md с навигационной таблицей --- README.md | 20 + helix-dna/README.md | 15 + helix-dna/src/index.html | 42 ++ helix-dna/src/style.css | 355 +++++++++++++++++ helix-dna/src/style.scss | 109 +++++ lightsaber/README.md | 15 + lightsaber/src/index.html | 28 ++ lightsaber/src/style.css | 765 ++++++++++++++++++++++++++++++++++++ pancake/README.md | 15 + pancake/src/index.html | 31 ++ pancake/src/style.css | 236 +++++++++++ pancake/src/style.scss | 250 ++++++++++++ pong-game/README.md | 15 + pong-game/src/index.html | 20 + pong-game/src/style.css | 80 ++++ pong-game/src/style.scss | 84 ++++ rolling-text/README.md | 14 + rolling-text/src/index.html | 22 ++ rolling-text/src/style.css | 86 ++++ 19 files changed, 2202 insertions(+) create mode 100644 README.md create mode 100755 helix-dna/README.md create mode 100755 helix-dna/src/index.html create mode 100755 helix-dna/src/style.css create mode 100755 helix-dna/src/style.scss create mode 100755 lightsaber/README.md create mode 100755 lightsaber/src/index.html create mode 100755 lightsaber/src/style.css create mode 100755 pancake/README.md create mode 100755 pancake/src/index.html create mode 100755 pancake/src/style.css create mode 100755 pancake/src/style.scss create mode 100755 pong-game/README.md create mode 100755 pong-game/src/index.html create mode 100755 pong-game/src/style.css create mode 100755 pong-game/src/style.scss create mode 100755 rolling-text/README.md create mode 100755 rolling-text/src/index.html create mode 100755 rolling-text/src/style.css diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd7d762 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# ⌛ Animated Loaders Collection + +Сборник эффектных индикаторов загрузки для современных веб-интерфейсов. +Все лоадеры реализованы на **Pure CSS**, что гарантирует высокую производительность и отсутствие лишних зависимостей. + +## Обзор коллекции + +| Превью | Компонент | Стиль | Особенности | +| :----- | :----------------------------------- | :----------- | :------------------------------------------ | +| 🎰 | [`Rolling Letters`](./rolling-text/) | Текстовый | Эффект барабана и каскадное выпадение букв. | +| 🧬 | [`Helix DNA`](./helix-dna/) | 3D / Научный | Сложная анимация вращения двойной спирали. | +| ⚔️ | [`Lightsaber Fight`](./lightsaber/) | Креатив | Мини-сюжет сражения на мечах с искрами. | +| 🥞 | [`Pancake Cooking`](./pancake/) | Сюжетный | Детальная анимация подбрасывания блинчика. | +| 🎾 | [`Pong Game`](./pong-game/) | Ретро | Минималистичный геймплей легендарной игры. | + +## Технологии + +- **HTML5** (Семантическая разметка) +- **CSS3 Animations** (`@keyframes`, `transitions`, `transforms`) +- **Zero JS** (Все анимации работают исключительно на стилях) diff --git a/helix-dna/README.md b/helix-dna/README.md new file mode 100755 index 0000000..aacc2de --- /dev/null +++ b/helix-dna/README.md @@ -0,0 +1,15 @@ +# 🧬 Helix CSS Loader + +Сложный анимированный лоадер, имитирующий вращение двойной спирали (DNA Helix). Построен на чистом CSS с использованием 26 анимированных элементов. + +### Особенности + +- **3D Illusion**: Эффект объема достигается за счет синхронизации перемещения (`translate3d`), изменения масштаба (`scale`) и управления слоями (`z-index`). +- **Smooth Gradient**: Фон с использованием `linear-gradient` подчеркивает глубину анимации. +- **Pure CSS**: Не требует JavaScript, вся логика завязана на задержках (`animation-delay`) для каждого отдельного "узла" спирали. + +### Технические детали + +- **Movement**: Ключевой кадр `@keyframes movement` отвечает за вертикальное перемещение. +- **Size/Opacity**: `@keyframes size-opacity` создает эффект приближения и удаления точек, меняя их размер и прозрачность. +- **Dual Color**: Четные и нечетные элементы имеют разные цвета (белый и ярко-розовый) для визуального разделения двух нитей спирали. diff --git a/helix-dna/src/index.html b/helix-dna/src/index.html new file mode 100755 index 0000000..e200069 --- /dev/null +++ b/helix-dna/src/index.html @@ -0,0 +1,42 @@ + + + + + Helix CSS Loader + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + diff --git a/helix-dna/src/style.css b/helix-dna/src/style.css new file mode 100755 index 0000000..54d0a93 --- /dev/null +++ b/helix-dna/src/style.css @@ -0,0 +1,355 @@ +html, +body { + height: 100%; +} + +body { + align-items: center; + background: #d65b9e; + background: linear-gradient(45deg, #d65b9e 1%, #f699cb 22%, #ffacd9 51%, #f699cb 83%, #d65b9e 100%); + display: flex; + justify-content: center; +} + +.loader { + position: relative; +} +.loader .dot { + -webkit-animation-name: movement; + animation-name: movement; + -webkit-animation-duration: 2s; + animation-duration: 2s; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + height: 10px; + position: absolute; + top: -10px; + transform: translate3d(0, -25px, 0) scale(1); + width: 10px; +} +.loader .dot:nth-of-type(1) { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; + left: 150px; +} +.loader .dot:nth-of-type(1)::before { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; +} +.loader .dot:nth-of-type(2) { + -webkit-animation-delay: -1.2s; + animation-delay: -1.2s; + left: 150px; +} +.loader .dot:nth-of-type(2)::before { + -webkit-animation-delay: -1.2s; + animation-delay: -1.2s; +} +.loader .dot:nth-of-type(3) { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; + left: 125px; +} +.loader .dot:nth-of-type(3)::before { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; +} +.loader .dot:nth-of-type(4) { + -webkit-animation-delay: -1.4s; + animation-delay: -1.4s; + left: 125px; +} +.loader .dot:nth-of-type(4)::before { + -webkit-animation-delay: -1.4s; + animation-delay: -1.4s; +} +.loader .dot:nth-of-type(5) { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; + left: 100px; +} +.loader .dot:nth-of-type(5)::before { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; +} +.loader .dot:nth-of-type(6) { + -webkit-animation-delay: -1.6s; + animation-delay: -1.6s; + left: 100px; +} +.loader .dot:nth-of-type(6)::before { + -webkit-animation-delay: -1.6s; + animation-delay: -1.6s; +} +.loader .dot:nth-of-type(7) { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; + left: 75px; +} +.loader .dot:nth-of-type(7)::before { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; +} +.loader .dot:nth-of-type(8) { + -webkit-animation-delay: -1.8s; + animation-delay: -1.8s; + left: 75px; +} +.loader .dot:nth-of-type(8)::before { + -webkit-animation-delay: -1.8s; + animation-delay: -1.8s; +} +.loader .dot:nth-of-type(9) { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; + left: 50px; +} +.loader .dot:nth-of-type(9)::before { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} +.loader .dot:nth-of-type(10) { + -webkit-animation-delay: -2s; + animation-delay: -2s; + left: 50px; +} +.loader .dot:nth-of-type(10)::before { + -webkit-animation-delay: -2s; + animation-delay: -2s; +} +.loader .dot:nth-of-type(11) { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; + left: 25px; +} +.loader .dot:nth-of-type(11)::before { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} +.loader .dot:nth-of-type(12) { + -webkit-animation-delay: -2.2s; + animation-delay: -2.2s; + left: 25px; +} +.loader .dot:nth-of-type(12)::before { + -webkit-animation-delay: -2.2s; + animation-delay: -2.2s; +} +.loader .dot:nth-of-type(13) { + -webkit-animation-delay: -1.3s; + animation-delay: -1.3s; + left: 0px; +} +.loader .dot:nth-of-type(13)::before { + -webkit-animation-delay: -1.3s; + animation-delay: -1.3s; +} +.loader .dot:nth-of-type(14) { + -webkit-animation-delay: -2.4s; + animation-delay: -2.4s; + left: 0px; +} +.loader .dot:nth-of-type(14)::before { + -webkit-animation-delay: -2.4s; + animation-delay: -2.4s; +} +.loader .dot:nth-of-type(15) { + -webkit-animation-delay: -1.5s; + animation-delay: -1.5s; + left: -25px; +} +.loader .dot:nth-of-type(15)::before { + -webkit-animation-delay: -1.5s; + animation-delay: -1.5s; +} +.loader .dot:nth-of-type(16) { + -webkit-animation-delay: -2.6s; + animation-delay: -2.6s; + left: -25px; +} +.loader .dot:nth-of-type(16)::before { + -webkit-animation-delay: -2.6s; + animation-delay: -2.6s; +} +.loader .dot:nth-of-type(17) { + -webkit-animation-delay: -1.7s; + animation-delay: -1.7s; + left: -50px; +} +.loader .dot:nth-of-type(17)::before { + -webkit-animation-delay: -1.7s; + animation-delay: -1.7s; +} +.loader .dot:nth-of-type(18) { + -webkit-animation-delay: -2.8s; + animation-delay: -2.8s; + left: -50px; +} +.loader .dot:nth-of-type(18)::before { + -webkit-animation-delay: -2.8s; + animation-delay: -2.8s; +} +.loader .dot:nth-of-type(19) { + -webkit-animation-delay: -1.9s; + animation-delay: -1.9s; + left: -75px; +} +.loader .dot:nth-of-type(19)::before { + -webkit-animation-delay: -1.9s; + animation-delay: -1.9s; +} +.loader .dot:nth-of-type(20) { + -webkit-animation-delay: -3s; + animation-delay: -3s; + left: -75px; +} +.loader .dot:nth-of-type(20)::before { + -webkit-animation-delay: -3s; + animation-delay: -3s; +} +.loader .dot:nth-of-type(21) { + -webkit-animation-delay: -2.1s; + animation-delay: -2.1s; + left: -100px; +} +.loader .dot:nth-of-type(21)::before { + -webkit-animation-delay: -2.1s; + animation-delay: -2.1s; +} +.loader .dot:nth-of-type(22) { + -webkit-animation-delay: -3.2s; + animation-delay: -3.2s; + left: -100px; +} +.loader .dot:nth-of-type(22)::before { + -webkit-animation-delay: -3.2s; + animation-delay: -3.2s; +} +.loader .dot:nth-of-type(23) { + -webkit-animation-delay: -2.3s; + animation-delay: -2.3s; + left: -125px; +} +.loader .dot:nth-of-type(23)::before { + -webkit-animation-delay: -2.3s; + animation-delay: -2.3s; +} +.loader .dot:nth-of-type(24) { + -webkit-animation-delay: -3.4s; + animation-delay: -3.4s; + left: -125px; +} +.loader .dot:nth-of-type(24)::before { + -webkit-animation-delay: -3.4s; + animation-delay: -3.4s; +} +.loader .dot:nth-of-type(25) { + -webkit-animation-delay: -2.5s; + animation-delay: -2.5s; + left: -150px; +} +.loader .dot:nth-of-type(25)::before { + -webkit-animation-delay: -2.5s; + animation-delay: -2.5s; +} +.loader .dot:nth-of-type(26) { + -webkit-animation-delay: -3.6s; + animation-delay: -3.6s; + left: -150px; +} +.loader .dot:nth-of-type(26)::before { + -webkit-animation-delay: -3.6s; + animation-delay: -3.6s; +} +.loader .dot::before { + -webkit-animation-name: size-opacity; + animation-name: size-opacity; + -webkit-animation-duration: 2s; + animation-duration: 2s; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + -webkit-animation-timing-function: ease; + animation-timing-function: ease; + background: white; + border-radius: 50%; + content: ""; + display: block; + height: 100%; + width: 100%; +} +.loader .dot:nth-of-type(even)::before { + background-color: #ff47aa; + box-shadow: inset 0 0 4px #ff1492; +} + +@-webkit-keyframes movement { + 0% { + transform: translate3d(0, -25px, 0); + z-index: 0; + } + 50% { + transform: translate3d(0, 25px, 0); + z-index: 10; + } + 100% { + transform: translate3d(0, -25px, 0); + z-index: -5; + } +} + +@keyframes movement { + 0% { + transform: translate3d(0, -25px, 0); + z-index: 0; + } + 50% { + transform: translate3d(0, 25px, 0); + z-index: 10; + } + 100% { + transform: translate3d(0, -25px, 0); + z-index: -5; + } +} +@-webkit-keyframes size-opacity { + 0% { + opacity: 1; + transform: scale(1); + } + 25% { + transform: scale(1.5); + } + 50% { + opacity: 1; + } + 75% { + opacity: 0.35; + transform: scale(0.5); + } + 100% { + opacity: 1; + transform: scale(1); + } +} +@keyframes size-opacity { + 0% { + opacity: 1; + transform: scale(1); + } + 25% { + transform: scale(1.5); + } + 50% { + opacity: 1; + } + 75% { + opacity: 0.35; + transform: scale(0.5); + } + 100% { + opacity: 1; + transform: scale(1); + } +} \ No newline at end of file diff --git a/helix-dna/src/style.scss b/helix-dna/src/style.scss new file mode 100755 index 0000000..920156c --- /dev/null +++ b/helix-dna/src/style.scss @@ -0,0 +1,109 @@ +html, +body { + height: 100%; +} + +body { + align-items: center; + background: #d65b9e; + background: linear-gradient(45deg, #d65b9e 1%,#f699cb 22%,#ffacd9 51%,#f699cb 83%,#d65b9e 100%); + display: flex; + justify-content: center; +} + +$dot-count: 26; +$dot-size: 10px; +$dot-space: 15px; +$dot-start: (($dot-count / 2 + 1) * ($dot-size + $dot-space)) / 2; + +$animation-time: 2s; +$animation-distance: 25px; + +.loader { + position: relative; + + .dot { + animation-name: movement; + animation-duration: $animation-time; + animation-iteration-count: infinite; + animation-timing-function: ease-in-out; + height: $dot-size; + position: absolute; + top: -#{$dot-size}; + transform: translate3d(0, -#{$animation-distance}, 0) scale(1); + width: $dot-size; + + @for $i from 1 through $dot-count { + $dot-move: ceil($i / 2); + $dot-pos: $dot-start - (($dot-size + $dot-space) * $dot-move); + + $animation-delay: -#{$i * .1}s; + @if $i % 2 == 0 { + $animation-delay: -#{($i * .1) + ($animation-time / 2)}; + } + + &:nth-of-type(#{$i}) { + animation-delay: $animation-delay; + left: $dot-pos; + + &::before { + animation-delay: $animation-delay; + } + } + } + + &::before { + animation-name: size-opacity; + animation-duration: $animation-time; + animation-iteration-count: infinite; + animation-timing-function: ease; + background: white; + border-radius: 50%; + content: ''; + display: block; + height: 100%; + width: 100%; + } + + &:nth-of-type(even)::before { + background-color: #ff47aa; + box-shadow: inset 0 0 4px darken(#ff47aa, 10%); + } + } +} + +@keyframes movement { + 0% { + transform: translate3d(0, -#{$animation-distance}, 0); + z-index: 0; + } + 50% { + transform: translate3d(0, #{$animation-distance}, 0); + z-index: 10; + } + 100% { + transform: translate3d(0, -#{$animation-distance}, 0); + z-index: -5; + } +} + +@keyframes size-opacity { + 0% { + opacity: 1; + transform: scale(1); + } + 25% { + transform: scale(1.5); + } + 50% { + opacity: 1; + } + 75% { + opacity: .35; + transform: scale(.5); + } + 100% { + opacity: 1; + transform: scale(1); + } +} diff --git a/lightsaber/README.md b/lightsaber/README.md new file mode 100755 index 0000000..423b305 --- /dev/null +++ b/lightsaber/README.md @@ -0,0 +1,15 @@ +# ⚔️ Lightsaber Fight Loader + +Уникальный тематический индикатор загрузки, выполненный в стиле сражения на световых мечах. 100% Pure CSS. + +### Особенности + +- **Интерактивный сюжет**: Анимация включает в себя активацию мечей, само «сражение» (столкновение) и появление искр. +- **Particle System**: Эффект искр при столкновении реализован через `@keyframes` и изменение прозрачности отдельных элементов. +- **Star Wars Vibe**: Используются классические цвета (зеленый и красный) с соответствующим свечением (`box-shadow`). + +### Технические детали + +- **Lightsabers**: Рукоятки — это основные блоки, а сами лучи созданы с помощью псевдоэлементов `:before`. +- **Fight Logic**: Анимации `fightleft` и `fightright` синхронизированы так, чтобы мечи пересекались в одной точке в определенный момент времени. +- **Glow Effect**: Динамическое изменение `box-shadow` создает эффект пульсирующего света. diff --git a/lightsaber/src/index.html b/lightsaber/src/index.html new file mode 100755 index 0000000..016b9f3 --- /dev/null +++ b/lightsaber/src/index.html @@ -0,0 +1,28 @@ + + + + + Lightsaber Fight Loader + + + + + + +

Lightsaber Fight Loader

+

A little 100% CSS loader inspired in a Lightsaber fight :)

+
+
+
+
+
+
+
+
+
+ + + + + + diff --git a/lightsaber/src/style.css b/lightsaber/src/style.css new file mode 100755 index 0000000..7a7a2dd --- /dev/null +++ b/lightsaber/src/style.css @@ -0,0 +1,765 @@ +body { + position: relative; + background-color: #eee; + min-height: 380px; +} + +h1 { + text-align: center; + font-family: Helvetica, Arial, sans-serif; + font-weight: 200; + color: #333; + font-size: 26px; + margin: 40px 0 15px; +} + +p { + text-align: center; + font-family: Helvetica, Arial, sans-serif; + font-weight: 200; + color: #666; + font-size: 16px; + margin: 10px 0; + font-style: italic; +} + +p.small { + text-align: center; + color: #999; + font-size: 14px; + margin: 0 0 40px; + font-style: normal; +} + +p a { + text-decoration: none; + font-weight: bold; + color: #666; +} + +p a:hover { + color: #608A00; +} + +#loader { + width: 80px; + height: 40px; + position: absolute; + top: 50%; + left: 50%; + margin: -20px -40px; + z-index: 1000; + +} + +.lightsaber { + position: absolute; + width: 4px; + height: 12px; + background-color: #666; + border-radius: 1px; + bottom: 0; +} + +.lightsaber.ls-left { + left: 0; +} + +.lightsaber.ls-right { + right: 0; +} + +.lightsaber:before { + position: absolute; + content: ' '; + display: block; + width: 2px; + height: 25px; + max-height: 1px; + left: 1px; + top: 1px; + background-color: #fff; + border-radius: 1px; + -webkit-transform: rotateZ(180deg); + transform: rotateZ(180deg); + -webkit-transform-origin: center top; + -ms-transform-origin: center top; + transform-origin: center top; +} + +.lightsaber:after { + position: absolute; + content: ' '; + display: block; + width: 2px; + height: 2px; + left: 1px; + top: 4px; + background-color: #fff; + border-radius: 50%; +} + +.ls-particles { + position: absolute; + left: 42px; + top: 10px; + width: 1px; + height: 5px; + background-color: rgb(51, 51, 51, 0); + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); +} + + +.lightsaber.ls-green:before { + -webkit-animation: showlightgreen 2s ease-in-out infinite 1s; animation: showlightgreen 2s ease-in-out infinite 1s; +} + +.lightsaber.ls-red:before { + -webkit-animation: showlightred 2s ease-in-out infinite 1s; animation: showlightred 2s ease-in-out infinite 1s; +} + + +.lightsaber.ls-left { + -webkit-animation: fightleft 2s ease-in-out infinite 1s; animation: fightleft 2s ease-in-out infinite 1s; +} + +.lightsaber.ls-right { + -webkit-animation: fightright 2s ease-in-out infinite 1s; animation: fightright 2s ease-in-out infinite 1s; +} + +.ls-particles.ls-part-1 { + -webkit-animation: particles1 2s ease-out infinite 1s; animation: particles1 2s ease-out infinite 1s; +} + +.ls-particles.ls-part-2 { + -webkit-animation: particles2 2s ease-out infinite 1s; animation: particles2 2s ease-out infinite 1s; +} + +.ls-particles.ls-part-3 { + -webkit-animation: particles3 2s ease-out infinite 1s; animation: particles3 2s ease-out infinite 1s; +} + +.ls-particles.ls-part-4 { + -webkit-animation: particles4 2s ease-out infinite 1s; animation: particles4 2s ease-out infinite 1s; +} + +.ls-particles.ls-part-5 { + -webkit-animation: particles5 2s ease-out infinite 1s; animation: particles5 2s ease-out infinite 1s; +} + +@-webkit-keyframes showlightgreen { + 0% { + max-height: 0; + box-shadow: 0 0 0 0 #87c054; + } + + 5% { + box-shadow: 0 0 4px 2px #87c054; + } + + 10% { + max-height: 22px; + } + + 80% { + max-height: 22px; + } + + 85% { + box-shadow: 0 0 4px 2px #87c054; + } + + 100% { + max-height: 0; + box-shadow: 0 0 0 0 #87c054; + } +} + +@-webkit-keyframes showlightred { + 0% { + max-height: 0; + box-shadow: 0 0 0 0 #f06363; + } + + 20% { + box-shadow: 0 0 4px 2px #f06363; + } + + 25% { + max-height: 22px; + } + + 80% { + max-height: 22px; + } + + 85% { + box-shadow: 0 0 4px 2px #f06363; + } + + 100% { + max-height: 0; + box-shadow: 0 0 0 0 #f06363; + } +} + +@-webkit-keyframes fightleft { + 0% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + left: 0; + bottom: 0; + } + + 30% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + bottom: 0; + } + + 40% { + -webkit-transform: rotateZ(45deg); + transform: rotateZ(45deg); + left: 0; + bottom: 2px; + } + + 45%{ + -webkit-transform: rotateZ(65deg); + transform: rotateZ(65deg); + left: 0; + } + + 65%{ + -webkit-transform: rotateZ(410deg); + transform: rotateZ(410deg); + left: 30px; + bottom: 10px; + } + + 95% { + -webkit-transform: rotateZ(410deg); + transform: rotateZ(410deg); + left: 0; + bottom: 0; + } + + 100% { + -webkit-transform: rotateZ(360deg); + transform: rotateZ(360deg); + left: 0; + bottom: 0; + } +} + +@-webkit-keyframes fightright { + 0% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + right: 0; + bottom: 0; + } + + 30% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + bottom: 0; + } + + 45% { + -webkit-transform: rotateZ(-45deg); + transform: rotateZ(-45deg); + right: 0; + bottom: 2px; + } + + 50%{ + -webkit-transform: rotateZ(-65deg); + transform: rotateZ(-65deg); + right: 0; + } + + 68%{ + -webkit-transform: rotateZ(-410deg); + transform: rotateZ(-410deg); + right: 27px; + bottom: 13px; + } + + 95% { + -webkit-transform: rotateZ(-410deg); + transform: rotateZ(-410deg); + right: 0; + bottom: 0; + } + + 100% { + -webkit-transform: rotateZ(-360deg); + transform: rotateZ(-360deg); + right: 0; + bottom: 0; + } +} + +@-webkit-keyframes particles1 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(35deg) translateY(0px); + transform: rotateZ(35deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(35deg) translateY(0px); + transform: rotateZ(35deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(35deg) translateY(0px); + transform: rotateZ(35deg) translateY(0px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(35deg) translateY(-30px); + transform: rotateZ(35deg) translateY(-30px); + } +} + +@-webkit-keyframes particles2 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(0px); + transform: rotateZ(-65deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(0px); + transform: rotateZ(-65deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(-65deg) translateY(0px); + transform: rotateZ(-65deg) translateY(0px); + } + + 95% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(-40px); + transform: rotateZ(-65deg) translateY(-40px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(-40px); + transform: rotateZ(-65deg) translateY(-40px); + } +} + +@-webkit-keyframes particles3 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(0px); + transform: rotateZ(-75deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(0px); + transform: rotateZ(-75deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(-75deg) translateY(0px); + transform: rotateZ(-75deg) translateY(0px); + } + + 97% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(-35px); + transform: rotateZ(-75deg) translateY(-35px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(-35px); + transform: rotateZ(-75deg) translateY(-35px); + } +} + +@-webkit-keyframes particles4 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(0px); + transform: rotateZ(-25deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(0px); + transform: rotateZ(-25deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(-25deg) translateY(0px); + transform: rotateZ(-25deg) translateY(0px); + } + + 97% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(-30px); + transform: rotateZ(-25deg) translateY(-30px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(-30px); + transform: rotateZ(-25deg) translateY(-30px); + } +} + +@-webkit-keyframes particles5 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(0px); + transform: rotateZ(65deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(0px); + transform: rotateZ(65deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(65deg) translateY(0px); + transform: rotateZ(65deg) translateY(0px); + } + + 97% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(-35px); + transform: rotateZ(65deg) translateY(-35px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(-35px); + transform: rotateZ(65deg) translateY(-35px); + } +} + +@keyframes showlightgreen { + 0% { + max-height: 0; + box-shadow: 0 0 0 0 #87c054; + } + + 5% { + box-shadow: 0 0 4px 2px #87c054; + } + + 10% { + max-height: 22px; + } + + 80% { + max-height: 22px; + } + + 85% { + box-shadow: 0 0 4px 2px #87c054; + } + + 100% { + max-height: 0; + box-shadow: 0 0 0 0 #87c054; + } +} + +@keyframes showlightred { + 0% { + max-height: 0; + box-shadow: 0 0 0 0 #f06363; + } + + 20% { + box-shadow: 0 0 4px 2px #f06363; + } + + 25% { + max-height: 22px; + } + + 80% { + max-height: 22px; + } + + 85% { + box-shadow: 0 0 4px 2px #f06363; + } + + 100% { + max-height: 0; + box-shadow: 0 0 0 0 #f06363; + } +} + +@keyframes fightleft { + 0% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + left: 0; + bottom: 0; + } + + 30% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + bottom: 0; + } + + 40% { + -webkit-transform: rotateZ(45deg); + transform: rotateZ(45deg); + left: 0; + bottom: 2px; + } + + 45%{ + -webkit-transform: rotateZ(65deg); + transform: rotateZ(65deg); + left: 0; + } + + 65%{ + -webkit-transform: rotateZ(410deg); + transform: rotateZ(410deg); + left: 30px; + bottom: 10px; + } + + 95% { + -webkit-transform: rotateZ(410deg); + transform: rotateZ(410deg); + left: 0; + bottom: 0; + } + + 100% { + -webkit-transform: rotateZ(360deg); + transform: rotateZ(360deg); + left: 0; + bottom: 0; + } +} + +@keyframes fightright { + 0% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + right: 0; + bottom: 0; + } + + 30% { + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + bottom: 0; + } + + 45% { + -webkit-transform: rotateZ(-45deg); + transform: rotateZ(-45deg); + right: 0; + bottom: 2px; + } + + 50%{ + -webkit-transform: rotateZ(-65deg); + transform: rotateZ(-65deg); + right: 0; + } + + 68%{ + -webkit-transform: rotateZ(-410deg); + transform: rotateZ(-410deg); + right: 27px; + bottom: 13px; + } + + 95% { + -webkit-transform: rotateZ(-410deg); + transform: rotateZ(-410deg); + right: 0; + bottom: 0; + } + + 100% { + -webkit-transform: rotateZ(-360deg); + transform: rotateZ(-360deg); + right: 0; + bottom: 0; + } +} + +@keyframes particles1 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(35deg) translateY(0px); + transform: rotateZ(35deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(35deg) translateY(0px); + transform: rotateZ(35deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(35deg) translateY(0px); + transform: rotateZ(35deg) translateY(0px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(35deg) translateY(-30px); + transform: rotateZ(35deg) translateY(-30px); + } +} + +@keyframes particles2 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(0px); + transform: rotateZ(-65deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(0px); + transform: rotateZ(-65deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(-65deg) translateY(0px); + transform: rotateZ(-65deg) translateY(0px); + } + + 95% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(-40px); + transform: rotateZ(-65deg) translateY(-40px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-65deg) translateY(-40px); + transform: rotateZ(-65deg) translateY(-40px); + } +} + +@keyframes particles3 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(0px); + transform: rotateZ(-75deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(0px); + transform: rotateZ(-75deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(-75deg) translateY(0px); + transform: rotateZ(-75deg) translateY(0px); + } + + 97% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(-35px); + transform: rotateZ(-75deg) translateY(-35px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-75deg) translateY(-35px); + transform: rotateZ(-75deg) translateY(-35px); + } +} + +@keyframes particles4 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(0px); + transform: rotateZ(-25deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(0px); + transform: rotateZ(-25deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(-25deg) translateY(0px); + transform: rotateZ(-25deg) translateY(0px); + } + + 97% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(-30px); + transform: rotateZ(-25deg) translateY(-30px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(-25deg) translateY(-30px); + transform: rotateZ(-25deg) translateY(-30px); + } +} + +@keyframes particles5 { + 0% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(0px); + transform: rotateZ(65deg) translateY(0px); + } + + 63% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(0px); + transform: rotateZ(65deg) translateY(0px); + } + + 64% { + background-color: rgba(51, 51, 51,1); + -webkit-transform: rotateZ(65deg) translateY(0px); + transform: rotateZ(65deg) translateY(0px); + } + + 97% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(-35px); + transform: rotateZ(65deg) translateY(-35px); + } + + 100% { + background-color: rgba(51, 51, 51,0); + -webkit-transform: rotateZ(65deg) translateY(-35px); + transform: rotateZ(65deg) translateY(-35px); + } +} \ No newline at end of file diff --git a/pancake/README.md b/pancake/README.md new file mode 100755 index 0000000..65bc638 --- /dev/null +++ b/pancake/README.md @@ -0,0 +1,15 @@ +# 🥞 Making Pancake Loader + +Невероятно детальный и "вкусный" индикатор загрузки, имитирующий приготовление блинчика на сковороде. Полностью реализован на чистом CSS. + +### Особенности + +- **Комплексная физика**: Анимация включает в себя наклон сковороды (`flip`), подбрасывание блинчика (`jump`) и его переворот в воздухе (`fly`). +- **Эффект пара**: Реализован через систему "пузырьков" (`.bubble`) с разными задержками и кривыми Безье для естественности. +- **Адаптивность (vh/vw)**: Размеры элементов привязаны к высоте экрана, что позволяет лоадеру корректно масштабироваться. + +### Технические детали + +- **Keyframes Magic**: Используется 5 различных сценариев анимации, работающих синхронно. +- **3D Transform**: Переворот блинчика имитируется через `rotateX` и `rotateY`. +- **Typography**: Интегрирован шрифт "Amatic SC" через Google Fonts для создания уютной атмосферы. diff --git a/pancake/src/index.html b/pancake/src/index.html new file mode 100755 index 0000000..7eb6f26 --- /dev/null +++ b/pancake/src/index.html @@ -0,0 +1,31 @@ + + + + + CodePen - 'Making pancake' loader + + + + + +

Cooking in progress..

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + diff --git a/pancake/src/style.css b/pancake/src/style.css new file mode 100755 index 0000000..17c611d --- /dev/null +++ b/pancake/src/style.css @@ -0,0 +1,236 @@ +@import url("https://fonts.googleapis.com/css?family=Amatic+SC"); +body { + background-color: #ffde6b; + height: 100vh; + width: 100vw; + overflow: hidden; +} + +h1 { + position: relative; + margin: 0 auto; + top: 25vh; + width: 100vw; + text-align: center; + font-family: "Amatic SC"; + font-size: 6vh; + color: #333; + opacity: 0.75; + animation: pulse 2.5s linear infinite; +} + +#cooking { + position: relative; + margin: 0 auto; + top: 0; + width: 75vh; + height: 75vh; + overflow: hidden; +} +#cooking .bubble { + position: absolute; + border-radius: 100%; + box-shadow: 0 0 0.25vh #4d4d4d; + opacity: 0; +} +#cooking .bubble:nth-child(1) { + margin-top: 2.5vh; + left: 58%; + width: 2.5vh; + height: 2.5vh; + background-color: #454545; + animation: bubble 2s cubic-bezier(0.53, 0.16, 0.39, 0.96) infinite; +} +#cooking .bubble:nth-child(2) { + margin-top: 3vh; + left: 52%; + width: 2vh; + height: 2vh; + background-color: #3d3d3d; + animation: bubble 2s ease-in-out 0.35s infinite; +} +#cooking .bubble:nth-child(3) { + margin-top: 1.8vh; + left: 50%; + width: 1.5vh; + height: 1.5vh; + background-color: #333; + animation: bubble 1.5s cubic-bezier(0.53, 0.16, 0.39, 0.96) 0.55s infinite; +} +#cooking .bubble:nth-child(4) { + margin-top: 2.7vh; + left: 56%; + width: 1.2vh; + height: 1.2vh; + background-color: #2b2b2b; + animation: bubble 1.8s cubic-bezier(0.53, 0.16, 0.39, 0.96) 0.9s infinite; +} +#cooking .bubble:nth-child(5) { + margin-top: 2.7vh; + left: 63%; + width: 1.1vh; + height: 1.1vh; + background-color: #242424; + animation: bubble 1.6s ease-in-out 1s infinite; +} +#cooking #area { + position: absolute; + bottom: 0; + right: 0; + width: 50%; + height: 50%; + background-color: transparent; + transform-origin: 15% 60%; + animation: flip 2.1s ease-in-out infinite; +} +#cooking #area #sides { + position: absolute; + width: 100%; + height: 100%; + transform-origin: 15% 60%; + animation: switchSide 2.1s ease-in-out infinite; +} +#cooking #area #sides #handle { + position: absolute; + bottom: 18%; + right: 80%; + width: 35%; + height: 20%; + background-color: transparent; + border-top: 1vh solid #333; + border-left: 1vh solid transparent; + border-radius: 100%; + transform: rotate(20deg) rotateX(0deg) scale(1.3, 0.9); +} +#cooking #area #sides #pan { + position: absolute; + bottom: 20%; + right: 30%; + width: 50%; + height: 8%; + background-color: #333; + border-radius: 0 0 1.4em 1.4em; + transform-origin: -15% 0; +} +#cooking #area #pancake { + position: absolute; + top: 24%; + width: 100%; + height: 100%; + transform: rotateX(85deg); + animation: jump 2.1s ease-in-out infinite; +} +#cooking #area #pancake #pastry { + position: absolute; + bottom: 26%; + right: 37%; + width: 40%; + height: 45%; + background-color: #333; + box-shadow: 0 0 3px 0 #333; + border-radius: 100%; + transform-origin: -20% 0; + animation: fly 2.1s ease-in-out infinite; +} + +@keyframes jump { + 0% { + top: 24%; + transform: rotateX(85deg); + } + 25% { + top: 10%; + transform: rotateX(0deg); + } + 50% { + top: 30%; + transform: rotateX(85deg); + } + 75% { + transform: rotateX(0deg); + } + 100% { + transform: rotateX(85deg); + } +} +@keyframes flip { + 0% { + transform: rotate(0deg); + } + 5% { + transform: rotate(-27deg); + } + 30%, 50% { + transform: rotate(0deg); + } + 55% { + transform: rotate(27deg); + } + 83.3% { + transform: rotate(0deg); + } + 100% { + transform: rotate(0deg); + } +} +@keyframes switchSide { + 0% { + transform: rotateY(0deg); + } + 50% { + transform: rotateY(180deg); + } + 100% { + transform: rotateY(0deg); + } +} +@keyframes fly { + 0% { + bottom: 26%; + transform: rotate(0deg); + } + 10% { + bottom: 40%; + } + 50% { + bottom: 26%; + transform: rotate(-190deg); + } + 80% { + bottom: 40%; + } + 100% { + bottom: 26%; + transform: rotate(0deg); + } +} +@keyframes bubble { + 0% { + transform: scale(0.15, 0.15); + top: 80%; + opacity: 0; + } + 50% { + transform: scale(1.1, 1.1); + opacity: 1; + } + 100% { + transform: scale(0.33, 0.33); + top: 60%; + opacity: 0; + } +} +@keyframes pulse { + 0% { + transform: scale(1, 1); + opacity: 0.25; + } + 50% { + transform: scale(1.2, 1); + opacity: 1; + } + 100% { + transform: scale(1, 1); + opacity: 0.25; + } +} \ No newline at end of file diff --git a/pancake/src/style.scss b/pancake/src/style.scss new file mode 100755 index 0000000..a150671 --- /dev/null +++ b/pancake/src/style.scss @@ -0,0 +1,250 @@ +@import url('https://fonts.googleapis.com/css?family=Amatic+SC'); + +$anim_time: 2.1; // main pan/pancake animation (in seconds) +$flatten_deg: 85; // how round will the pancake be at the top/peak (in deg), affecting general animation though so not really adjustable +$angle: 27; // max pan's angle while flipping (in deg) +$peak: 40%; // pancake's highest level, obviously ;) +$color_back: #ffde6b; // background +$color: #333; // the rest + +body { + background-color: $color_back; + height: 100vh; + width: 100vw; + overflow: hidden; +} + +h1 { + position: relative; + margin: 0 auto; + top: 25vh; + width: 100vw; + text-align: center; + font-family: 'Amatic SC'; + font-size: 6vh; + color: $color; + opacity: .75; + animation: pulse 2.5s linear infinite; +} + +#cooking { + position: relative; + margin: 0 auto; + top: 0; + width: 75vh; + height: 75vh; + overflow: hidden; + .bubble { + position: absolute; + border-radius: 100%; + box-shadow: 0 0 .25vh lighten($color, 10%); + opacity: 0; + } + .bubble:nth-child(1) { + margin-top: 2.5vh; + left: 58%; + width: 2.5vh; + height: 2.5vh; + background-color: lighten($color, 7%); + animation: bubble 2s cubic-bezier(.53, .16, .39, .96) infinite; + } + .bubble:nth-child(2) { + margin-top: 3vh; + left: 52%; + width: 2vh; + height: 2vh; + background-color: lighten($color, 4%); + animation: bubble 2s ease-in-out .35s infinite; + } + .bubble:nth-child(3) { + margin-top: 1.8vh; + left: 50%; + width: 1.5vh; + height: 1.5vh; + background-color: $color; + animation: bubble 1.5s cubic-bezier(.53, .16, .39, .96) .55s infinite; + } + .bubble:nth-child(4) { + margin-top: 2.7vh; + left: 56%; + width: 1.2vh; + height: 1.2vh; + background-color: darken($color, 3%); + animation: bubble 1.8s cubic-bezier(.53, .16, .39, .96) .9s infinite; + } + .bubble:nth-child(5) { + margin-top: 2.7vh; + left: 63%; + width: 1.1vh; + height: 1.1vh; + background-color: darken($color, 6%); + animation: bubble 1.6s ease-in-out 1s infinite; + } + #area { + position: absolute; + bottom: 0; + right: 0; + width: 50%; + height: 50%; + background-color: transparent; + transform-origin: 15% 60%; + animation: flip #{$anim_time}s ease-in-out infinite; + #sides { + position: absolute; + width: 100%; + height: 100%; + transform-origin: 15% 60%; + animation: switchSide #{$anim_time}s ease-in-out infinite; + #handle { + position: absolute; + bottom: 18%; + right: 80%; + width: 35%; + height: 20%; + background-color: transparent; + border-top: 1vh solid $color; + border-left: 1vh solid transparent; + border-radius: 100%; + transform: rotate(20deg) rotateX(0deg) scale(1.3, .9); + } + #pan { + position: absolute; + bottom: 20%; + right: 30%; + width: 50%; + height: 8%; + background-color: $color; + border-radius: 0 0 1.4em 1.4em; + transform-origin: -15% 0; + } + } + #pancake { + position: absolute; + top: 24%; + width: 100%; + height: 100%; + transform: rotateX(85deg); + animation: jump #{$anim_time}s ease-in-out infinite; + #pastry { + position: absolute; + bottom: 26%; + right: 37%; + width: 40%; + height: 45%; + background-color: $color; + box-shadow: 0 0 3px 0 $color; + border-radius: 100%; + transform-origin: -20% 0; + animation: fly #{$anim_time}s ease-in-out infinite; + } + } + } +} + +@keyframes jump { + 0% { + top: 24%; + transform: rotateX(#{$flatten_deg}deg); + } + 25% { + top: 10%; + transform: rotateX(0deg); + } + 50% { + top: 30%; + transform: rotateX(#{$flatten_deg}deg); + } + 75% { + transform: rotateX(0deg); + } + 100% { + transform: rotateX(#{$flatten_deg}deg); + } +} + +@keyframes flip { + 0% { + transform: rotate(0deg); + } + 5% { + transform: rotate(-#{$angle}deg); + } + 30%, + 50% { + transform: rotate(0deg); + } + 55% { + transform: rotate(#{$angle}deg); + } + 83.3% { + transform: rotate(0deg); + } + 100% { + transform: rotate(0deg); + } +} + +@keyframes switchSide { + 0% { + transform: rotateY(0deg); + } + 50% { + transform: rotateY(180deg); + } + 100% { + transform: rotateY(0deg); + } +} + +@keyframes fly { + 0% { + bottom: 26%; + transform: rotate(0deg); + } + 10% { + bottom: $peak; + } + 50% { + bottom: 26%; + transform: rotate(-190deg); + } + 80% { + bottom: $peak; + } + 100% { + bottom: 26%; + transform: rotate(0deg); + } +} + +@keyframes bubble { + 0% { + transform: scale(.15, .15); + top: 80%; + opacity: 0; + } + 50% { + transform: scale(1.1, 1.1); + opacity: 1; + } + 100% { + transform: scale(.33, .33); + top: 60%; + opacity: 0; + } +} + +@keyframes pulse { + 0% { + transform: scale(1, 1); + opacity: .25; + } + 50% { + transform: scale(1.2, 1); + opacity: 1; + } + 100% { + transform: scale(1, 1); + opacity: .25; + } +} \ No newline at end of file diff --git a/pong-game/README.md b/pong-game/README.md new file mode 100755 index 0000000..acfff36 --- /dev/null +++ b/pong-game/README.md @@ -0,0 +1,15 @@ +# 🎾 Pong Pure Loader + +Минималистичный индикатор загрузки, воссоздающий геймплей легендарной игры Pong. Реализовано полностью на чистом CSS. + +### Особенности + +- **Retro Gaming Vibe**: Классическая механика взаимодействия двух ракеток и мяча. +- **Perfect Timing**: Движения обеих ракеток (`player_one`, `player_two`) идеально синхронизированы с траекторией полета мяча. +- **Extreme Lightness**: Код занимает всего несколько десятков строк и не требует никаких внешних ресурсов или JS. + +### Технические детали + +- **Ball Animation**: Мяч движется по сложной траектории с использованием `linear` тайминга для имитации постоянной скорости. +- **Paddles**: Ракетки перемещаются только по оси Y (`translateY`), имитируя логику игры. +- **Layout**: Использование `position: absolute` и `transform: translate(-50%, -50%)` для идеального центрирования на экране. diff --git a/pong-game/src/index.html b/pong-game/src/index.html new file mode 100755 index 0000000..2dc79cf --- /dev/null +++ b/pong-game/src/index.html @@ -0,0 +1,20 @@ + + + + + Pong Pure CSS Loader + + + + + + +
+
+
+
+
+ + + + diff --git a/pong-game/src/style.css b/pong-game/src/style.css new file mode 100755 index 0000000..23e3477 --- /dev/null +++ b/pong-game/src/style.css @@ -0,0 +1,80 @@ +body { + background: #56c8d8; +} + +.content { + position: absolute; + top: 45%; + left: 57.5%; + transform: translate(-50%, -50%); + display: block; +} + +.paddle, .player_two, .player_one { + height: 40px; + width: 3px; + background-color: white; + position: relative; +} + +.player_one { + left: -180px; + animation: movePaddleOne 4s infinite; +} + +.player_two { + left: 20px; + animation: movePaddleTwo 4s infinite; +} + +.ball { + position: relative; + height: 5px; + width: 5px; + border-radius: 50%; + background-color: white; + animation: moveBall 4s infinite linear; +} + +@keyframes movePaddleOne { + 0%, 100% { + transform: translate(0px, 100px); + } + 25% { + transform: translate(0px, 0px); + } + 50% { + transform: translate(0px, 0px); + } + 75% { + transform: translate(0px, 100px); + } +} +@keyframes movePaddleTwo { + 0%, 100% { + transform: translate(0px, -50px); + } + 25% { + transform: translate(0px, 10px); + } + 50% { + transform: translate(0px, 0px); + } + 75% { + transform: translate(0px, 50px); + } +} +@keyframes moveBall { + 0%, 100% { + transform: translate(-180px, 30px); + } + 25% { + transform: translate(18px, -25px); + } + 50% { + transform: translate(-180px, -55px); + } + 75% { + transform: translate(18px, 15px); + } +} \ No newline at end of file diff --git a/pong-game/src/style.scss b/pong-game/src/style.scss new file mode 100755 index 0000000..b676074 --- /dev/null +++ b/pong-game/src/style.scss @@ -0,0 +1,84 @@ +body { + background: #56c8d8; +} + +.content { + position: absolute; + top: 45%; + left: 57.5%; + transform: translate(-50%, -50%); + display: block; +} + +.paddle{ + height:40px; + width:3px; + background-color:white; + position:relative; +} + +.player_one{ + @extend .paddle; + left:-180px; + animation: movePaddleOne 4s infinite; +} + +.player_two{ + @extend .paddle; + left:20px; + animation: movePaddleTwo 4s infinite; +} + +.ball{ + position:relative; + height:5px; + width:5px; + border-radius:50%; + background-color:white; + animation: moveBall 4s infinite linear; +} + +@keyframes movePaddleOne{ + 0%, 100%{ + transform:translate(0px, 100px); + } + 25%{ + transform:translate(0px, 0px); + } + 50%{ + transform:translate(0px, 0px); + } + 75%{ + transform:translate(0px, 100px); + } +} + +@keyframes movePaddleTwo{ + 0%, 100%{ + transform:translate(0px,-50px); + } + 25%{ + transform:translate(0px,10px); + } + 50%{ + transform:translate(0px,0px); + } + 75%{ + transform:translate(0px,50px); + } +} + +@keyframes moveBall{ + 0%, 100%{ + transform:translate(-180px, 30px); + } + 25%{ + transform:translate(18px, -25px); + } + 50%{ + transform:translate(-180px, -55px); + } + 75%{ + transform:translate(18px, 15px); + } +} \ No newline at end of file diff --git a/rolling-text/README.md b/rolling-text/README.md new file mode 100755 index 0000000..c8af99a --- /dev/null +++ b/rolling-text/README.md @@ -0,0 +1,14 @@ +# 🎰 Rolling Letters Loader + +Креативный текстовый индикатор загрузки с эффектом «барабана». Буквы слова **LOADING** поочередно вылетают и прокручиваются по вертикали, создавая эффект динамичного каскада. + +### Особенности + +- **Pure CSS**: Вся магия анимации реализована через `@keyframes` и трансформации. +- **Zero JS**: Решение работает без использования JavaScript и сторонних библиотек. +- **Staggered Animation**: Эффект «волны» достигается за счет последовательной задержки (`animation-delay`) для каждого символа. + +### Технологии + +- **HTML5**: Семантическая разметка с использованием `` для каждой буквы. +- **CSS3**: Использование `rotateX` для 3D-вращения и `top` для перемещения по вертикали. diff --git a/rolling-text/src/index.html b/rolling-text/src/index.html new file mode 100755 index 0000000..c7bbb49 --- /dev/null +++ b/rolling-text/src/index.html @@ -0,0 +1,22 @@ + + + + + CSS Rolling Letters Loader + + + + +

+ l + o + a + d + i + n + g +

+ + + + diff --git a/rolling-text/src/style.css b/rolling-text/src/style.css new file mode 100755 index 0000000..26f7837 --- /dev/null +++ b/rolling-text/src/style.css @@ -0,0 +1,86 @@ +html, body { + height: 100%; + width: 100%; + margin: 0; + padding: 0; + font-size: 100%; + background: #191a1a; + text-align: center; +} + +h1 { + margin: 0; + padding: 0; + font-family: ‘Arial Narrow’, sans-serif; + font-weight: 100; + font-size: 1.1em; + color: #a3e1f0; +} + +span { + position: relative; + top: 0.63em; + display: inline-block; + text-transform: uppercase; + opacity: 0; + transform: rotateX(-90deg); +} + +.let1 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.2s; +} + +.let2 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.3s; +} + +.let3 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.4s; +} + +.let4 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.5s; + +} + +.let5 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.6s; +} + +.let6 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.7s; +} + +.let7 { + animation: drop 1.2s ease-in-out infinite; + animation-delay: 1.8s; +} + +@keyframes drop { + 10% { + opacity: 0.5; + } + 20% { + opacity: 1; + top: 3.78em; + transform: rotateX(-360deg); + } + 80% { + opacity: 1; + top: 3.78em; + transform: rotateX(-360deg); + } + 90% { + opacity: 0.5; + } + 100% { + opacity: 0; + top: 6.94em + } +} \ No newline at end of file