ForumD.ru - Дизайн, графика, скрипты, техническая поддержка для форумов и сайтов

Объявление

GEMcross

Кроссовер, ориентированный на активную игру и уютный флуд.
Собираем у себя драгоценных игроков уже почти три года.

Посетить

💰 Теперь у нас можно приобрести "Мгновенные уведомления от Алекса"

Скрипт оповещает пользователей о событиях на форуме в реальном времени, придавая динамики общению.
Автор: Alex_63 | Платформа: MyBB.ru.

У нас: структурированная документация, возможность платить иностранными картами, перевыпустить подписку или купить бессрочно.

Купить скрипт

🔥 Новинка в портфолио: ДИЗАЙН ФОРУМА В СТИЛЕ ФЭНТЭЗИ С ПРОЗРАЧНОСТЬЮ

Платформа: MyBB.ru (RusFF)
Стоимость: 8000 рублей;
Авторы: Moju & Gerda

Посмотреть

🌟 ОПЛАТА ЗАКАЗА НАГРАДНЫМИ БАЛЛАМИ И СКИДКИ

Заказы можно оплачивать наградными баллами (НБ). Полностью или частично.
Бартер за НБ осуществляется на условиях платного заказа, в качестве оплаты - НБ.
А если у вас есть любой платный заказ, вы можете обменять НБ на скидочные купоны.

узнать подробности

📣 Наш проект: Ролевой поисковик

Поиск роли на текстовых ролевых
Проект от специалистов FD

Спойлеры и обсуждение

❤️ Поддержать проект

Если у вас есть желание помочь нам сделать наш проект лучше:
Реклама на сайтеПредложения
Стать модераторомОтзывы

Подробнее

SPECIAL OFFER: We distribute designs for free

Finalizing the layout for your project;
Developing a style code;
Mobile version included if you wish.

Details

Support the project

If you want to help us:
Become a moderator
SuggestionsReviews

Details
❗ ❗ ❗ Technical work is underway. We'll fix it soon. :) If you're english-speaker and want to use our forum, switch to the russian language. This is temporary, until the works with multi-language option will be done. Sorry for the inconvenience.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Эксперименты Will O The Wisp

Сообщений 171 страница 180 из 187

171

стикер-анимация

Код:
[html]
<style>
.anim750{
  transition: all 750ms ease-in-out;
}

#Awesome{
	position: relative;
	width: 180px;
	height: 180px;
	margin: 0 auto;
  
  backface-visibility: hidden;
}

#Awesome .sticky{
	transform: rotate(45deg);
}

#Awesome:hover .sticky{
	transform: rotate(10deg);
}

#Awesome .sticky{
	position: absolute;
	top: 0;
	left: 0;
	width:180px;
	height: 180px;
}

#Awesome .reveal .circle{
	box-shadow: 0 1px 0px rgba(0,0,0,.15);
  
  font-family: 'helvetica neue', arial;
  font-weight: 200;
  line-height: 140px;
  text-align: center;
  
  cursor: pointer;
}

#Awesome .reveal .circle{
	background: #fafafa;
}

#Awesome .circle_wrapper{
	position: absolute;
	width: 180px;
	height: 180px;
	left: 0px;
	top: 0px;
	overflow: hidden;
}

#Awesome .circle{
	position: absolute;
	width: 140px;
	height:  140px;
	margin: 20px;
	
	border-radius: 999px;
}

#Awesome .back{
	height: 10px;
	top: 30px;
}

#Awesome:hover .back{
	height: 90px;
	top: 110px;
}

#Awesome .back .circle{
	margin-top: -130px;
	background-color: #fbec3f;

	background-image: -webkit-linear-gradient(bottom, rgba(251,236,63,.0), rgba(255,255,255,.8));
}

#Awesome:hover .back .circle{
	margin-top: -50px;
}

#Awesome .front{
	height: 150px;
	bottom: 0;
	top: auto;
	
	-webkit-box-shadow: 0 -140px 20px -140px rgba(0,0,0,.3);
}

#Awesome:hover .front{
	height: 70px;
	
	-webkit-box-shadow: 0 -60px 10px -60px rgba(0,0,0,.1);
}

#Awesome .front .circle{
	margin-top: -10px;
	background: #fbec3f;

	background-image: -webkit-linear-gradient(bottom, rgba(251,236,63,.0) 75%, #f7bb37 95%);
  background-image: -moz-linear-gradient(bottom, rgba(251,236,63,.0) 75%, #f7bb37 95%);
  background-image: linear-gradient(bottom, rgba(251,236,63,.0) 75%, #f7bb37 95%);
}

#Awesome h4{
  font-family: 'helvetica neue', arial;
  font-weight: 200;
  text-align: center;
	position: absolute;
	width: 180px;
	height: 140px;
  line-height: 140px;
	
	transition: opacity 50ms linear 400ms;
}

#Awesome:hover h4{
	opacity: 0;
	
	transition: opacity 50ms linear 300ms;
}

#Awesome:hover .front .circle{
	margin-top: -90px;
	background-color: #e2d439;
	background-position: 0 100px;
}
</style>
<div id="Awesome" class="anim750">
	
  <div class="reveal circle_wrapper">
    <div class="circle">У того есть паренек</div>
	</div>
            
	<div class="sticky anim750">
    <div class="front circle_wrapper anim750">
    	<div class="circle anim750"></div>
	  </div>
	</div>
	
  <h4>Кто откроет уголок</h4>
            
  <div class="sticky anim750">
    <div class="back circle_wrapper anim750">
    	<div class="circle anim750"></div>
    </div>
	</div>
            
</div>

[/html]

+2

172

игра-кликер
https://codepen.io/grantjenkins/pen/wvErxmz

Код:
[html]
<style>

/* global css variables */
:root {
  --how-color: rgba(249, 133, 70, 0.7);
  --scores-color: rgba(46, 191, 158, 0.7);
  --game-color: rgba(170, 145, 224, 0.7);
  --play-color: rgba(30, 152, 166, 0.8);
  --special-color: rgba(173, 168, 28, 0.7);
}

#box34{
  text-align: center;
  margin:0;
  padding:0;
  font-family: 'Handlee', cursive;
  font-size:18px;
  color: rgba(255, 255, 255, 0.75);
  background: radial-gradient(#f09e7287 15%, transparent 16%) 0 0, radial-gradient(#f09e7287 15%, transparent 16%) 8px 8px, radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px, radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
  background-size:16px 16px;
  background-color:#615d5d;
  background-attachment: fixed;
  min-height: 500px;
}

/* top navigation */
#header {
  font-size: 45px;
}
header nav {
  position: fixed;
  top: 0px;
  height:auto;
  padding:0px;
  width: 100%;
  transition: transform 0.6s;
  z-index:20;
}
header nav.begone {
  transform: translate3d(0, -100%, 0);
}
nav button{
  position:absolute;
  width:100%;
  left:0;
  background-color: rgb(51, 50, 51);
  color: rgb(255, 255, 255);
  padding: 10px;
  border: none;
  font-size: 17px;
  transition: background-color 0.3s, opacity 0.3s linear;
  outline: none;
  height:40px;
}
#homeButton {
  background-color: rgba(222, 85, 88, 0.7);
  left:0;
  width:50px;
}
#howButton {
  background-color: var(--how-color);
  left:50px;
  width: calc((100% - 50px) / 3);
}
#scoresButton {
  background-color: var(--scores-color);
  left: calc(((100% - 50px) / 3) + 50px);
  width: calc((100% - 50px) / 3);
}
#gameButton {
  background-color: var(--game-color);
  left: calc(((100% - 50px) / 3 * 2) + 50px);
  width: calc((100% - 50px) / 3);
}
button:hover {
  opacity: 0.8;
  cursor: pointer;
}
button.active {
  background-color: rgba(0, 0, 0, 0.2) !important;
}
button {
  font-family: 'Handlee', cursive;
}

/* handles the page transitions */
.showPage{
  -webkit-animation: showPage 2s ease forwards;
  -moz-animation: showPage 2s ease forwards;
  -o-animation: showPage 2s ease forwards;
  animation: showPage 2s ease forwards;
}

/* style of main content */
#content {
  margin-top:40px;
  padding: 10px;
}
#content h1 {
  margin-top:30px;
  font-size:65px;
  font-family: 'Indie Flower', cursive;
  margin-bottom:0px;
  color: rgba(255, 255, 255, 0.25);
}
#content #how article {
  margin-top: 60px;
}

/* styling of the wolves */
.wolves div {
  position: absolute;
  width:100px;
  height:90px;
}
.wolves .top-left {
  top: 60px;
  left: 20px;
  -webkit-animation: wolf-rotate 4s linear infinite;
  -moz-animation: wolf-rotate 4s linear infinite;
  -o-animation: wolf-rotate 4s linear infinite;
  animation: wolf-rotate 4s linear infinite;
}
.wolves .top-right {
  top: 60px;
  left: calc(100% - 120px);
  -webkit-animation: wolf-rotate 4s linear -2s infinite;
  -moz-animation: wolf-rotate 4s linear -2s infinite;
  -o-animation: wolf-rotate 4s linear -2s infinite;
  animation: wolf-rotate 4s linear -2s infinite;
}
.wolf div {
  position: absolute;
}
.wolf .wolf-head {
  width: 0;
  height: 0;
  top: 0px;
  left: 0px;
  border-style: solid;
  border-width: 90px 50px 0 50px;
  border-color: #888 transparent transparent transparent;
  border-radius:100%;
  -webkit-animation: wolf-head-change 4s linear infinite;
  -moz-animation: wolf-head-change 4s linear infinite;
  -o-animation: wolf-head-change 4s linear infinite;
  animation: wolf-head-change 4s linear infinite;
}
.wolf .wolf-ear-left {
  width: 0;
  height: 0;
  top: -20px;
  left: 10px;
  border-style: solid;
  border-width: 0 15px 40px 15px;
  border-color: transparent transparent #888 transparent;
  transform: rotate(-20deg);
}
.wolf .wolf-ear-right {
  width: 0;
  height: 0;
  top: -20px;
  left: 60px;
  border-style: solid;
  border-width: 0 15px 40px 15px;
  border-color: transparent transparent #888 transparent;
  transform: rotate(20deg);
}
.wolf .wolf-eye-left {
  width: 0;
  height: 0;
  top: 25px;
  left: 60px;
  border-style: solid;
  border-width: 18px 14px 0 0;
  border-color: #444 transparent transparent transparent;
  transform: skew(-15deg);
}
.wolf .wolf-eye-right {
  width: 0;
  height: 0;
  top: 25px;
  left: 25px;
  border-style: solid;
  border-width: 0 14px 18px 0;
  border-color: transparent #444 transparent transparent;
  transform: skew(15deg);
}
.wolf .wolf-eyeball-left {
  width: 5px;
  height: 5px;
  top: 27px;
  left: 63px;
  background-color: rgb(255, 255, 255);
  border-radius:50%;
}
.wolf .wolf-eyeball-right {
  width: 5px;
  height: 5px;
  top: 27px;
  left: 31px;
  background-color: rgb(255, 255, 255);
  border-radius:50%;
}
.wolf .wolf-nose {
  width: 0;
  height: 0;
  top: 72px;
  left: 45px;
  border-style: solid;
  border-width: 12px 5px 0 5px;
  border-color: #444444 transparent transparent transparent;
}

