CSS арқылы геометриялық 3D анимация жасап көрейік

Осыдан 3-4 күн бұрын VK-ны ақтарып отырым, лентадан бір әдемі анимация көріп, кейін канваста жасап көрмесем деп бөлісіп қойғанмын. Енді ойланып, осыны CSS-те жасап шығуді жөн көрдім. Бұл жазбам сол туралы болмақ.


Қолданған құралдарым
  • Браузер: Хром
  • Мәтіндік редактор: Sublime Text 3
  • Редакторға қосымша ретінде Emmet және Emmet CSS
  • Препроцессор SASS, синтаксис SCSS

Алдымен бір штук кубты шығарып алайық, кейін соны цыкл арқылы көбейтіп, SCSS-те жазып шығамыз.

Кубтың HTML разметкасы
<section class="container"> <!-- сыртқы контейнер -->
	<div id="cube_1"> <!-- кубтың контейнері, төмендегі алты div кубтың алты жағы -->
		<div class="front"></div>
		<div class="back"></div>
		<div class="right"></div>
		<div class="left"></div>
		<div class="top"></div>
		<div class="bottom"></div>
	</div>
</section>


Кубтың (жалпы құжаттың негізгі) CSS разметкасы. ЕСКЕРТУ: код тым көп болып кетпес үшін, мында жазғанда CSS3 элементтерін вендорлы префикстерісіз жазып жатырмын, бірақ есіңізде болсын, ескі браузерлер түсінсін десеңіз барлық CSS3 «фишкаларға» префикстерді (-webkit-, -moz-, -ms-, -o-) қосып жазғаныңыз дұрыс болады.
body {
	background-color: #323232; /* фон түсі */
}
.container { /* сыртқы контейнердің разметкасы */
  width: 600px;
  height: 600px;
  position: relative;
  margin: 0 auto;
  margin-top: 80px;
}
#cube_1 {
  position: absolute;
  transform-style: preserve-3d; /* бұл элемент 3D кейістік ретінде қарастырыдады*/
  transform: rotateX(10deg) rotateY(20deg); /* блокты X осьінен 10, Y осьінен 20 градусқа бұрамыз */
  width: 20px;
  height: 20px;
  top: 300px;
  left: 300px;
}
#cube_1 div {
  margin: 0;
  position: absolute;
  width: 20px;
  height: 20px;
  box-shadow: inset 0 0 1px #fff;
}
/*төмендегі разметкада кубтың алты жағын позициялап, куб түріне әкелеміз*/
#cube_1 .front {transform: rotateY(0deg) translateZ(10px);}
#cube_1 .back {transform: rotateX(180deg) translateZ(10px);}
#cube_1 .right {transform: rotateY(90deg) translateZ(10px);}
#cube_1 .left {transform: rotateY(-90deg) translateZ(10px);}
#cube_1 .top {transform: rotateX(90deg) translateZ(10px);}
#cube_1 .bottom {transform: rotateX(-90deg) translateZ(10px);}

Ал енді не шыққанын көрейік

КЕРЕМЕТ!
Сізге куб екені көрінсін деп, X және Y осьтерін бұрып көрсеткен едім, енді X осьін 35.3 Y осьін 45 градусқа бұрып, төмендегідей нәтижеге аламыз.
#cube_1 {
  transform: rotateX(35.3deg) rotateY(45deg);
}

Нәтиже

ТАМАША!
Енді осы бір штук кубқа анимация жазайық
@keyframes first_anim { /* анимация аты */
	from {transform: rotateX(35.3deg) rotateY(45deg); /* анимация басталғанда X 35.3 Y 45 градусқа бұрылады */}
	to {transform: rotateX(35.3deg) rotateY(-135deg); /* анимация соңында X 35.3 Y -135 градусқа бұрылады */}
}
#cube_1 {
  animation-name: first_anim; /* жоғарыдағы анимацияны кубқа орнатамыз */
  animation-iteration-count: infinite; /* анимация шексіз болады */
  animation-duration: 6s; /* анимация ұзақтығы 6 секунд */
}

Нәтижесін көреміз

Болды. Бізде бір куб бар, және ол анимацияланып тұр. Енді осындай кубтың 30-40-ын жазып шығып, әрқайсысын позициялап, анимация басталу уақытын көрсету керек :) Қолмен жазатын болсақ күні бойы отыратынымыз анық. Бірақ бізде EMMET пен SASS бар, солардың көмегіне жүгінейік.

Алдымен HTML разметка. Төмендегі Emmet кодты орындаймыз да (бастапқы баптаулары бойынша Tab арқылы) 40 div#cube_* шығарамыз.
section.container>div#cube_$*40>.front+.back+.right+.left+.top+.bottom


