Xiper

Поворот объекта вокруг свой

Автор: Евгений Рыжков Дата публикации:

Поворот плоского объекта

Для демонстрации перевернем игральную карту.

<div class="container" id="container">
<div id="card">
	<figure class="back"></figure>
	<figure class="front"></figure>
</div>
</div>
.container {
	margin: 100px auto auto 100px;
	position: relative;
	width: 190px;
	height: 266px;
	/* задаем глубину сцене */
	-webkit-perspective: 600px; /* webkit */
	-moz-perspective: 600px; /* mozilla */
	-ms-perspective: 600px; /* IE 10 */
	-o-perspective: 600px; /* opera когда-то тоже должна начать понимать */
	perspective: 600px;	/* св-во по стандартам */
}
#card { /* поворачивать будем общий контейнер */
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	position: absolute;
	-webkit-transition: -webkit-transform 0.5s;
	-moz-transition: -moz-transform 0.5s;
	-ms-transition: -moz-transform 0.5s;
	-o-transition: -o-transform 0.5s;
	transition: transform 0.5s; /* трансформации будут происходить анимированно продолжительностью 0.5 сек */
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	-ms-transform-style: preserve-3d;
	-o-transform-style: preserve-3d;
	transform-style: preserve-3d;	/* указываем, что дочерние элементы находятся в 3D пространстве */
}
#card.flip {	/* добавляя этот класс, поворачиваем контейнер на 180 градусов */
	-webkit-transform: rotateY( 180deg );
	-moz-transform: rotateY( 180deg );
	-ms-transform: rotateY( 180deg );
	-o-transform: rotateY( 180deg );
	transform: rotateY( 180deg );
}
figure {
	width: 100%;
	height: 100%;
	position: absolute;
	display: block;
	-webkit-backface-visibility: hidden;
	-moz-backface-visibility: hidden;
	-ms-backface-visibility: hidden;
	-o-backface-visibility: hidden;
	backface-visibility: hidden;	/* если элемент "отвернулся" от пользователя, контент этого элемента не виден */
}
.back {
	background: url(card-back.png);
}
.front {
	background: url(card-front.png);
	-webkit-transform: rotateY( 180deg );
	-moz-transform: rotateY( 180deg );
	-ms-transform: rotateY(180deg);
	-o-transform: rotateY( 180deg );
	transform: rotateY( 180deg );	/* в начальном положении фэйс карты к нам развернут на 180 градусов */
}

Чтобы запустить анимацию достаточно контейнеру card добавить класс flip. Демо.

Поворот объемного объекта

Для этого добавляем объекту глубины и грани. В качестве примера повернем книгу.

<div class="container" id="container">
<div id="book">
	<figure class="back"></figure>
	<figure class="front"></figure>
	<figure class="left-1"></figure>
	<figure class="left-2"></figure>
	<figure class="right"></figure>
</div>
</div>

left-1 и left-2 — это одна грань книги. Разбита на две части чтобы придать торцу книги выпуклости (для большей реалистичности нужно большее число составляющих грани).