/* styling of the box on the home page */
#box {
  padding: 20px;
  width: 300px;
  height:275px;
  text-align: center;
  margin: auto;
  margin-top: 20px;
  border-radius: 0px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.9);
  background-color: rgba(92, 91, 92, 0.4);
}
#box #creator {
  opacity: 0.5;
  font-size: 16px;
}
#box .home-buttons {
  width: 100px;
  height: 100px;
  margin: 20px 10px;
  border: none;
  outline: none;
  transition: background-color 0.3s, opacity 0.3s linear, border-radius 0.4s ease-out;
  color: rgb(255, 255, 255);
  font-size: 18px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.9);
}
#box #homeHowButton {
  background-color: var(--how-color);
  border-radius: 0 40px;
  -webkit-animation: rotate 1.5s ease-out 1.5s forwards;
  -moz-animation: rotate 1.5s ease-out 1.5s forwards;
  -o-animation: rotate 1.5s ease-out 1.5s forwards;
  animation: rotate 1.5s ease-out 1.5s forwards;
}
#box #homePlayButton {
  background-color: var(--game-color);
  border-radius: 40px 0;
  -webkit-animation: rotate 1.5s ease-in 1.5s reverse forwards;
  -moz-animation: rotate 1.5s ease-in 1.5s reverse forwards;
  -o-animation: rotate 1.5s ease-in 1.5s reverse forwards;
  animation: rotate 1.5s ease-in 1.5s reverse forwards;
}
#box .home-buttons:hover, #box #homeHowButton:hover, #box #homePlayButton:hover {
  opacity: 0.8;
  cursor: pointer;
  border-radius: 100%;
}
#box #welcome {
  font-size: 20px;
}

/* styling of the text on the how page */
#how .line {
  position: relative;
  margin: 0 auto;
  white-space: nowrap;
  line-height: 40px;
  overflow: hidden;
  opacity: 0;
}
#how .line-1 {
  -webkit-animation: fadein 1s ease-in 1.5s forwards;
  -moz-animation: fadein 1s ease-in 1.5s forwards;
  -o-animation: fadein 1s ease-in 1.5s forwards;
  animation: fadein 1s ease-in 1.5s forwards;
}
#how .line-2 {
  -webkit-animation: fadein 1s ease-in 3.5s forwards;
  -moz-animation: fadein 1s ease-in 3.5s forwards;
  -o-animation: fadein 1s ease-in 3.5s forwards;
  animation: fadein 1s ease-in 3.5s forwards;
}
#how .line-3 {
  -webkit-animation: fadein 1s ease-in 5.5s forwards;
  -moz-animation: fadein 1s ease-in 5.5s forwards;
  -o-animation: fadein 1s ease-in 5.5s forwards;
  animation: fadein 1s ease-in 5.5s forwards;
}
#how .line-4 {
  -webkit-animation: fadein 1s ease-in 7.5s forwards;
  -moz-animation: fadein 1s ease-in 7.5s forwards;
  -o-animation: fadein 1s ease-in 7.5s forwards;
  animation: fadein 1s ease-in 7.5s forwards;
}
#how .line-5 {
  -webkit-animation: fadein 1s ease-in 9.5s forwards;
  -moz-animation: fadein 1s ease-in 9.5s forwards;
  -o-animation: fadein 1s ease-in 9.5s forwards;
  animation: fadein 1s ease-in 9.5s forwards;
}
#how .particle-gold {
  width: 60px;
  height: 60px;
  margin: auto;
  opacity: 0;
  margin-top: 20px;
  -webkit-animation: fadein 1s ease-in 11s forwards, rotate 2s linear infinite;
  -moz-animation: fadein 1s ease-in 11s forwards, rotate 2s linear infinite;
  -o-animation: fadein 1s ease-in 11s forwards, rotate 2s linear infinite;
  animation: fadein 1s ease-in 11s forwards, rotate 2s linear infinite;
}

/* styling of the high scores table */
.table-scores {
  width: 275px;
  border: solid 0px;
  border: none;
  border-collapse: separate;
  border-spacing: 0 7px;
  line-height: 20px;
  margin: auto;
  margin-top: 30px;
  opacity: 0;
  -webkit-animation: fadein 1.5s ease-out 2s forwards;
  -moz-animation: fadein 1.5s ease-out 2s forwards;
  -o-animation: fadein 1.5s ease-out 2s forwards;
  animation: fadein 1.5s ease-out 2s forwards;
}
.table-scores th {
  color: rgba(50, 135, 168, 0.8);
}
.table-scores td {
  font-size: 14px;
  line-height: 20px;
  border-bottom: 1px solid rgba(220, 220, 220, 0.2);
}
.scores-header-name, .scores-name {
  text-align:left;
}
.scores-header-score, .scores-score {
  text-align: right;
}

/* styling of the game */
#game {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#game .game-title {
  padding-top: 50px;
  font-size: 60px;
  color: rgba(200, 200, 200, 0.15);
}
#gameComponents {
  display: none;
}
#gameComponents .game-score {
  margin: auto;
  margin-top: 100px;
  text-align: center;
  font-size: 60px;
  color: rgba(200, 200, 200, 0.2);
  opacity: 0;
  z-index: -1;
  position: relative;
  transition: opacity 0.3s linear;
  -webkit-animation: fadein 1.5s ease-in forwards;
  -moz-animation: fadein 1.5s ease-in forwards;
  -o-animation: fadein 1.5s ease-in forwards;
  animation: fadein 1.5s ease-in forwards;
}
#gameComponents #gameTimer {
  margin: auto;
  margin-top: 100px;
  text-align: center;
  font-size: 50px;
  color: rgba(200, 200, 200, 0.2);
  opacity: 0;
  z-index: -1;
  position: relative;
  transition: opacity 0.3s linear;
  -webkit-animation: fadein 1.5s ease-in forwards;
  -moz-animation: fadein 1.5s ease-in forwards;
  -o-animation: fadein 1.5s ease-in forwards;
  animation: fadein 1.5s ease-in forwards;
}
#gameScore, #gameScoreBest {
  margin: auto;
  text-align: center;
  font-size: 60px;
  color: rgba(200, 200, 200, 0.15);
  opacity: 0;
}
#gameScore {
  margin-top: 120px;
  opacity: 0;
  -webkit-animation: show-scores 0.75s forwards 0.25s;
  -moz-animation: show-scores 0.75s forwards 0.25s;
  -o-animation: show-scores 0.75s forwards 0.25s;
  animation: show-scores 0.75s forwards 0.25s;
}
#gameScoreBest {
  opacity: 0;
  -webkit-animation: show-scores 0.75s forwards 1s;
  -moz-animation: show-scores 0.75s forwards 1s;
  -o-animation: show-scores 0.75s forwards 1s;
  animation: show-scores 0.75s forwards 1s;
}
#gameStartButton, #gameReplayButton {
  position: absolute;
  left: calc(50% - 75px);
  top: calc(50%);
  margin: auto;
  background-color: var(--play-color);
  width: 150px;
  height: 50px;
  font-size: 18px;
  color: rgb(255, 255, 255);
  border: none;
  outline: none;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.9);
  transition: background-color 0.3s, opacity 0.3s linear;
}
#gameReplayButton {
  top: calc(60%);
  opacity: 0;
  -webkit-animation: spin 1.5s forwards 2s;
  -moz-animation: spin 1.5s forwards 2s;
  -o-animation: spin 1.5s forwards 2s;
  animation: spin 1.5s forwards 2s;
}
#gameStartButton:hover, #gameReplayButton:hover {
  opacity: 0.8 !important;
}

/* styling of the particles */
#particle-box {
  position: absolute;
  overflow: hidden;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.particle {
  position:absolute;
  opacity: 0;
  transition: all 1s ease-in-out;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
}
.particle-red, .bit-red {
  background-color: rgba(222, 85, 88, 1);
}
.particle-green, .bit-green {
  background-color: rgba(46, 191, 158, 1);
}
.particle-blue, .bit-blue {
  background-color: rgba(0, 145, 224, 1);
}
.particle-gold, .bit-gold {
  background-color: var(--special-color);
  border-radius: 30% 0;
}
div.particle:hover {
  cursor: pointer;
  width: 150px !important;
  height: 150px !important;
  opacity: 0.5 !important;
  -webkit-animation-play-state: paused !important;
  -moz-animation-play-state: paused !important;
  -o-animation-play-state: paused !important;
  animation-play-state: paused !important;
}

/* styling of the explosions when you click a particle */
.explosion {
  position: absolute;
  width: 600px;
  height: 600px;
  pointer-events: none;
}
.bit {
  position: absolute; 
  width: 10px;
  height: 10px;
  -webkit-animation: pop 1.5s ease-in reverse forwards;
  -moz-animation: pop 1.5s ease-in reverse forwards;
  -o-animation: pop 1.5s ease-in reverse forwards;
  animation: pop 1.5s ease-in reverse forwards;
}

