Создание вращающегося 3d-блока с помощью CSS transitions и Javascript

195
03 мая 2018, 05:47

Я экспериментировал с CSS, пытаясь создать 3d box, в котором можно выбрать передний план фигуры с помощью javascript.
Он просто меняет имя класса box divs и использует свойство transition для плавного перехода между разными местоположениями объекта.

Здесь ссылка на jsfiddle с работающим примером http://jsfiddle.net/synthet1c/VdDmA/1/

В настоящий момент это выглядит круто, но это не совсем так, как я хочу ...
Кто-нибудь знает, как я могу сохранять правильную позицию box , когда он проходит через transition?

В настоящее время, если face куба поворачивается от 360 градусов до 90 градусов, то face будет вращаться на 270 градусов в неправильном направлении. Я понимаю, почему так происходит, но не могу решить проблему.
Я добавил все префиксы браузеров, но использовал его только в Firefox.

var id = function(elem){ 
    var theId = document.getElementById(elem); 
    return theId; 
} 
 
function button1(){ 
    id('front').className = 'front'; 
    id('right').className = 'right'; 
    id('back').className = 'back'; 
    id('left').className = 'left'; 
} 
 
function button2(){ 
    id('front').className = 'right'; 
    id('right').className = 'back'; 
    id('back').className = 'left'; 
    id('left').className = 'front'; 
}    
 
function button3(){ 
    id('front').className = 'back'; 
    id('right').className = 'left'; 
    id('back').className = 'front'; 
    id('left').className = 'right'; 
}    
 
function button4(){ 
    id('front').className = 'left'; 
    id('right').className = 'front'; 
    id('back').className = 'right'; 
    id('left').className = 'back'; 
}   
.right{ 
    transform: rotateY(90deg) translatez(75px) translatex(-75px); 
    transition: all 4s; 
} 
 
.back{ 
    transform: rotateY(180deg) translatez(0px) translatex(0px); 
    transition: all 4s; 
} 
 
.left{ 
    transform: rotateY(270deg) translatez(75px) translatex(70px); 
    transition: all 4s; 
} 
 
.front{ 
    transform: rotateY(0deg) translatez(150px) translatex(0px); 
    transition: all 4s; 
}
<div class='buttons'> 
    <button class='btn'>Front</button> 
    <button class='btn'>Left</button> 
    <button class='btn'>Back</button> 
    <button class='btn'>Right</button> 
</div> 
<div class='house'> 
    <div class='face front'>Front</div> 
    <div class='face back'>Back</div> 
    <div class='face right'>Right</div> 
    <div class='face left'>Left</div> 
</div>

Answer 1

Pure CSS

Кроме того, вы можете делать вращающийся 3D-блок с чистым CSS. Тем не менее, проблема вращения> 180 ° может быть решена только с помощью JavaScript.

body { padding: 5em 0 0; perspective: 45em; } 
.faceopt { 
	position: absolute; 
	visibility: hidden; 
	z-index: -1; 
} 
.faceopt + label { 
	display: inline-block; 
	padding: .25em 1em; 
	border-radius: .5em; 
	box-shadow: 0 1px 0 black, 0 -1px 0 #96d1f8; 
	background: #65a9d7 linear-gradient(top, #3e779d, #65a9d7); 
	color: white; 
	font: 1em Century Gothic, Verdana, sans-serif; 
	text-shadow: 0 1px 0 black; 
	transition: .5s; 
	cursor: pointer; 
} 
.faceopt + label:hover, .faceopt:checked + label { color: yellow; } 
.house { 
	margin: 5em auto; 
	transform-style: preserve-3d; 
	transition: transform 1s; 
} 
.house, .face { width: 10em; height: 10em; } 
.face { 
	box-sizing: border-box; 
	position: absolute; 
	padding: 1em; 
} 
.front { transform: translateZ(5em); background: rgba(255, 165, 0, .75); } 
.back {  
	transform: rotateY(180deg) translateZ(5em); 
	background: rgba(30, 144, 255, .75); 
} 
.right { 
	transform: rotateY(90deg) translateZ(5em); 
	background: rgba(220, 20, 60, .75); 
} 
.left { 
	transform: rotateY(-90deg) translateZ(5em); 
	background: rgba(127, 255, 0, .75); 
} 
#left:checked ~ .house { transform: rotateY(90deg); } 
#back:checked ~ .house { transform: rotateY(180deg); } 
#right:checked ~ .house { transform: rotateY(-90deg); }
<input type='radio' name='faceopt' id='front' class='faceopt' checked> 
<label for='front'>Front</label> 
<input type='radio' name='faceopt' id='left' class='faceopt'> 
<label for='left'>Left</label> 
<input type='radio' name='faceopt' id='back' class='faceopt'> 
<label for='back'>Back</label> 
<input type='radio' name='faceopt' id='right' class='faceopt'> 
<label for='right'>Right</label> 
<div class='house'> 
	<div class='face front'>Front</div> 
	<div class='face back'>Back</div> 
	<div class='face right'>Right</div> 
	<div class='face left'>Left</div> 