.container {
	margin: 100px auto auto 100px;
	position: relative;
	width: 226px;
	height: 316px;
	/* задаем глубину сцене */
	-webkit-perspective: 600px; /* webkit */
	-moz-perspective: 600px; /* mozilla */
	-ms-perspective: 600px; /* IE 10 */
	-o-perspective: 600px; /* opera когда-то тоже должна начать понимать */
	perspective: 600px;	/* св-во по стандартам */
}
#book { /* поварачивать будет общий контейнер */
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	position: absolute;
	-webkit-transition: -webkit-transform 1.5s;
	-moz-transition: -moz-transform 1.5s;
	-ms-transition: -moz-transform 1.5s;
	-o-transition: -o-transform 1.5s;
	transition: transform 1.5s; /* трансформации будут происходить анимированно продолжительностью 0.5 сек */
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	-ms-transform-style: preserve-3d;
	-o-transform-style: preserve-3d;
	transform-style: preserve-3d;	/* указываем, что дочерние элементы находятся в 3D пространстве */
}
#book.flip {	/* добавляя этот класс, поворачиваем контейнер на 180 градусов */
	-webkit-transform: rotateY( 180deg );
	-moz-transform: rotateY( 180deg );
	-ms-transform: rotateY( 180deg );
	-o-transform: rotateY( 180deg );
	transform: rotateY( 180deg );
}
figure {
	position: absolute;
	display: block;
	-webkit-backface-visibility: hidden;
	-moz-backface-visibility: hidden;
	-ms-backface-visibility: hidden;
	-o-backface-visibility: hidden;
	backface-visibility: hidden;	/* если элемент отвернут лицом от пользователя, контент этого элемента не виден */
}
.back, .front, .left-1, .left-2, .right {
	background: url(book-texture.jpg);
}
.front {
	width: 100%;
	height: 100%;
	background-position: -276px 0;
	-webkit-transform: rotateY( 0deg ) translateZ(  25px );
	-moz-transform: rotateY( 0deg ) translateZ(  25px );
	-ms-transform: rotateY(0deg) translateZ(  25px );
	-o-transform: rotateY( 0deg ) translateZ(  25px );
	transform: rotateY( 0deg ) translateZ(  25px );
	/* 
		rotateY - поворачиваем грань на нужный угол
		translateZ - т.к. объект имеет толщину
	*/
}
.back {
	width: 100%;
	height: 100%;
	-webkit-transform: rotateY( 180deg ) translateZ(  25px );
	-moz-transform: rotateY( 180deg ) translateZ(  25px );
	-ms-transform: rotateY(180deg) translateZ(  25px );
	-o-transform: rotateY( 180deg ) translateZ(  25px );
	transform: rotateY( 180deg ) translateZ(  25px );	/* в начальном положении фэйс карты к нам развернут на 180 градусов */
}
/*
	придаем выпуклости торцу 
	разбиваем его на две части и ставим их под небольшим углом друг к другу
*/
.left-1 {
	background-position: -250px 0;
	width: 28.5px;
			/*
				тут я немного схалтурил. реально размер половины грани равен 25px и при этом значении оставалась дырка между гранями
				в этом примере не стал пересчитывать толщину книги с учетом потерь из-за "выпуклости" торца
		 */
	height: 100%;
	-webkit-transform: rotateY( -70deg ) translate3d(-3px, 0, 8px );
	-moz-transform: rotateY( -70deg ) translate3d(-3px, 0, 8px );
	-ms-transform: rotateY(-70deg) translate3d( -3px, 0, 8px );
	-o-transform: rotateY( -70deg ) translate3d( -3px, 0, 8px );
	transform: rotateY( -70deg ) translate3d( -3px, 0, 8px ); /*
																															 8 получаем из решения прямоугольного треугольника (по известному углу и гипотенузе вычисляем катет) online решить можно тут
																															 -3 - костыль, подобранный в ручную для этого примера
																														*/
	-webkit-transform-origin: left center;
	-moz-transform-origin: left center;
	-ms-transform-origin: left center;
	-o-transform-origin: left center;
	transform-origin: left center; /* поворачиваю торцы вокруг их левой границы: так проще потом расположить элемент (в данном случае) */
}
.left-2 {
	background-position: -225px 0;
	width: 28px;
	height: 100%;
	-webkit-transform: rotateY( -110deg ) translate3d( -24.5px, 0, 8px );
	-moz-transform: rotateY( -110deg ) translate3d(  -24.5px, 0, 8px );
	-ms-transform: rotateY(-110deg) translate3d( -24.5px, 0, 8px );
	-o-transform: rotateY( -110deg ) translate3d( -24.5px, 0, 8px );
	transform: rotateY( -110deg ) translate3d( -24.5px, 0, 8px ); /*24.5 - тоже из решения прямоугольного треугольника - второй катет */
	-webkit-transform-origin: left center;
	-moz-transform-origin: left center;
	-ms-transform-origin: left center;
	-o-transform-origin: left center;
	transform-origin: left center;
}
.right {
	background-position: -276px 0;
	width: 50px;
	height: 100%;
	-webkit-transform: rotateY( 90deg );
	-moz-transform: rotateY( 90deg );
	-ms-transform: rotateY(90deg);
	-o-transform: rotateY( 90deg );
	transform: rotateY( 90deg );
	top: 0;
	right: 	0;
}

Демо.

На момент написания заметки поддержка:

  • IE 10
  • Firefox
  • Safari
  • Chrome
  • iOs Safari
  • Android