@-webkit-keyframes showPage {
  from {
    opacity:0;
    transform: translateY(-100%);
  }
  to {
    opacity:1;
    transform: translateY(0%);
  }
}
@-moz-keyframes showPage {
  from {
    opacity:0;
    transform: translateY(-100%);
  }
  to {
    opacity:1;
    transform: translateY(0%);
  }
}
@-o-keyframes showPage {
  from {
    opacity:0;
    transform: translateY(-100%);
  }
  to {
    opacity:1;
    transform: translateY(0%);
  }
}
@keyframes showPage {
  from {
    opacity:0;
    transform: translateY(-100%);
  }
  to {
    opacity:1;
    transform: translateY(0%);
  }
}

@-webkit-keyframes wolf-rotate {
  0% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(20deg);
  }
  50% {
    transform: rotate(0deg);
  }
  75% {
    transform: rotate(-20deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
@-moz-keyframes wolf-rotate {
  0% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(20deg);
  }
  50% {
    transform: rotate(0deg);
  }
  75% {
    transform: rotate(-20deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
@-o-keyframes wolf-rotate {
  0% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(20deg);
  }
  50% {
    transform: rotate(0deg);
  }
  75% {
    transform: rotate(-20deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
@keyframes wolf-rotate {
  0% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(20deg);
  }
  50% {
    transform: rotate(0deg);
  }
  75% {
    transform: rotate(-20deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

@-webkit-keyframes wolf-head-change {
  0% {
    border-color: #F98546 transparent transparent transparent;
  }
  20% {
    border-color: #2EBF9E transparent transparent transparent;
  }
  40% {
    border-color: #218F76 transparent transparent transparent;
  }
  60% {
    border-color: #0091e0 transparent transparent transparent;
  }
  80% {
    border-color: #f3554a transparent transparent transparent;
  }
  100% {
    border-color: #F98546 transparent transparent transparent;
  }
}
@-moz-keyframes wolf-head-change {
  0% {
    border-color: #F98546 transparent transparent transparent;
  }
  20% {
    border-color: #2EBF9E transparent transparent transparent;
  }
  40% {
    border-color: #218F76 transparent transparent transparent;
  }
  60% {
    border-color: #0091e0 transparent transparent transparent;
  }
  80% {
    border-color: #f3554a transparent transparent transparent;
  }
  100% {
    border-color: #F98546 transparent transparent transparent;
  }
}
@-o-keyframes wolf-head-change {
  0% {
    border-color: #F98546 transparent transparent transparent;
  }
  20% {
    border-color: #2EBF9E transparent transparent transparent;
  }
  40% {
    border-color: #218F76 transparent transparent transparent;
  }
  60% {
    border-color: #0091e0 transparent transparent transparent;
  }
  80% {
    border-color: #f3554a transparent transparent transparent;
  }
  100% {
    border-color: #F98546 transparent transparent transparent;
  }
}
@keyframes wolf-head-change {
  0% {
    border-color: #F98546 transparent transparent transparent;
  }
  20% {
    border-color: #2EBF9E transparent transparent transparent;
  }
  40% {
    border-color: #218F76 transparent transparent transparent;
  }
  60% {
    border-color: #0091e0 transparent transparent transparent;
  }
  80% {
    border-color: #f3554a transparent transparent transparent;
  }
  100% {
    border-color: #F98546 transparent transparent transparent;
  }
}

@-webkit-keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@-moz-keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@-o-keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@-webkit-keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@-moz-keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@-o-keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

@-webkit-keyframes spin {
  0% {
    opacity: 0;
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(360deg);
  }
  100% {
    opacity: 1;
    transform: rotate(0deg);
  }
}
@-moz-keyframes spin {
  0% {
    opacity: 0;
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(360deg);
  }
  100% {
    opacity: 1;
    transform: rotate(0deg);
  }
}
@-o-keyframes spin {
  0% {
    opacity: 0;
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(360deg);
  }
  100% {
    opacity: 1;
    transform: rotate(0deg);
  }
}
@keyframes spin {
  0% {
    opacity: 0;
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(360deg);
  }
  100% {
    opacity: 1;
    transform: rotate(0deg);
  }
}

@-webkit-keyframes show-scores {
  from {
    opacity: 0;
    transform: rotate(0deg);
  }
  to {
    opacity: 1;
    transform: rotate(360deg);
  }
}
@-moz-keyframes show-scores {
  from {
    opacity: 0;
    transform: rotate(0deg);
  }
  to {
    opacity: 1;
    transform: rotate(360deg);
  }
}
@-o-keyframes show-scores {
  from {
    opacity: 0;
    transform: rotate(0deg);
  }
  to {
    opacity: 1;
    transform: rotate(360deg);
  }
}
@keyframes show-scores {
  from {
    opacity: 0;
    transform: rotate(0deg);
  }
  to {
    opacity: 1;
    transform: rotate(360deg);
  }
}

@-webkit-keyframes move {
  0% {
    transform: translateY(500px) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-100px)  rotate(360deg);
    opacity: 0;
  }
}
@-moz-keyframes move {
  0% {
    transform: translateY(500px) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-100px)  rotate(360deg);
    opacity: 0;
  }
}
@-o-keyframes move {
  0% {
    transform: translateY(500px) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-100px)  rotate(360deg);
    opacity: 0;
  }
}
@keyframes move {
  0% {
    transform: translateY(500px) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-100px)  rotate(360deg);
    opacity: 0;
  }
}

@-webkit-keyframes pop {
  from {
    transform: rotate(360deg);
    opacity: 0;
  }
  to {
    transform: rotate(0deg);
    top: 50%;
    left: 50%;
    opacity: 1;
  }
}
@-moz-keyframes pop {
  from {
    transform: rotate(360deg);
    opacity: 0;
  }
  to {
    transform: rotate(0deg);
    top: 50%;
    left: 50%;
    opacity: 1;
  }
}
@-o-keyframes pop {
  from {
    transform: rotate(360deg);
    opacity: 0;
  }
  to {
    transform: rotate(0deg);
    top: 50%;
    left: 50%;
    opacity: 1;
  }
}
@keyframes pop {
  from {
    transform: rotate(360deg);
    opacity: 0;
  }
  to {
    transform: rotate(0deg);
    top: 50%;
    left: 50%;
    opacity: 1;
  }
}

</style>
<script>

var game_score = 0;
var game_score_best = 0;
var GAME_TIMER_START = 30;
var game_timer = 0;
var game_highscores = false;
var game_over = false;
var gameCountdownTimer;
var gameSpecialTimer = 0;
var game_scores = [
  {
    name: "Grant Jenkins",
    score: 131
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  },
  {
    name: "Could be you",
    score: 0
  }
];
game_scores.sort(function(a, b) {
  return b.score - a.score; 
});

// get random number between min and max value
function rand(min, max) {
  return Math.floor(Math.random() * (max + 1)) + min;
}

//add explosions when you click on a particle
function explode(x, y, bitcolor) {
  var particles = 15,
      // explosion container and its reference to be able to delete it on animation end
      explosion = $('<div class="explosion"></div>');

  //put the explosion container into the game page
  $('#game').append(explosion);

  //position the container to be centered
  explosion.css('left', x - explosion.width() / 2);
  explosion.css('top', y - explosion.height() / 2);

  for (var i = 0; i < particles; i++) {
    //random end positions for each of the particles
    var x = (explosion.width() / 2) + rand(80, 150) * Math.cos(2 * Math.PI * i / rand(particles - 10, particles + 10));
    var y = (explosion.height() / 2) + rand(80, 150) * Math.sin(2 * Math.PI * i / rand(particles - 10, particles + 10));

    //create the particle elements
    elm = $('<div class="bit bit-' + bitcolor + '" style="' +
            'top: ' + y + 'px; ' +
            'left: ' + x + 'px"></div>');

    // no need to add the listener on all generated elements
    if (i == 0) { 
      //when animation ends then it will automatically remove the element
      elm.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
        explosion.remove();
      });
    }
    //add the particle
    explosion.append(elm);
  }
}

//event triggered when the user clicks on a particle
var particleClick = function(e) {
  let particleWidth = this.offsetWidth;

  //if particle reached full width
  if(particleWidth === 150) {
    //add appropriate score/time based on type of particle
    switch($(this).data("type")) {
      case "time":
        game_score++;
        game_timer+=5;
        break;
      case "points":
        game_score+=5;
        game_timer++;
        break;
      default:
        game_score++;
        game_timer++;
    }

    //add the score to the screen
    $(".game-score").text(game_score);

    //get the color of the particle
    var arr = $(this).attr("class").split('-');
    var item = arr[arr.length-1];

    //remove the particle
    this.remove();

    //add explosions
    explode(e.pageX, e.pageY, item);

    //create a new particle in place if the existing one
    createParticle();
  }
}

//creates each particle
var createParticle = function() {
  //initiate and set properties on particle
  let particle = {
    x: Math.random() * window.innerWidth,
    y: Math.random() * window.innerHeight + 20,
    size: Math.random() * 25 + 10,
    speed: Math.random() * 6 + 3,
    delay: Math.random() * 0.3 + 0.2,
    color: Math.random() < 0.33 ? "red" : Math.random() < 0.5 ? "green" : "blue",
    data: "normal"
  };

  //increase the special timer so that we get a
  //special particle at least every 5 particles
  gameSpecialTimer = (gameSpecialTimer + 1) % 5;

  //if special particle the set properties here
  if(Math.random() < 0.1 || gameSpecialTimer === 0) {
    particle.color = "gold";
    particle.data = Math.random() < 0.3 ? "time" : "points";
  }

  //append the particle to the particle box
  $("#particle-box").append("<div class='particle particle-" + 
                            particle.color + "' data-type='" + particle.data + "'></div>");

  //get the particle that was just added
  var last = $("#particle-box").children().last();

  //setup the click event for the particle
  last.on( "click", particleClick );

  //add appropriate css properties including css animation
  last.css(
    "animation", 
    "move " + particle.speed + "s infinite linear " + particle.delay + "s");
  last.css(
    "left", 
    particle.x);
  last.css(
    "top", 
    particle.y);
  last.css(
    "width", 
    particle.size);
  last.css(
    "height", 
    particle.size);
}

//setup the initial particles for each game
var setupParticles = function() {
  //remove any existing particles
  $("#particle-box").empty();

  //create an initial set of 40 particles
  for(var i = 0; i < 40; i++) {
    createParticle();
  }
}

//reset the game
var resetGame = function() {
  //reset game timer    
  game_timer = 0;

  //set game over to true
  game_over = true;

  //reset special timer
  gameSpecialTimer = 0;

  //clear the existing interval if it exists
  clearInterval(gameCountdownTimer);

  //remove any existing explosions
  $(".explosion").empty();

  //remove all particles
  $("#particle-box").empty();

  //show/hide appropriate components
  $("#gameStartButton").show();
  $("#gameComponents").hide();
  $("#gameOver").hide();
}

//starts the game
var startGame = function() {
  //reset score
  game_score = 0;

  //set game over to false
  game_over = false;

  //reset game score
  $(".game-score").text(game_score);

  //reset timer
  game_timer = GAME_TIMER_START;

  //hide/show components
  $("#gameStartButton").hide();
  $("#gameOver").hide();
  $("#gameComponents").show();

  //setup particles
  setupParticles();

  //display initial timer
  $("#gameTimer").text(game_timer + " seconds remaining");

  //setup interval to control the timing of the game
  gameCountdownTimer = setInterval(function(){
    //if game over...
    if(game_timer <= 0){
      //clear the interval (remove it)
      clearInterval(gameCountdownTimer);

      if(!game_over) {
        //set best score to be the max score
        game_score_best = Math.max(game_score_best, game_score);

        //display the scores
        $("#gameScore").text("Score: " + game_score);
        $("#gameScoreBest").text("Best Score: " + game_score_best);

        //display the game over box
        $("#gameOver").show();

        //remove the particles
        $("#particle-box").empty();

        //hide the start button and game components
        $("#gameStartButton").hide();
        $("#gameComponents").hide();
      }
    }
    //else if game still in progress
    else {
      $("#gameTimer").text(game_timer + " seconds remaining");
    }
    //decrease the timer by 1 each second
    game_timer -= 1;
  },
                                   1000); //interval set to 1 second
}

setupScores = function() {
  var scoresTable = '<table cellspacing="0" class="table-scores">' +
      '<thead>' +
      '<tr>' +
      '<th class="scores-header-name">Name</th>' +
      '<th class="scores-header-score">Score</th>' +
      '</tr>' +
      '</thead>' +
      '<tbody>';

  for(var i = 0; i < game_scores.length; i++) {
    let score = game_scores[i];

    scoresTable += '<tr>' +
      '<td class="scores-name">' + score.name + '</td>' +
      '<td class="scores-score">' + score.score + '</td>' +
      '</tr>';
  }

  scoresTable += '</tbody></table>';

  $("#scoresTable").empty();
  $("#scoresTable").append(scoresTable);
}

$(".page").css({display: "none"});
$("#home").css({display: "block"});
var switchPage = function (page){
  $(".page").css({display: "none"});
  $(page).css({display: "block",});

  $(".page").removeClass('showPage');
  $(page).addClass('showPage');

  $('button').removeClass('active');
  $(page+"Button").addClass('active');

  //reset game
  if(page === "#game") {
    resetGame();
  }
  //build highscores (only once)
  else if(page === "#scores" && !game_highscores) {
    setupScores();
  }
};
//switch to the home page when first get to the site
switchPage("#home");


</script>

<!--
  Particles (Game)
  Grant Jenkins, March 2023
  #cpc-random-button, #codepenchallenge

  - All animations using CSS animations
  - All particles are divs with translations
  - Wolves are pure HTML/CSS (style/animations)
  - CSS caters for all major browsers (webkit, moz, o)

  Check out my Khan Academy projects here:
  https://www.khanacademy.org/profile/grantjenkins/projects
  
  Find me in the Microsoft Power Automate forums here:
  https://powerusers.microsoft.com/t5/user/viewprofilepage/user-id/76589

    -----------------------------------------------------
    If you want to submit your score, let me know :)
    -----------------------------------------------------
-->

<div id="box34">
<html>
    <head>
        <meta charset="utf-8">
        <title>Particles (Game)</title>
        <link 
        href="https://fonts.googleapis.com/css?family=Indie+Flower|Material+Icons|Handlee&display=swap" 
        rel="stylesheet">
       
    </head>
    <body>
        <header>
            <nav>
                <button id="homeButton" onClick="switchPage('#home');" class="active material-icons">house</button>
                <button id="howButton" onClick="switchPage('#how');">How To Play</button>
                <button id="scoresButton" onClick="switchPage('#scores');">High Scores</button>
                <button id="gameButton" onClick="switchPage('#game');">Play</button>
            </nav>
        </header> <!--Navigation-->
        <div id="content">
            <div id="home" class="page"> <!--Home Page-->
                <div class="wolves">
                    <div class="wolf top-left">
                        <div class="wolf-ear-left"></div>
                        <div class="wolf-ear-right"></div>
                        <div class="wolf-head"></div>
                        <div class="wolf-eye-left"></div>
                        <div class="wolf-eye-right"></div>
                        <div class="wolf-eyeball-left"></div>
                        <div class="wolf-eyeball-right"></div>
                        <div class="wolf-nose"></div>
                    </div>
                    <div class="wolf top-right">
                        <div class="wolf-ear-left"></div>
                        <div class="wolf-ear-right"></div>
                        <div class="wolf-head"></div>
                        <div class="wolf-eye-left"></div>
                        <div class="wolf-eye-right"></div>
                        <div class="wolf-eyeball-left"></div>
                        <div class="wolf-eyeball-right"></div>
                        <div class="wolf-nose"></div>
                    </div>
                </div> <!--Wolves-->
            
                <h1 id="header">Particles</h1>
                <div id="box">
                    <p id="creator">A game by Grant Jenkins</p>
                    <p id="welcome">Welcome to Particles, a game of speed and accuracy.</p>
                    <div id="circles">
                        <button id="homeHowButton" class="home-buttons" onClick="switchPage('#how');">How</button>
                        <button id="homePlayButton" class="home-buttons" onClick="switchPage('#game');">Play</button>
                    </div>
                </div>
                
            </div> <!--home-->
            <div id="how" class="page"> <!--How page-->
                <h1>How</h1>
                <article>
                    <p class="line line-1">You need to hover over the particles as they move up the screen.</p>
                    <p class="line line-2">When a particle reaches full size you need to click on it.</p>
                    <p class="line line-3">Clicking on a particle will award you one point and add one second to your time.</p>
                    <p class="line line-4">There are special gold particles that award you even more points/time.</p>
                    <p class="line line-5">Click on the Play button to get started.</p>
                    <div class="particle-gold"></div>
                </article>
                <div class="wolves">
                    <div class="wolf top-left">
                        <div class="wolf-ear-left"></div>
                        <div class="wolf-ear-right"></div>
                        <div class="wolf-head"></div>
                        <div class="wolf-eye-left"></div>
                        <div class="wolf-eye-right"></div>
                        <div class="wolf-eyeball-left"></div>
                        <div class="wolf-eyeball-right"></div>
                        <div class="wolf-nose"></div>
                    </div>
                    <div class="wolf top-right">
                        <div class="wolf-ear-left"></div>
                        <div class="wolf-ear-right"></div>
                        <div class="wolf-head"></div>
                        <div class="wolf-eye-left"></div>
                        <div class="wolf-eye-right"></div>
                        <div class="wolf-eyeball-left"></div>
                        <div class="wolf-eyeball-right"></div>
                        <div class="wolf-nose"></div>
                    </div>
                </div> <!--Wolves-->
                
            </div> <!--how-->
            <div id="scores" class="page"> <!--Scores page-->
                <h1>Scores</h1>
                <div id="scoresTable"></div>
                <div class="wolves">
                    <div class="wolf top-left">
                        <div class="wolf-ear-left"></div>
                        <div class="wolf-ear-right"></div>
                        <div class="wolf-head"></div>
                        <div class="wolf-eye-left"></div>
                        <div class="wolf-eye-right"></div>
                        <div class="wolf-eyeball-left"></div>
                        <div class="wolf-eyeball-right"></div>
                        <div class="wolf-nose"></div>
                    </div>
                    <div class="wolf top-right">
                        <div class="wolf-ear-left"></div>
                        <div class="wolf-ear-right"></div>
                        <div class="wolf-head"></div>
                        <div class="wolf-eye-left"></div>
                        <div class="wolf-eye-right"></div>
                        <div class="wolf-eyeball-left"></div>
                        <div class="wolf-eyeball-right"></div>
                        <div class="wolf-nose"></div>
                    </div>
                </div> <!--Wolves-->
                
            </div> <!--scores-->
            <div id="game" class="page"> <!--game page-->
                <div id="particle-box"></div>
                <div id="gameComponents">
                    <div id="gameTimer"></div>
                    <div class="game-score">0</div>
                </div>
                <div id="gameOver">
                    <div id="gameScore" class="game-score">0</div>
                    <div id="gameScoreBest">0</div>
                    <button id="gameReplayButton" onclick="startGame();">Replay</button>
                </div>
                <button id="gameStartButton" onclick="startGame();">Start</button>
            </div> <!--Game-->
        </div> <!--Content-->
    
        <!--jQuery library-->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    </body>
</html>
</div>
[/html]

+3

173

И еще один дизайн где много чего двигается просто так

Озадачился панелью юзера слева тела форума (отключена при особом расширении экрана). Добавил эффект на название и аватарки. В целом полное баловство без ограничений. Да, так тоже можно.

+3

174

#p181613,Will O The Wisp написал(а):

Озадачился панелью юзера слева тела форума (отключена при особом расширении экрана). Добавил эффект на название и аватарки. В целом полное баловство без ограничений. Да, так тоже можно.

На самом деле, у тебя интересные и свежие идеи в плане дизайна. Ими можно только вдохновляться!

+1

175

Свернутый текст

Закончил сегодня с реализацией шаблона ни для чего конкретного. Это дизайн наоборот, основанный на сочетании однотонного задника и картиночнтого тела форума. Ярко, сочно, вычурно как бархатцы. В качестве пробы пера изменена форма входа, картинка с задника множится, вертится и фильтруется. Шаблон действительно очень яркий.

+2

176

Сториз

Код:
[html]
<style>
h5 {
  opacity: 0.66;
  font-weight: normal;
  font-size: 1.25rem;
}

.container {
  position: relative;
  width: 430px;
  height: 350px;
  margin: 50px auto;
  background: #fafafa;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  color: #fff;
}

.time {
  padding: 10px;
  display: flex;
  justify-content: space-around;
}

.time-item {
  flex: 1 1 auto;
  border-radius: 5px;
  margin-right: 5px;
  height: 10px;
  background-color: rgba(0,0,0,0.10);
  position: relative;
  overflow: hidden;
}

.time-item:last-child {
  margin-right: 0;
}

.time-item > div {
  position: absolute;
  width: 0%;
  height: 100%;
  background-color: rgba(255,255,255,0.5);
}

.content {
  position: absolute;
  height: 350px;
  width:430px;
  background-image: linear-gradient(-180deg, rgba(255,255,255,0.00) 0%, rgba(0,0,0,0.15) 100%);

  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.texts {
  padding: 7%;
}

#back, #next {
  position: absolute;
  top: 0;
}

#back {
  left: 0;
  height: 100%;
  width: 50%;
}