</div>

Answer 2

На самом деле это довольно просто.

Вам просто нужно сделать проверку, чтобы узнать, будет ли разница, назовем ее dif, по абсолютной величине между углом, в котором вы сейчас находитесь, и углом, который вы хотите получить,- более 180°, и если это так, то вы поворачиваете на 360°, минус разность по абсолютной величине. Направление вращения определяется знаком dif.

Я также внес некоторые изменения в CSS, и если вы хотите больше узнать о том, как создать реалистичный куб, вы можете изучить мой (действительно) подробный ответ на аналогичный вопрос.

(function() { 
	var btnsEl = document.querySelector('.buttons'), currentAngle = 0; 
	btnsEl.addEventListener('click', function(e) { 
		var b = e.target.innerHTML.toLowerCase(),  
			house = document.querySelector('.house'),  
			btns = {'front': 0, 'left': 90, 'back': 180, 'right': -90},  
			dif = btns[b] - currentAngle%360; 
		if(!e.target.classList.contains('btn') || dif === 0) return; 
		currentAngle += (Math.abs(dif) > 180) ?  
						(Math.abs(dif) - 360)*Math.abs(dif)/dif :  
						dif; 
		house.style['-webkit-transform'] = 'rotateY(' + currentAngle + 'deg)'; 
		house.style['transform'] = 'rotateY(' + currentAngle + 'deg)'; 
	}, false);  
}());
body { padding: 5em 0 0; perspective: 45em; } 
button { cursor: pointer; } 
.house {  
	position: relative; 
	margin: 2em auto; 
	transform-style: preserve-3d; 
	transition: transform 1s; 
} 
.house, .face { width: 10em; height: 10em; } 
.face { 
	box-sizing: border-box; 
	position: absolute; 
	padding: 1em; 
} 
.front { transform: translateZ(5em); background: rgba(255, 165, 0, .75); } 
.back {  
	transform: rotateY(180deg) translateZ(5em); 
	background: rgba(30, 144, 255, .75); 
} 
.right { 
	transform: rotateY(90deg) translateZ(5em); 
	background: rgba(220, 20, 60, .75); 
} 
.left { 
	transform: rotateY(-90deg) translateZ(5em); 
	background: rgba(127, 255, 0, .75); 
}
<div class='buttons'> 
    <button class='btn'>Front</button> 
    <button class='btn'>Left</button> 
    <button class='btn'>Back</button> 
    <button class='btn'>Right</button> 
</div> 
<div class='house'> 
    <div class='face front'>Front</div> 
    <div class='face back'>Back</div> 
    <div class='face right'>Right</div> 
    <div class='face left'>Left</div> 
</div>

demo

READ ALSO
Как поменять тему в Sublime Text 3?

Как поменять тему в Sublime Text 3?

Как поменять тему в Sublime Text 3 ? А то уже глаза кровью наливаются от розового текста HTML-документа :(

170
2 обработчика для одной формы

2 обработчика для одной формы

Доброй ночи, есть форма от Яндекс кассы

182
Не работает auto-fill в Grid

Не работает auto-fill в Grid

Не работает свойство:

158