Енді CSS-ке назар аударайық. Іііі, қалай түсіндірсем екен, қалай жазсам екен… видео ретінде жасауым керек еді, жарайды, алдымен айнымалыларды шығарып алайық.
$container_size: 600; /*сыртқы контейнердің көлемі*/
$cube_start_size: 14; /*ең кішкентай кубтың көлемі*/ 
$size_step: 10; /*келесі куб неше пиксельге үлкеюі керек*/
$cube_col: 40; /*кубтар саны*/

$anim_duration: 6; /*анимация ұзақтығы*/
$anim_delay: 2000; /*анимация неше мс кейін басталуы керек*/
$anim_delay_step: 100; /*келесі кубта неше мс кейін анимация басталуы керек*/

$rotateX_start: 35.3; /* бастапқы X осьі */ 
$rotateY_start: 45; /* бастапқы Y осьі */

$rotateX_end: 35.3; /* соңғы X осьі */
$rotateY_end: -135; /* соңғы Y осьі */


Енді CSS-те қайталанбайтын, бәріне ортақ разметкаларды тауып алып, бөлек жазайық.
body {
	background-color: #323232;
}
.container {
  width: $container_size+px;
  height: $container_size+px;
  position: relative;
  margin: 0 auto;
  margin-top: 100px;
}

[id^=cube] {
  position: absolute;
  transform-style: preserve-3d;
  transform: rotateX($rotateX_start+deg) rotateY($rotateY_start+deg);
  animation-name: first_anim;
  animation-iteration-count: infinite;
  animation-duration: $anim_duration+s;
}
[id^=cube] div {
  margin: 0;
  position: absolute;
  -webkit-box-shadow: inset 0 0 1px #000;
  box-shadow: inset 0 0 1px #fff;
}


Енді циклымыз.
@for $i from 1 through $cube_col {
	#cube_#{$i} {
	  width: $cube_start_size+px;
	  height: $cube_start_size+px;
	  top: $container_size/2+px;
	  left: $container_size/2+px;
	  animation-delay: $anim_delay+ms;
	}

	#cube_#{$i} div {
	  width: $cube_start_size+px;
	  height: $cube_start_size+px;
	}
	#cube_#{$i} .front {transform: rotateY(0deg) translateZ($cube_start_size/2+px);}
	#cube_#{$i} .back {transform: rotateX(180deg) translateZ( $cube_start_size/2+px);}
	#cube_#{$i} .right {transform: rotateY(90deg) translateZ($cube_start_size/2+px);}
	#cube_#{$i} .left {transform: rotateY(-90deg) translateZ($cube_start_size/2+px);}
	#cube_#{$i} .top {transform: rotateX(90deg) translateZ($cube_start_size/2+px);}
	#cube_#{$i} .bottom {transform: rotateX(-90deg) translateZ($cube_start_size/2+px);}
	$cube_start_size: $cube_start_size+$size_step; /*келесі куб көлемін $size_step-ға үлкейтеміз*/
	$container_size: $container_size - $size_step; /*позициясын жылжытып отыру үшін керек*/
	$anim_delay: $anim_delay+$anim_delay_step; /*келесі куб анимациясын $anim_delay_step-ға арттырамыз*/
}


Болып қалдық, енді анимациямызды қайтадан жазып шығайық
@keyframes first_anim {
	from {transform: rotateX($rotateX_start+deg) rotateY($rotateY_start+deg);}
	to {transform: rotateX($rotateX_end+deg) rotateY($rotateY_end+deg);}
}


Болды. Ал енді
НӘТИЖЕНІ КӨРЕЙІК!



$rotateX_start, $rotateY_start және $rotateX_end, $rotateY_end мәнедерін өзгерту арқылы (немесе кез-келген айнымалының мәндерін өзгерту арқылы) әртүрлі қызық нәтиже алуға болады. Мысалы, төмендегідей мәндері арқылы
$rotateX_start: 0; 
$rotateY_start: 0;

$rotateX_end: 360; 
$rotateY_end: 360


Анимация былай өзгереді


Немесе әр кубтың түстерін өзгертіп көруге болады.



Сау болыңыздар!

  • +2
5 пікір
kamyrov
Базар жоқ! Әдемі жасалған және әдемі жазылған!)
domalak
Анимацияларыңа жабысып қалдым. Керемет!
droidtar
Көп еңбектеніпсіз! Жарайсыз!
yerbol89
Мынаны қарап көр амиго :)

thomaspark.github.io/wonders/
Тек тіркелген қолданушылар ғана пікір қалдыра алады.