#next {
  left: 50%;
  height: 100%;
  width: 50%;
}

</style>
<script>

const stories = [
  {
    title: 'Story 1',
    description: 'description 1',
    image: 'https://i.pinimg.com/736x/2e/be/62/2ebe623d6d27d70ea13731a01b4210e9.jpg',
    time: 3500
  },
  {
    title: 'Story 2',
    description: 'description 2',
    image: 'https://i.pinimg.com/736x/7c/f8/18/7cf818809ed21f9d21263b8a8417d504.jpg',
    time: 4000
  },{
    title: 'Story 3',
    description: 'description 3',
    image: 'https://i.pinimg.com/736x/b7/7b/e1/b77be1a020e21187490bb65859d2832c.jpg',
    time: 2500
  },
  {
    title: 'Story 4',
    description: 'description 4',
    image: 'https://i.pinimg.com/736x/8d/77/5e/8d775e040b58466a44518ad6b5c2a678.jpg',
    time: 7500
  }
]

const container = document.querySelector('.container')
const nextButton = document.querySelector('#next')
const backButton = document.querySelector('#back')

function Storyfier(storiesArray, rootEl) {
  this.stories = storiesArray
  this.root = rootEl
  this.times = rootEl.querySelector('#times')
  this.currentTime = 0
  this.currentIndex = 0

  // create breakpoints for when the slides should change
  this.intervals = this.stories.map((story, index) => {
    // TODO change so that it just uses the previous value + current time
    let sum = 0
    for (let i = 0; i < index; i++){
      sum += this.stories[i].time
    }
    return sum
  })

  // necessary to make sure the last slide plays to completion
  this.maxTime = this.intervals[this.intervals.length - 1] + this.stories[this.stories.length - 1].time

  // render progress bars
  this.progressBars = this.stories.map(() => {
    const el = document.createElement('div')
    el.classList.add('time-item')
    el.innerHTML = '<div style="width: 0%"></div>'
    return el
  })

  this.progressBars.forEach((el) => {
    this.times.appendChild(el)
  })

  // methods
  this.render = () => {
    const story = this.stories[this.currentIndex]
    this.root.style.background = `url('${story.image}')`
    this.root.querySelector('#title').innerHTML = story.title
    this.root.querySelector('#description').innerHTML = story.description
  }

  this.updateProgress = () => {
    this.progressBars.map((bar, index) => {
      // Fill already passed bars
      if (this.currentIndex > index) {
        bar.querySelector('div').style.width = '100%'
        return
      }

      if (this.currentIndex < index) {
        bar.querySelector('div').style.width = '0%'
        return
      }

      // update progress of current bar
      if (this.currentIndex == index) {
        const timeStart = this.intervals[this.currentIndex]

        let timeEnd;
        if (this.currentIndex == this.stories.length - 1){
          timeEnd = this.maxTime
        } else {
          timeEnd = this.intervals[this.currentIndex + 1]
        }

        const animatable = bar.querySelector('div')
        animatable.style.width = `${((this.currentTime - timeStart)/(timeEnd - timeStart))*100}%`


      }
    })
  }
}

