Reputation: 722
I'm using transform: rotate();
to rotate content in & out of view, however, each body of text is at a different position when it comes into view. So when you click the next button on my demo if you look at the border the contents are in different positions.
When the next button is clicked the wheel rotates equally 90 degrees so I expect the content to be in the same position on each rotation. Could someone explain/resolve why this doesn't happen?
I created a wheel for my content and I styled the wheel to hide options no currently visible;
// Page load transform start, setters
var degree = 0;
var itemStart = $('.wheel').find('.item-one').addClass('item-active');
var itemNext = $('.wheel').find('.item-four').addClass('item-prev');
// On click
$('.next').click(function() {
var wheel = $('.wheel');
// Increment rotation
degree += 90;
wheel.css({
WebkitTransform: 'rotate(' + degree + 'deg)'
});
// Update setter
itemStart = $('.wheel').find('.item-active');
itemNext = $('.wheel').find('.item-prev');
// Add Animation
$(itemStart).addClass('fadeOut');
$(itemNext).addClass('fadeIn');
//If were at the end
var getStartPrev = $(itemStart).prev();
var getNextPrev = $(itemNext).prev();
if (getStartPrev.length == 0) {
$(itemStart).removeClass('item-active');
$(itemNext).prev().addClass('item-prev');
$('.item-four').addClass('item-active').removeClass('item-prev');
} else {
$(itemStart).removeClass('item-active');
$(itemNext).removeClass('item-prev').addClass('item-active');
$(itemNext).prev().addClass('item-prev');
}
if (getNextPrev.length == 0) {
$('.item-four').addClass('item-prev');
}
// Remove Animation
setTimeout(function() {
$('.wheel').find('.item').removeClass('fadeIn fadeOut');
}, 400);
});
.wheel-wrp {
position: relative;
height: 700px;
width: 700px;
}
.wheel {
height: 700px;
width: 700px;
transition: 0.75s;
border-radius: 50%;
position: relative;
background: #fff;
left: -350px;
}
.item {
width: 250px;
position: absolute;
opacity: 0;
}
.item-active {
opacity: 1;
}
.item-one {
bottom: 300px;
left: 450px;
}
.item-two {
bottom: 20px;
left: 230px;
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
transform: rotate(90deg);
}
.item-three {
bottom: 320px;
left: 0px;
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
transform: rotate(180deg);
}
.item-four {
top: 20px;
left: 230px;
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
transform: rotate(270deg);
}
.current-item {
bottom: 300px;
left: 450px;
}
.next-item {
top: 20px;
left: 230px;
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
transform: rotate(-90deg);
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
<div class="wheel-wrp">
<div class="wheel">
<div class="item item-one">
<h4>Project 1 - beautifully crafted digital brand</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item item-two">
<h4>Project 2 - redefining technological boundaries</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item item-three">
<h4>Project 3 - Beauty in Design</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item item-four">
<h4>Project 4 - simply stunning </h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
</div>
</div>
</div>
<div class="next">Next</div>
Example demo - https://codepen.io/SamXronn/pen/opqWbq
Upvotes: 6
Views: 707
Reputation: 26370
Here's my go at it.
I have set the items's transform origin to top left (the same point used for positioning)
Using transform translateY
and translateX
, each item can then be placed against the wheel, regardless of their width and height
You don't need jQuery for animation. Just use it to toggle the active class. The same result is achieved much more smoothly and with much less code with CSS3 animation and an "active" class.
let currentItem = 0
const $wheel = $('.wheel'),
$items = $wheel.find(".item")
$('.next').click(() => rotate(1));
$('.prev').click(() => rotate(-1));
const rotate = direction => {
currentItem -= direction
$wheel.css("transform",`rotate(${-currentItem*90}deg)`)
$items.removeClass("active")
.eq(currentItem%$items.length)
.addClass("active")
}
body {
background-color: #2c3e50;
}
button {
background: #2980b9;
padding: 15px 35px;
color: #fff;
float: left;
position: relative;
z-index: 9999;
cursor: pointer;
}
.wheel {
height: 700px;
width: 700px;
transition: transform 0.75s;
border-radius: 50%;
position: relative;
background: #fff;
}
.item {
width: 250px;
position: absolute;
opacity: 0.2;
transition: opacity 0.75s;
border: 1px solid #f00;
transform-origin: top left;
}
.item:nth-child(1) {
top: 50%;
left: 100%;
transform: translateY(-50%) translateX(-100%);
}
.item:nth-child(2) {
top: 100%;
left: 50%;
transform: rotate(90deg) translateY(-50%) translateX(-100%);
}
.item:nth-child(3) {
left: 0;
top: 50%;
transform: rotate(180deg) translateY(-50%) translateX(-100%);
}
.item:nth-child(4) {
top: 0;
left: 50%;
transform: rotate(270deg) translateY(-50%) translateX(-100%);
}
.item.active {
opacity: 1;
}
h4 {
margin: 0px 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="page">
<div class="wheel">
<div class="item active">
<h4>Project 1 - beautifully crafted digital brand</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item">
<h4>Project 2 - redefining technological boundaries</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item">
<h4>Project 3 - Beauty in Design</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item">
<h4>Project 4 - simply stunning </h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
</div>
</div>
<button class="prev">Prev</button>
<button class="next">Next</button>
Upvotes: 3
Reputation: 15616
And this is my tryout :) I removed the item-one two..
classes and used css nth-child
selectors, and prepared the initial wheel layout first with CSS using transform-origin
to center of the circle, and then rotated the wheel itself. The returning to initial position was tricky because it animated şn reverse direction when rotating from 270deg's to 0deg. So I added an extra class to instantly move to initial position without animating.
$(".next").on("click", function () {
var wheel = $(".wheel");
if (wheel.hasClass("rotate-1")) {
wheel.removeClass("rotate-1").addClass("rotate-2");
}
else if (wheel.hasClass("rotate-2")) {
wheel.removeClass("rotate-2").addClass("rotate-3");
}
else if (wheel.hasClass("rotate-3")) {
wheel.removeClass("rotate-3").addClass("rotate-4");
}
else if (wheel.hasClass("rotate-4")) {
wheel.removeClass("rotate-4").addClass("rotate-5").delay(1000).queue(function (next) {
$(this).addClass("rotate-1");
$(this).removeClass("rotate-5");
next();
});
}
});
.wheel {
border-radius: 50%;
background: rebeccapurple;
width: 700px;
height: 700px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
transition: all 1s ease;
margin-left : -350px;
}
.item {
background:transparent;
color: white;
width: 250px;
margin-right: 10px;
margin-left: calc(50% - 135px);
position: absolute;
transform-origin: calc(-50% + 35px) 50%;
transition: all 1s ease;
}
.wheel.rotate-1 {
transform: rotateZ(0deg);
transition: all 0s ease;
}
.wheel.rotate-2 {
transform: rotateZ(90deg);
}
.wheel.rotate-3 {
transform: rotateZ(180deg);
}
.wheel.rotate-4 {
transform: rotateZ(270deg);
}
.wheel.rotate-5 {
transform: rotateZ(360deg);
}
.item:nth-child(1) {
transform: rotateZ(0deg);
}
.item:nth-child(2) {
transform: rotateZ(-90deg);
}
.item:nth-child(3) {
transform: rotateZ(-180deg);
}
.item:nth-child(4) {
transform: rotateZ(-270deg);
}
.wheel.rotate-1 .item {
opacity: 0;
}
.wheel.rotate-1 .item:nth-child(1) {
opacity: 1;
}
.wheel.rotate-2 .item {
opacity: 0;
}
.wheel.rotate-2 .item:nth-child(2) {
opacity: 1;
}
.wheel.rotate-3 .item {
opacity: 0;
}
.wheel.rotate-3 .item:nth-child(3) {
opacity: 1;
}
.wheel.rotate-4 .item {
opacity: 0;
}
.wheel.rotate-4 .item:nth-child(4) {
opacity: 1;
}
.wheel.rotate-5 .item {
opacity: 0;
}
.wheel.rotate-5 .item:nth-child(1) {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
<div class="wheel-wrp">
<div class="wheel rotate-1">
<div class="item">
<h4>Project 1 - beautifully crafted digital brand</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum..
</p>
</div>
<div class="item">
<h4>Project 2 - redefining technological boundaries</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum..
</p>
</div>
<div class="item">
<h4>Project 3 - Beauty in Design</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum..
</p>
</div>
<div class="item">
<h4>Project 4 - simply stunning </h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum..
</p>
</div>
</div>
</div>
</div>
<div class="next">Next</div>
Upvotes: 1
Reputation: 3913
Quite a challenging one. The issue is a combination of vertical centering for your divs have different heights, and your absolute positioning with px. And the transform rotates, of course
I've came out with a solution using the typical top:50; transform:-50%
vertical centering hack, adapted to the different div rotations.
That takes care of the vertical alignment by totally predictible and calculated values. Horizontal alignment on the other hand is proving to be trickier, maybe I'm missing something here, but I've come up with a solution for those by means of magical numbers (% that work, although I'm not sure why)... Anyway, here's the snippet
// Page load transform start, setters
var degree = 0;
var itemStart = $('.wheel').find('.item-one').addClass('item-active');
var itemNext = $('.wheel').find('.item-four').addClass('item-prev');
// On click
$('.next').click( function() {
var wheel = $('.wheel');
// Increment rotation
degree += 90;
wheel.css({ WebkitTransform: 'rotate(' + degree + 'deg)'});
// Update setter
itemStart = $('.wheel').find('.item-active');
itemNext = $('.wheel').find('.item-prev');
// Add Animation
$(itemStart).addClass('fadeOut');
$(itemNext).addClass('fadeIn');
//If were at the end
var getStartPrev = $(itemStart).prev();
var getNextPrev = $(itemNext).prev();
if( getStartPrev.length == 0 ) {
$(itemStart).removeClass('item-active');
$(itemNext).prev().addClass('item-prev');
$('.item-four').addClass('item-active').removeClass('item-prev');
} else {
$(itemStart).removeClass('item-active');
$(itemNext).removeClass('item-prev').addClass('item-active');
$(itemNext).prev().addClass('item-prev');
}
if( getNextPrev.length == 0 ) {
$('.item-four').addClass('item-prev');
}
// Remove Animation
setTimeout(function(){
$('.wheel').find('.item').removeClass('fadeIn fadeOut');
}, 400);
});
body{
background-color: #2c3e50;
}
.next{
background: #2980b9;
padding: 15px 35px;
color: #fff;
float: left;
position: relative;
z-index: 9999;
cursor: pointer;
}
.wheel-wrp{
position: relative;
height: 700px;
width: 700px;
}
.wheel{
height: 700px;
width: 700px;
transition: 0.75s;
border-radius: 50%;
position: relative;
background: #fff;
left: -350px;
}
.item{
width: 250px;
position: absolute;
opacity: 0;
border: 1px solid red;
}
.item-active{
opacity: 1;
}
.item-one {
top: 50%;
transform: translateY(-50%);
left: 75%;
}
.item-two {
right: 50%;
top: 83%;
transform: translateX(50%) rotate(90deg);
}
.item-three {
top: 50%;
right: 75%;
transform: rotate(180deg) translateY(50%);
}
.item-four {
left: 50%;
bottom: 84%;
transform: translateX(-50%) rotate(270deg);
}
.current-item{
bottom: 300px;
left: 450px;
}
.next-item{
top: 20px;
left: 230px;
-webkit-transform:rotate(0deg);
-moz-transform:rotate(0deg);
transform:rotate(-90deg);
opacity: 0;
}
h4{
margin:0px 0px;
}
.fadeOut{
animation: menuFadeOut 350ms;
webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
.fadeIn{
animation: menuFadeIn 1500ms;
webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@keyframes menuFadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes menuFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="page">
<div class="wheel-wrp">
<div class="wheel">
<div class="item item-one">
<h4>Project 1 - beautifully crafted digital brand</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item item-two">
<h4>Project 2 - redefining technological boundaries</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item item-three">
<h4>Project 3 - Beauty in Design</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
<div class="item item-four">
<h4>Project 4 - simply stunning </h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
</div>
</div>
</div>
</div>
<div class="next">Next</div>
The only changes are in the particular items definition, so if you want to check on your pen for better visibility, this is the part you should replace:
.item-one {
top: 50%;
transform: translateY(-50%);
left: 75%;
}
.item-two {
right: 50%;
top: 83%;
transform: translateX(50%) rotate(90deg);
}
.item-three {
top: 50%;
right: 75%;
transform: rotate(180deg) translateY(50%);
}
.item-four {
left: 50%;
bottom: 84%;
transform: translateX(-50%) rotate(270deg);
}
Hope that helps. And if by any means someone feels like explaining + fixing those magic numbers, that'd be much welcomed ;)
Upvotes: 1