Storyfier.prototype.start = function(){
  // Render initial state
  this.render()

  // START INTERVAL
  const test = setInterval(() => {
    this.currentTime += 10
    this.updateProgress()

    if (this.currentIndex >= this.stories.length - 1 && (this.currentTime > this.maxTime)){
      clearInterval(test)
      return
    }

    const lastIndex = this.currentIndex
    if (this.currentTime >= this.intervals[this.currentIndex + 1]){
      this.currentIndex += 1
    }

    if (this.currentIndex != lastIndex) {
      this.render()
    }
  }, 10)
}

Storyfier.prototype.next = function(){
  const next = this.currentIndex + 1
  if (next > this.stories.length - 1){
    return
  }

  this.currentIndex = next
  this.currentTime = this.intervals[this.currentIndex]
  this.render()
}

Storyfier.prototype.back = function(){
  if ((this.currentTime > (this.intervals[this.currentIndex] + 350)) || this.currentIndex === 0){
    this.currentTime = this.intervals[this.currentIndex]
    return
  }

  this.currentIndex -= 1
  this.currentTime = this.intervals[this.currentIndex]
  this.render()
}

const setup = async () => {
  const loadImages = stories.map(({ image }) => {
    return new Promise((resolve, reject) => {
      let img = new Image()
      img.onload = () => {
        resolve(image)
      }
      img.src = image
    })
  })

  await Promise.all(loadImages)

  const s = new Storyfier(stories, container);
  s.start()

  nextButton.addEventListener('click', () => {
    s.next()
  })

  backButton.addEventListener('click', () => {
    s.back()
  })
}

setup()

</script>
<div class="container">
  <div id="times" class="time">
  </div>

  <div class="content">
    <div class="texts">
      <h1 id="title"></h1>
      <h5 id="description"></h5>
    </div>
  </div>

  <div id="back"></div>
  <div id="next"></div>
</div>
[/html]

+2

177

https://forumupload.ru/uploads/0007/e3/f7/7629/284747.jpg
Как может выглядеть контейнер под статистику если применить к нему display: flex;

+4

178

Стильные кнопочки
https://codepen.io/jkantner/pen/QWZrMeB

Код:
[html]
<style>
:root {
	--hue: 223;
	--bg: hsl(var(--hue),10%,90%);
	--fg: hsl(var(--hue),10%,10%);
	--trans-dur: 0.3s;
	font-size: calc(16px + (24 - 16) * (100vw - 320px) / (2560 - 320));
}

.icon-btns {
	display: grid;
	grid-gap: 3em;
	grid-template-columns: repeat(2,1fr);
	margin: auto;
	padding: 3em 0;
}
.icon-btn {
	background-color: transparent;
	outline: transparent;
	position: relative;
	width: 4.5em;
	height: 4.5em;
	perspective: 24em;
	transform-style: preserve-3d;
	-webkit-tap-highlight-color: transparent;
border: none;
}
.icon-btn__back,
.icon-btn__front,
.icon-btn__label {
	transition:
    opacity var(--trans-dur) cubic-bezier(0.83,0,0.17,1),
    transform var(--trans-dur) cubic-bezier(0.83,0,0.17,1);
}
.icon-btn__back,
.icon-btn__front {
	border-radius: 1.25em;
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}
.icon-btn__back {
	background: linear-gradient(hsl(var(--hue),10%,50%),hsl(208,10%,50%));
	box-shadow: 0.5em -0.5em 0.75em hsla(var(--hue),10%,10%,0.15);
	display: block;
	transform: rotate(15deg);
	transform-origin: 100% 100%;
}
.icon-btn__front {
	background-color: hsla(0,0%,100%,0.3);
	box-shadow: 0 0 0 0.125em hsla(0,0%,100%,0.3) inset;
	backdrop-filter: blur(0.75em);
	-webkit-backdrop-filter: blur(0.75em);
	display: flex;
	transform-origin: 80% 50%;
}
.icon-btn--blue .icon-btn__back {
	background: linear-gradient(hsl(var(--hue),90%,50%),hsl(208,90%,50%));
}
.icon-btn--green .icon-btn__back {
	background: linear-gradient(hsl(123,90%,40%),hsl(108,90%,40%));
}
.icon-btn--indigo .icon-btn__back {
	background: linear-gradient(hsl(253,90%,50%),hsl(238,90%,50%));
}
.icon-btn--purple .icon-btn__back {
	background: linear-gradient(hsl(283,90%,50%),hsl(268,90%,50%));
}
.icon-btn--red .icon-btn__back {
	background: linear-gradient(hsl(3,90%,50%),hsl(348,90%,50%));
}
.icon-btn--orange .icon-btn__back {
	background: linear-gradient(hsl(43,90%,50%),hsl(28,90%,50%));
}
.icon-btn__icon {
	margin: auto;
	width: 1.5em;
	height: 1.5em;
}
.icon-btn__label {
	font-size: 0.75em;
	line-height: 2;
	opacity: 0;
	position: absolute;
	top: 100%;
	right: 0;
	left: 0;
	transform: translateY(0);
color: #fff;
}
.icon-btn:focus-visible .icon-btn__back,
.icon-btn:hover .icon-btn__back {
	transform: rotate(22.5deg);
}
.icon-btn:focus-visible .icon-btn__front,
.icon-btn:hover .icon-btn__front {
	transform: translateZ(3em) rotateX(20deg) rotateY(20deg);
}
.icon-btn:focus-visible .icon-btn__label,
.icon-btn:hover .icon-btn__label {
	opacity: 1;
	transform: translateY(20%);
}
.sprites {
	display: block;
	position: fixed;
	transform: translateY(-100%);
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
	:root {
    --bg: hsl(var(--hue),10%,30%);
    --fg: hsl(var(--hue),10%,90%);
	}
}

/* Beyond mobile */
@media (min-width: 768px) {
	.icon-btns {
    grid-template-columns: repeat(3,1fr);
	}
}
</style>

<container style="background: #6e5a5a;
display: block;
padding: 20px 0px 10px 60px;">
<svg class="sprites" display="none">
	<defs>
    <linearGradient id="icon-grad" x1="0" y1="0" x2="1" y2="1">
    	<stop offset="0%" stop-color="#fff" />
    	<stop offset="100%" stop-color="#222" />
    </linearGradient>
    <mask id="icon-mask">
    	<rect x="0" y="0" width="24" height="24" fill="url(#icon-grad)" />
    </mask>
    <symbol id="files" viewBox="0 0 24 24">
    	<g fill="hsl(0,0%,100%)" mask="url(#icon-mask)">
        <path d="m2.003,3h3.997c1.105,0,2,.895,2,2h0s14.005,0,14.005,0c1.102,0,1.995.893,1.995,1.995v1.005H0v-2.997c0-1.106.897-2.003,2.003-2.003Z"/>
        <path d="m22.005,21H1.996c-1.102,0-1.996-.893-1.996-1.996v-9.004l24-.172v9.177c0,1.102-.893,1.995-1.995,1.995Z"/>
    	</g>
    </symbol>
    <symbol id="books" viewBox="0 0 24 24">
    	<g fill="hsl(0,0%,100%)" mask="url(#icon-mask)">
        <path d="m14.113,22.696c-.356.389-1.022.176-1.022-.351V3.287c1.091-1.091,2.277-1.558,3.509-1.83,2.182-.481,4.125-.377,5.314-.222,1.317.171,2.087,1.342,2.087,2.495v14.357c0,1.553-1.296,2.777-2.802,2.727-1.246-.041-2.975.003-4.541.382-1.195.289-1.954.856-2.544,1.501Z"/>
        <path d="m9.887,22.696c.356.389,1.022.176,1.022-.351V3.287c-1.091-1.091-2.277-1.558-3.509-1.83-2.182-.481-4.125-.377-5.314-.222C.77,1.406,0,2.577,0,3.729v14.357c0,1.553,1.296,2.777,2.802,2.727,1.246-.041,2.975.003,4.541.382,1.194.289,1.954.856,2.544,1.501Z"/>
    	</g>
    </symbol>
    <symbol id="graph" viewBox="0 0 24 24">
    	<g fill="hsl(0,0%,100%)" mask="url(#icon-mask)">
        <rect rx="1" ry="1" x="0" y="12" width="6" height="12" />
        <rect rx="1" ry="1" x="9" y="0" width="6" height="24" />
        <rect rx="1" ry="1" x="18" y="6" width="6" height="18" />
    	</g>
    </symbol>
    <symbol id="weather" viewBox="0 0 24 24">
    	<g fill="hsl(0,0%,100%)" mask="url(#icon-mask)">
        <path d="m2.65,10.95c.916-.546,1.986-.858,3.129-.858.138,0,.276.004.414.013.388-1.331,1.13-2.499,2.113-3.403-.187-2.126-1.971-3.791-4.144-3.791-2.299,0-4.162,1.863-4.162,4.162,0,1.766,1.1,3.273,2.65,3.877Z"/>
        <path d="m19.687,12.464s-.003,0-.005,0c.002-.072.005-.144.005-.216,0-3.454-2.8-6.254-6.253-6.254-3.235,0-5.897,2.457-6.22,5.607-.454-.14-.936-.216-1.435-.216-2.679,0-4.852,2.172-4.852,4.852s2.172,4.852,4.852,4.852h13.908c2.382,0,4.313-1.931,4.313-4.312,0-2.382-1.931-4.313-4.313-4.313Z"/>
    	</g>
    </symbol>
    <symbol id="pen" viewBox="0 0 24 24">
    	<g fill="hsl(0,0%,100%)" mask="url(#icon-mask)">
        <path d="M3.1,0C2.5-0.1,2.1,0.6,2.5,1L10,8.5c0.2,0,0.4-0.1,0.6-0.1c1.2,0,2.2,1,2.2,2.2c0,1.2-1,2.2-2.2,2.2c-1.2,0-2.2-1-2.2-2.2c0-0.2,0-0.4,0.1-0.6L1,2.5C0.6,2.1-0.1,2.5,0,3.1L3.4,17c0.1,0.4,0.4,0.7,0.9,0.8l6.4,1.3c-0.2,0.4-0.1,0.9,0.2,1.2l3.3,3.3c0.4,0.4,1.1,0.4,1.6,0l7.8-7.8c0.4-0.4,0.4-1.1,0-1.6l-3.3-3.3c-0.3-0.3-0.8-0.4-1.2-0.2l-1.3-6.4c-0.1-0.4-0.4-0.8-0.8-0.9L3.1,0z"/>
    	</g>
    </symbol>
    <symbol id="heart" viewBox="0 0 24 24">
    	<g fill="hsl(0,0%,100%)" mask="url(#icon-mask)">
        <path d="m.204,9.117c.272,1.039.791,1.942,1.558,2.709l10.238,10.597,10.238-10.597c.767-.767,1.287-1.67,1.558-2.709.272-1.039.272-2.07,0-3.093-.272-1.023-.791-1.918-1.558-2.685-.767-.767-1.662-1.287-2.685-1.558-1.023-.272-2.062-.272-3.117,0-1.055.272-1.95.791-2.685,1.558l-1.75,2.11-1.75-2.11c-.767-.767-1.662-1.287-2.685-1.558s-2.054-.272-3.093,0c-1.039.272-1.942.791-2.709,1.558-.767.767-1.287,1.662-1.558,2.685-.272,1.023-.272,2.054,0,3.093Z"/>
    	</g>
    </symbol>
	</defs>
</svg>
<div class="icon-btns">
	<button class="icon-btn icon-btn--blue" type="button">
    <span class="icon-btn__back"></span>
    <span class="icon-btn__front">
    	<svg class="icon-btn__icon" width="24px" height="24px" aria-hidden="true">
        <use xlink:href="#files" />
    	</svg>
    </span>
    <span class="icon-btn__label">Files</span>
	</button>
	<button class="icon-btn icon-btn--purple" type="button">
    <span class="icon-btn__back"></span>
    <span class="icon-btn__front">
    	<svg class="icon-btn__icon" width="24px" height="24px" aria-hidden="true">
        <use xlink:href="#books" />
    	</svg>
    </span>
    <span class="icon-btn__label">Books</span>
	</button>
	<button class="icon-btn icon-btn--red" type="button">
    <span class="icon-btn__back"></span>
    <span class="icon-btn__front">
    	<svg class="icon-btn__icon" width="24px" height="24px" aria-hidden="true">
        <use xlink:href="#heart" />
    	</svg>
    </span>
    <span class="icon-btn__label">Health</span>
	</button>
	<button class="icon-btn icon-btn--indigo" type="button">
    <span class="icon-btn__back"></span>
    <span class="icon-btn__front">
    	<svg class="icon-btn__icon" width="24px" height="24px" aria-hidden="true">
        <use xlink:href="#weather" />
    	</svg>
    </span>
    <span class="icon-btn__label">Weather</span>
	</button>
	<button class="icon-btn icon-btn--orange" type="button">
    <span class="icon-btn__back"></span>
    <span class="icon-btn__front">
    	<svg class="icon-btn__icon" width="24px" height="24px" aria-hidden="true">
        <use xlink:href="#pen" />
    	</svg>
    </span>
    <span class="icon-btn__label">Notes</span>
	</button>
	<button class="icon-btn icon-btn--green" type="button">
    <span class="icon-btn__back"></span>
    <span class="icon-btn__front">
    	<svg class="icon-btn__icon" width="24px" height="24px" aria-hidden="true">
        <use xlink:href="#graph" />
    	</svg>
    </span>
    <span class="icon-btn__label">Spreadsheets</span>
	</button>
</div>
</container>
[/html]

Отредактировано Will O The Wisp (17.05.23 08:32)

+3

179

Работающая авадакедавра с размещением в теме

Код:
[html]
<style>

#container {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 800px;
}

.a-title {
  position: absolute;
  color: transparent;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-image: conic-gradient(#ed0101, blue);
  pointer-events: none;
  mix-blend-mode: difference;
  filter: drop-shadow(2px 4px 6px black);
}
.a-second-title {
  position: absolute;
  margin-top: 25vh;
  pointer-events: none;
  -webkit-text-stroke: 1.3px white;
  letter-spacing: 1.125px;
  font-size: -webkit-xxx-large;
  font-weight: 900;
  mix-blend-mode: color-dodge;
}

canvas {
  width: 100%;
  height: 100%;
}

</style>
<script>
'use strict';

const canvas = document.getElementsByTagName('canvas')[0];
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;

let config = {
  TEXTURE_DOWNSAMPLE: 1,
  DENSITY_DISSIPATION: 0.98,
  VELOCITY_DISSIPATION: 0.99,
  PRESSURE_DISSIPATION: 0.8,
  PRESSURE_ITERATIONS: 25,
  CURL: 28,
  SPLAT_RADIUS: 0.004 };


let pointers = [];
let splatStack = [];

const { gl, ext } = getWebGLContext(canvas);

function getWebGLContext(canvas) {
  const params = { alpha: false, depth: false, stencil: false, antialias: false };

  let gl = canvas.getContext('webgl2', params);
  const isWebGL2 = !!gl;
  if (!isWebGL2)
  gl = canvas.getContext('webgl', params) || canvas.getContext('experimental-webgl', params);

  let halfFloat;
  let supportLinearFiltering;
  if (isWebGL2) {
    gl.getExtension('EXT_color_buffer_float');
    supportLinearFiltering = gl.getExtension('OES_texture_float_linear');
  } else {
    halfFloat = gl.getExtension('OES_texture_half_float');
    supportLinearFiltering = gl.getExtension('OES_texture_half_float_linear');
  }

  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  const halfFloatTexType = isWebGL2 ? gl.HALF_FLOAT : halfFloat.HALF_FLOAT_OES;
  let formatRGBA;
  let formatRG;
  let formatR;

  if (isWebGL2)
  {
    formatRGBA = getSupportedFormat(gl, gl.RGBA16F, gl.RGBA, halfFloatTexType);
    formatRG = getSupportedFormat(gl, gl.RG16F, gl.RG, halfFloatTexType);
    formatR = getSupportedFormat(gl, gl.R16F, gl.RED, halfFloatTexType);
  } else

  {
    formatRGBA = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
    formatRG = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
    formatR = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
  }

  return {
    gl,
    ext: {
      formatRGBA,
      formatRG,
      formatR,
      halfFloatTexType,
      supportLinearFiltering } };


}

function getSupportedFormat(gl, internalFormat, format, type)
{
  if (!supportRenderTextureFormat(gl, internalFormat, format, type))
  {
    switch (internalFormat) {

      case gl.R16F:
        return getSupportedFormat(gl, gl.RG16F, gl.RG, type);
      case gl.RG16F:
        return getSupportedFormat(gl, gl.RGBA16F, gl.RGBA, type);
      default:
        return null;}

  }

  return {
    internalFormat,
    format };

}

function supportRenderTextureFormat(gl, internalFormat, format, type) {
  let texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 4, 4, 0, format, type, null);

  let fbo = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);

  const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
  if (status != gl.FRAMEBUFFER_COMPLETE)
  return false;
  return true;
}

function pointerPrototype() {
  this.id = -1;
  this.x = 0;
  this.y = 0;
  this.dx = 0;
  this.dy = 0;
  this.down = false;
  this.moved = false;
  this.color = [30, 0, 300];
}

pointers.push(new pointerPrototype());

class GLProgram {
  constructor(vertexShader, fragmentShader) {
    this.uniforms = {};
    this.program = gl.createProgram();

    gl.attachShader(this.program, vertexShader);
    gl.attachShader(this.program, fragmentShader);
    gl.linkProgram(this.program);

    if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
    throw gl.getProgramInfoLog(this.program);

    const uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
    for (let i = 0; i < uniformCount; i++) {
      const uniformName = gl.getActiveUniform(this.program, i).name;
      this.uniforms[uniformName] = gl.getUniformLocation(this.program, uniformName);
    }
  }

  bind() {
    gl.useProgram(this.program);
  }}


function compileShader(type, source) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
  throw gl.getShaderInfoLog(shader);

  return shader;
};

const baseVertexShader = compileShader(gl.VERTEX_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    attribute vec2 aPosition;
    varying vec2 vUv;
    varying vec2 vL;
    varying vec2 vR;
    varying vec2 vT;
    varying vec2 vB;
    uniform vec2 texelSize;

    void main () {
        vUv = aPosition * 0.5 + 0.5;
        vL = vUv - vec2(texelSize.x, 0.0);
        vR = vUv + vec2(texelSize.x, 0.0);
        vT = vUv + vec2(0.0, texelSize.y);
        vB = vUv - vec2(0.0, texelSize.y);
        gl_Position = vec4(aPosition, 0.0, 1.0);
    }
`);

const clearShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    uniform sampler2D uTexture;
    uniform float value;

    void main () {
        gl_FragColor = value * texture2D(uTexture, vUv);
    }
`);

const displayShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    uniform sampler2D uTexture;

    void main () {
        gl_FragColor = texture2D(uTexture, vUv);
    }
`);

const splatShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    uniform sampler2D uTarget;
    uniform float aspectRatio;
    uniform vec3 color;
    uniform vec2 point;
    uniform float radius;

    void main () {
        vec2 p = vUv - point.xy;
        p.x *= aspectRatio;
        vec3 splat = exp(-dot(p, p) / radius) * color;
        vec3 base = texture2D(uTarget, vUv).xyz;
        gl_FragColor = vec4(base + splat, 1.0);
    }
`);

const advectionManualFilteringShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    uniform sampler2D uVelocity;
    uniform sampler2D uSource;
    uniform vec2 texelSize;
    uniform float dt;
    uniform float dissipation;

    vec4 bilerp (in sampler2D sam, in vec2 p) {
        vec4 st;
        st.xy = floor(p - 0.5) + 0.5;
        st.zw = st.xy + 1.0;
        vec4 uv = st * texelSize.xyxy;
        vec4 a = texture2D(sam, uv.xy);
        vec4 b = texture2D(sam, uv.zy);
        vec4 c = texture2D(sam, uv.xw);
        vec4 d = texture2D(sam, uv.zw);
        vec2 f = p - st.xy;
        return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
    }

    void main () {
        vec2 coord = gl_FragCoord.xy - dt * texture2D(uVelocity, vUv).xy;
        gl_FragColor = dissipation * bilerp(uSource, coord);
        gl_FragColor.a = 1.0;
    }
`);

const advectionShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    uniform sampler2D uVelocity;
    uniform sampler2D uSource;
    uniform vec2 texelSize;
    uniform float dt;
    uniform float dissipation;

    void main () {
        vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
        gl_FragColor = dissipation * texture2D(uSource, coord);
        gl_FragColor.a = 1.0;
    }
`);

const divergenceShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    varying vec2 vL;
    varying vec2 vR;
    varying vec2 vT;
    varying vec2 vB;
    uniform sampler2D uVelocity;

    vec2 sampleVelocity (in vec2 uv) {
        vec2 multiplier = vec2(1.0, 1.0);
        if (uv.x < 0.0) { uv.x = 0.0; multiplier.x = -1.0; }
        if (uv.x > 1.0) { uv.x = 1.0; multiplier.x = -1.0; }
        if (uv.y < 0.0) { uv.y = 0.0; multiplier.y = -1.0; }
        if (uv.y > 1.0) { uv.y = 1.0; multiplier.y = -1.0; }
        return multiplier * texture2D(uVelocity, uv).xy;
    }

    void main () {
        float L = sampleVelocity(vL).x;
        float R = sampleVelocity(vR).x;
        float T = sampleVelocity(vT).y;
        float B = sampleVelocity(vB).y;
        float div = 0.5 * (R - L + T - B);
        gl_FragColor = vec4(div, 0.0, 0.0, 1.0);
    }
`);

const curlShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    varying vec2 vL;
    varying vec2 vR;
    varying vec2 vT;
    varying vec2 vB;
    uniform sampler2D uVelocity;

    void main () {
        float L = texture2D(uVelocity, vL).y;
        float R = texture2D(uVelocity, vR).y;
        float T = texture2D(uVelocity, vT).x;
        float B = texture2D(uVelocity, vB).x;
        float vorticity = R - L - T + B;
        gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0);
    }
`);

const vorticityShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    varying vec2 vT;
    varying vec2 vB;
    uniform sampler2D uVelocity;
    uniform sampler2D uCurl;
    uniform float curl;
    uniform float dt;

    void main () {
        float T = texture2D(uCurl, vT).x;
        float B = texture2D(uCurl, vB).x;
        float C = texture2D(uCurl, vUv).x;
        vec2 force = vec2(abs(T) - abs(B), 0.0);
        force *= 1.0 / length(force + 0.00001) * curl * C;
        vec2 vel = texture2D(uVelocity, vUv).xy;
        gl_FragColor = vec4(vel + force * dt, 0.0, 1.0);
    }
`);

const pressureShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    varying vec2 vL;
    varying vec2 vR;
    varying vec2 vT;
    varying vec2 vB;
    uniform sampler2D uPressure;
    uniform sampler2D uDivergence;

    vec2 boundary (in vec2 uv) {
        uv = min(max(uv, 0.0), 1.0);
        return uv;
    }

    void main () {
        float L = texture2D(uPressure, boundary(vL)).x;
        float R = texture2D(uPressure, boundary(vR)).x;
        float T = texture2D(uPressure, boundary(vT)).x;
        float B = texture2D(uPressure, boundary(vB)).x;
        float C = texture2D(uPressure, vUv).x;
        float divergence = texture2D(uDivergence, vUv).x;
        float pressure = (L + R + B + T - divergence) * 0.25;
        gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);
    }
`);

const gradientSubtractShader = compileShader(gl.FRAGMENT_SHADER, `
    precision highp float;
    precision mediump sampler2D;

    varying vec2 vUv;
    varying vec2 vL;
    varying vec2 vR;
    varying vec2 vT;
    varying vec2 vB;
    uniform sampler2D uPressure;
    uniform sampler2D uVelocity;

    vec2 boundary (in vec2 uv) {
        uv = min(max(uv, 0.0), 1.0);
        return uv;
    }

    void main () {
        float L = texture2D(uPressure, boundary(vL)).x;
        float R = texture2D(uPressure, boundary(vR)).x;
        float T = texture2D(uPressure, boundary(vT)).x;
        float B = texture2D(uPressure, boundary(vB)).x;
        vec2 velocity = texture2D(uVelocity, vUv).xy;
        velocity.xy -= vec2(R - L, T - B);
        gl_FragColor = vec4(velocity, 0.0, 1.0);
    }
`);

let textureWidth;
let textureHeight;
let density;
let velocity;
let divergence;
let curl;
let pressure;
initFramebuffers();

const clearProgram = new GLProgram(baseVertexShader, clearShader);
const displayProgram = new GLProgram(baseVertexShader, displayShader);
const splatProgram = new GLProgram(baseVertexShader, splatShader);
const advectionProgram = new GLProgram(baseVertexShader, ext.supportLinearFiltering ? advectionShader : advectionManualFilteringShader);
const divergenceProgram = new GLProgram(baseVertexShader, divergenceShader);
const curlProgram = new GLProgram(baseVertexShader, curlShader);
const vorticityProgram = new GLProgram(baseVertexShader, vorticityShader);
const pressureProgram = new GLProgram(baseVertexShader, pressureShader);
const gradienSubtractProgram = new GLProgram(baseVertexShader, gradientSubtractShader);

function initFramebuffers() {
  textureWidth = gl.drawingBufferWidth >> config.TEXTURE_DOWNSAMPLE;
  textureHeight = gl.drawingBufferHeight >> config.TEXTURE_DOWNSAMPLE;

  const texType = ext.halfFloatTexType;
  const rgba = ext.formatRGBA;
  const rg = ext.formatRG;
  const r = ext.formatR;

  density = createDoubleFBO(2, textureWidth, textureHeight, rgba.internalFormat, rgba.format, texType, ext.supportLinearFiltering ? gl.LINEAR : gl.NEAREST);
  velocity = createDoubleFBO(0, textureWidth, textureHeight, rg.internalFormat, rg.format, texType, ext.supportLinearFiltering ? gl.LINEAR : gl.NEAREST);
  divergence = createFBO(4, textureWidth, textureHeight, r.internalFormat, r.format, texType, gl.NEAREST);
  curl = createFBO(5, textureWidth, textureHeight, r.internalFormat, r.format, texType, gl.NEAREST);
  pressure = createDoubleFBO(6, textureWidth, textureHeight, r.internalFormat, r.format, texType, gl.NEAREST);
}

function createFBO(texId, w, h, internalFormat, format, type, param) {
  gl.activeTexture(gl.TEXTURE0 + texId);
  let texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, param);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, param);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, null);

  let fbo = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
  gl.viewport(0, 0, w, h);
  gl.clear(gl.COLOR_BUFFER_BIT);

  return [texture, fbo, texId];
}

function createDoubleFBO(texId, w, h, internalFormat, format, type, param) {
  let fbo1 = createFBO(texId, w, h, internalFormat, format, type, param);
  let fbo2 = createFBO(texId + 1, w, h, internalFormat, format, type, param);

  return {
    get read() {
      return fbo1;
    },
    get write() {
      return fbo2;
    },
    swap() {
      let temp = fbo1;
      fbo1 = fbo2;
      fbo2 = temp;
    } };

}

const blit = (() => {
  gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]), gl.STATIC_DRAW);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW);
  gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(0);

  return destination => {
    gl.bindFramebuffer(gl.FRAMEBUFFER, destination);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
  };
})();

let lastTime = Date.now();
multipleSplats(parseInt(Math.random() * 20) + 5);
update();

function update() {
  resizeCanvas();

  const dt = Math.min((Date.now() - lastTime) / 1000, 0.016);
  lastTime = Date.now();

  gl.viewport(0, 0, textureWidth, textureHeight);

  if (splatStack.length > 0)
  multipleSplats(splatStack.pop());

  advectionProgram.bind();
  gl.uniform2f(advectionProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
  gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.read[2]);
  gl.uniform1i(advectionProgram.uniforms.uSource, velocity.read[2]);
  gl.uniform1f(advectionProgram.uniforms.dt, dt);
  gl.uniform1f(advectionProgram.uniforms.dissipation, config.VELOCITY_DISSIPATION);
  blit(velocity.write[1]);
  velocity.swap();

  gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.read[2]);
  gl.uniform1i(advectionProgram.uniforms.uSource, density.read[2]);
  gl.uniform1f(advectionProgram.uniforms.dissipation, config.DENSITY_DISSIPATION);
  blit(density.write[1]);
  density.swap();

  for (let i = 0; i < pointers.length; i++) {
    const pointer = pointers[i];
    if (pointer.moved) {
      splat(pointer.x, pointer.y, pointer.dx, pointer.dy, pointer.color);
      pointer.moved = false;
    }
  }

  curlProgram.bind();
  gl.uniform2f(curlProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
  gl.uniform1i(curlProgram.uniforms.uVelocity, velocity.read[2]);
  blit(curl[1]);

  vorticityProgram.bind();
  gl.uniform2f(vorticityProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
  gl.uniform1i(vorticityProgram.uniforms.uVelocity, velocity.read[2]);
  gl.uniform1i(vorticityProgram.uniforms.uCurl, curl[2]);
  gl.uniform1f(vorticityProgram.uniforms.curl, config.CURL);
  gl.uniform1f(vorticityProgram.uniforms.dt, dt);
  blit(velocity.write[1]);
  velocity.swap();

  divergenceProgram.bind();
  gl.uniform2f(divergenceProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
  gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.read[2]);
  blit(divergence[1]);

  clearProgram.bind();
  let pressureTexId = pressure.read[2];
  gl.activeTexture(gl.TEXTURE0 + pressureTexId);
  gl.bindTexture(gl.TEXTURE_2D, pressure.read[0]);
  gl.uniform1i(clearProgram.uniforms.uTexture, pressureTexId);
  gl.uniform1f(clearProgram.uniforms.value, config.PRESSURE_DISSIPATION);
  blit(pressure.write[1]);
  pressure.swap();

  pressureProgram.bind();
  gl.uniform2f(pressureProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
  gl.uniform1i(pressureProgram.uniforms.uDivergence, divergence[2]);
  pressureTexId = pressure.read[2];
  gl.uniform1i(pressureProgram.uniforms.uPressure, pressureTexId);
  gl.activeTexture(gl.TEXTURE0 + pressureTexId);
  for (let i = 0; i < config.PRESSURE_ITERATIONS; i++) {
    gl.bindTexture(gl.TEXTURE_2D, pressure.read[0]);
    blit(pressure.write[1]);
    pressure.swap();
  }

  gradienSubtractProgram.bind();
  gl.uniform2f(gradienSubtractProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
  gl.uniform1i(gradienSubtractProgram.uniforms.uPressure, pressure.read[2]);
  gl.uniform1i(gradienSubtractProgram.uniforms.uVelocity, velocity.read[2]);
  blit(velocity.write[1]);
  velocity.swap();

  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  displayProgram.bind();
  gl.uniform1i(displayProgram.uniforms.uTexture, density.read[2]);
  blit(null);

  requestAnimationFrame(update);
}

function splat(x, y, dx, dy, color) {
  splatProgram.bind();
  gl.uniform1i(splatProgram.uniforms.uTarget, velocity.read[2]);
  gl.uniform1f(splatProgram.uniforms.aspectRatio, canvas.width / canvas.height);
  gl.uniform2f(splatProgram.uniforms.point, x / canvas.width, 1.0 - y / canvas.height);
  gl.uniform3f(splatProgram.uniforms.color, dx, -dy, 1.0);
  gl.uniform1f(splatProgram.uniforms.radius, config.SPLAT_RADIUS);
  blit(velocity.write[1]);
  velocity.swap();

  gl.uniform1i(splatProgram.uniforms.uTarget, density.read[2]);
  gl.uniform3f(splatProgram.uniforms.color, color[0] * 0.3, color[1] * 0.3, color[2] * 0.3);
  blit(density.write[1]);
  density.swap();
}

function multipleSplats(amount) {
  for (let i = 0; i < amount; i++) {
    const color = [Math.random() * 10, Math.random() * 10, Math.random() * 10];
    const x = canvas.width * Math.random();
    const y = canvas.height * Math.random();
    const dx = 1000 * (Math.random() - 0.5);
    const dy = 1000 * (Math.random() - 0.5);
    splat(x, y, dx, dy, color);
  }
}

function resizeCanvas() {
  if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight) {
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    initFramebuffers();
  }
}

canvas.addEventListener('mousemove', e => {
  pointers[0].moved = pointers[0].down;
  pointers[0].dx = (e.offsetX - pointers[0].x) * 10.0;
  pointers[0].dy = (e.offsetY - pointers[0].y) * 10.0;
  pointers[0].x = e.offsetX;
  pointers[0].y = e.offsetY;
});

canvas.addEventListener('touchmove', e => {
  e.preventDefault();
  const touches = e.targetTouches;
  for (let i = 0; i < touches.length; i++) {
    let pointer = pointers[i];
    pointer.moved = pointer.down;
    pointer.dx = (touches[i].pageX - pointer.x) * 10.0;
    pointer.dy = (touches[i].pageY - pointer.y) * 10.0;
    pointer.x = touches[i].pageX;
    pointer.y = touches[i].pageY;
  }
}, false);

canvas.addEventListener('mousemove', () => {
  pointers[0].down = true;
  pointers[0].color = [Math.random() + 0.2, Math.random() + 0.2, Math.random() + 0.2];
});

canvas.addEventListener('touchstart', e => {
  e.preventDefault();
  const touches = e.targetTouches;
  for (let i = 0; i < touches.length; i++) {
    if (i >= pointers.length)
    pointers.push(new pointerPrototype());

    pointers[i].id = touches[i].identifier;
    pointers[i].down = true;
    pointers[i].x = touches[i].pageX;
    pointers[i].y = touches[i].pageY;
    pointers[i].color = [Math.random() + 0.2, Math.random() + 0.2, Math.random() + 0.2];
  }
});

window.addEventListener('mouseleave', () => {
  pointers[0].down = false;
});

window.addEventListener('touchend', e => {
  const touches = e.changedTouches;
  for (let i = 0; i < touches.length; i++)
  for (let j = 0; j < pointers.length; j++)
  if (touches[i].identifier == pointers[j].id)
  pointers[j].down = false;
});
</script>

<section id='container'>
  <h1 class='a-title'>Move the mouse</h1>
  <h2 class='a-second-title'>See the magic</h2>
  <canvas></canvas>
</section>

[/html]

+2

180

Аватар в строке приветствия + код юзер-панели с аватаркой и сменой аватара по клику

Код:
<!-- Аватарка в строке приветствия плюс смена аватара по клику-->
<script>$('#pun-status>p').prepend('<div id="u-ava"></div>')</script>
<script type="text/javascript">
if (UserAvatar == ""){UserAvatar = "https://i.imgur.com/S1lii2p.png"}
var arr=document.getElementsByTagName("div")
i=0
while(arr[i] ){
if(arr[i].id=="u-ava") {
name=arr[i].innerHTML
name=name.substring(0)
arr[i].innerHTML="<a href='/profile.php?section=avatar&id="+UserID+"' title='Изменить аватар'><img style='width: 45px; height: auto; vertical-align: middle; border-radius: 5%;    margin: -1.6em -50px;  float: inline-end; border: 2px solid #a29c99;' src="+UserAvatar+"></a>"+name
}
if(arr[i].id=="u-ava" && GroupID == "3") {
arr[i].innerHTML="<a href='/register.php'><img style='width: 45px; height: auto; vertical-align: middle; border-radius: 5%;    margin: -1.6em -50px;  float: inline-end; border: 2px solid #a29c99;' src='https://i.imgur.com/rn6keOU.png' title='Регистрация'></a>"+name
}
i++}
</script>

+3