I'm attempting to create a circular navigation with n elements navigable by clicking the keyboard's right and left arrows. I use classes with specific CSS3 rotate and translate values and a little bit of javascript in order to change the classes to do so.
My problem is that the transition between elements with classes four and five, the one that translates between 360deg and 30deg, which goes in the opposite direction than I want it to. You can see the obvious unwanted behavior here in this jsFiddle
.one { transform: rotate(270deg) translate(200px); }
.two { transform: rotate(300deg) translate(200px); }
.three { transform: rotate(330deg) translate(200px); }
.four { transform: rotate(360deg) translate(200px); }<-- Problematic transition
.five { transform: rotate(30deg) translate(200px); }<-- Problematic transition
.six { transform: rotate(60deg) translate(200px); }
.seven { transform: rotate(90deg) translate(200px); }
.eight { transform: rotate(120deg) translate(200px); }
.nine { transform: rotate(150deg) translate(200px); }
.ten { transform: rotate(180deg) translate(200px); }
.eleven { transform: rotate(210deg) translate(200px); }
.twelve { transform: rotate(240deg) translate(200px); }
I would prefer a CSS fix for this, but I also attempted a javascript one which can be found here. I only attempted using the left arrow in this example. My approach with javascript is to obtain the current translated value in string form, strip the rotate degree from it, and add or subtract 30 degrees from it depending on whether or not the right or left arrow is pressed. The current problem with this approach is that it does not give me a value for element.style.webkitTransform (I'm using the Chrome), it's just empty for some reason. Also I'd prefer not to have to prefix everything in the javascript, thus the reason why I would like a CSS only fix
My attempt at the javascript (untested because the first line won't work for some reason):
var thisTransform = circleArray[i].style.webkitTransform;
if (thisTransform.indexOf("rotate(") >= 0) {
var newDeg = parseInt(thisTransform.split("rotate(")[1].substring(thisTransform.indexOf("deg"))) - 30;
circleArray[i].style.webkitTransform = "rotate(" + newDeg + "deg) translate(200px) !important;";
}
Side note: I use prefixfree.min.js in my project to prevent form having to manually input all of the browser prefixes
Is there a CSS only fix for my problem that I am unaware of? What is causing the error when attempting to obtain the translate value using javascript?
First of all, let me say that I think that probably the best solution would be just rotate the base circle; I am almost sure that the results would be better and easier.
But this is just an by side idea, let's go to the problem that you post.
I have done a workaroud to your problem creating a class that will move correctly the problematic classes. My idea is to provide an animation that does the movement ok:
.foura { -webkit-transform: rotate(360deg) translate(200px);
-webkit-animation: aclock .3s linear 1;
transform: rotate(360deg) translate(200px);
animation: aclock .3s linear 1;
transition: none;
}
#keyframes aclock {
0% {transform: rotate(30deg) translate(200px);}
100% {transform: rotate(0deg) translate(200px);}
}
The idea is that the movement from 30 deg to 360 deg, being done thru an animation, can be changed to go from 30 deg to 0 deg.
I provide another similar class for class five.
The remaining problem is that the script must set the element to class four or foura depending on the rotation sense, and the same for five and fivea.
This lead to that (somewhat messy) script:
document.onkeydown = function (e) {
e = e || window.event;
switch(e.which || e.keyCode) {
case 37:
for (var i = 0, j = circleArray.length; i < j; i++) {
var curClassList = circleArray[i].classList,
curClass = curClassList.toString().split(' ')[1];
baseClass = curClass;
if (baseClass == "fivea") {
baseClass = "five";
}
if (baseClass == "foura") {
baseClass = "four";
}
if(circleClassArray.indexOf(baseClass) - 1 >= 0)
{
var newClass = circleClassArray[circleClassArray.indexOf(baseClass) - 1];
if (newClass == "four") {
newClass = "foura";
}
curClassList.add(newClass)
curClassList.remove(curClass);
} else {
curClassList.add(circleClassArray[j - 1]);
curClassList.remove(curClass);
}
}
break;
case 39:
for (var i = 0, j = circleArray.length; i < j; i++) {
var curClassList = circleArray[i].classList,
curClass = curClassList.toString().split(' ')[1];
baseClass = curClass;
if (baseClass == "fivea") {
baseClass = "five";
}
if (baseClass == "foura") {
baseClass = "four";
}
if(circleClassArray.indexOf(baseClass) + 1 < j)
{
var newClass = circleClassArray[circleClassArray.indexOf(baseClass) + 1];
if (newClass == "five") {
newClass = "fivea";
}
curClassList.add(newClass)
curClassList.remove(curClass);
} else {
curClassList.add(circleClassArray[0]);
curClassList.remove(curClass);
}
}
break;
}
}
And this is the full CSS:
.circle-big {
position: relative;
height:500px;
width:500px;
background:red;
border-radius: 50% 50%;
margin: 10% 10%;
border:5px solid black;
}
.circle-inner {
border-radius: 50%;
width: 300px;
height: 300px;
border: 5px solid white;
background-color: black;
display: block;
position: absolute;
overflow: hidden;
top: 50%;
left: 50%;
margin-top:-155px;
margin-left:-155px;
}
.circle {
border-radius: 50%;
width: 70px;
height: 70px;
background-color: white;
display: block;
position: absolute;
overflow: hidden;
top: 50%;
left: 50%;
margin-top:-35px;
margin-left:-35px;
transition: all .3s linear;
}
.one { -webkit-transform: rotate(270deg) translate(200px);
transform: rotate(270deg) translate(200px);
background:blue; }
.two { -webkit-transform: rotate(300deg) translate(200px);
transform: rotate(300deg) translate(200px); }
.three { -webkit-transform: rotate(330deg) translate(200px);
transform: rotate(330deg) translate(200px);
}
.four { -webkit-transform: rotate(360deg) translate(200px);
transform: rotate(360deg) translate(200px);}
.foura { -webkit-transform: rotate(360deg) translate(200px);
-webkit-animation: aclock .3s linear 1;
transform: rotate(360deg) translate(200px);
animation: aclock .3s linear 1;
transition: none;
}
.five { -webkit-transform: rotate(30deg) translate(200px);
transform: rotate(30deg) translate(200px);}
.fivea { -webkit-transform: rotate(30deg) translate(200px);
-webkit-animation: clock .3s linear 1;
transform: rotate(30deg) translate(200px);
animation: clock .3s linear 1;
transition: none;
}
.six { -webkit-transform: rotate(60deg) translate(200px);
transform: rotate(60deg) translate(200px);}
.seven { -webkit-transform: rotate(90deg) translate(200px);
transform: rotate(90deg) translate(200px);}
.eight { -webkit-transform: rotate(120deg) translate(200px);
transform: rotate(120deg) translate(200px);}
.nine { -webkit-transform: rotate(150deg) translate(200px);
transform: rotate(150deg) translate(200px); }
.ten { -webkit-transform: rotate(180deg) translate(200px);
transform: rotate(180deg) translate(200px);}
.eleven { -webkit-transform: rotate(210deg) translate(200px);
transform: rotate(210deg) translate(200px);}
.twelve { -webkit-transform: rotate(240deg) translate(200px);
transform: rotate(240deg) translate(200px);}
#-webkit-keyframes clock {
0% {-webkit-transform: rotate(0deg) translate(200px);}
100% {-webkit-transform: rotate(30deg) translate(200px);}
}
#-webkit-keyframes aclock {
0% {-webkit-transform: rotate(30deg) translate(200px);}
100% {-webkit-transform: rotate(0deg) translate(200px);}
}
#keyframes clock {
0% {transform: rotate(0deg) translate(200px);}
100% {transform: rotate(30deg) translate(200px);}
}
#keyframes aclock {
0% {transform: rotate(30deg) translate(200px);}
100% {transform: rotate(0deg) translate(200px);}
}
updated fiddle
Following my first idea, I have added the following code to the script:
case 38:
angle = angle + 30;
var circleBig = document.getElementsByClassName("circle-big")[0];
var style = "rotate(" + angle + "deg)";
circleBig.style.webkitTransform = style;
break;
case 40:
angle = angle - 30;
var circleBig = document.getElementsByClassName("circle-big")[0];
var style = "rotate(" + angle + "deg)";
circleBig.style.webkitTransform = style;
break;
And added also transition to the big circle. Now I think it works ok (on up and down arrow !)
second version
Brand new version
For the new requirement (to keep the inner circles upright) I have redesigned most of the fiddle. I have adapted an idea that I saw from Lea Verou, to make the rotation without auxiliar divs. It consists in setting the transform to angle + translation + oposite angle. That makes the div go where you want, unrotated.
Once decided to go this way, the script has to modified the styles of the inner circles, and not the style of the base circle. To do that easily, I have stored in every element the angle of that particular element (in a data- property).
Brand New demo
The resulting HTML is similiar:
<div class="circle-big">
<div class="circle one" data-angle=270>1</div>
<div class="circle two" data-angle=300>2</div>
<div class="circle three" data-angle=330>3</div>
<div class="circle four" data-angle=0>4</div>
<div class="circle five" data-angle=30>5</div>
<div class="circle six" data-angle=60>6</div>
<div class="circle seven" data-angle=90>7</div>
<div class="circle eight" data-angle=120>8</div>
<div class="circle nine" data-angle=150>9</div>
<div class="circle ten" data-angle=180>10</div>
<div class="circle eleven" data-angle=210>11</div>
<div class="circle twelve" data-angle=240>12</div>
<div class="circle-inner"></div>
</div>
And the script is
var circleArray = document.getElementsByClassName("circle");
var angle = 0;
window.onload = chargearray;
function chargearray () {
for (var i = 0, j = circleArray.length; i < j; i++) {
var circle = circleArray[i];
var circleAngle = parseInt (circle.dataset.angle);
var totalAngle = angle + circleAngle
var style = "rotate(" + totalAngle + "deg) translate(200px)";
totalAngle = - totalAngle;
style = style + " rotate(" + totalAngle + "deg)"
circle.style.webkitTransform = style;
circle.style.Transform = style;
}
}
document.onkeydown = function (e) {
e = e || window.event;
switch(e.which || e.keyCode) {
case 37:
angle = angle + 30;
chargearray ();
break;
case 39:
angle = angle - 30;
chargearray ();
break;
}
}
Related
I wanted to create a scrolling text banner custom HTML element.
And I found the first example that is in this site(https://blog.hubspot.com/website/scrolling-text-css) does very close to what I want to do.
The one problem that I have with above is that if I have a long text (i.e. like a paragraph) so that it goes over the width of the container, I see the text showing in multiple lines so that multiple lines of text scroll at the same time.
I'd like to make it so that a single line of text shows and it scrolls until it shows all the text then repeat the scrolling cycle. I am guessing it will have to be some css setting that I have to update. What kind of setting do I need to add or change to make long text to show in a single scrolling line? Any help will be appreciated.
Below is my custom element .js file that I came up with based on the contents from the site I mentioned above. It does some extra stuff of taking color and text attributes and applies them, but you can ignore that part. createStyle() function is where I have the css stuff for styling:
my-scrolling-text-v3.js:
class MyScrollingTextV3CustomElement extends HTMLElement {
attrObj = {
color: '#000',
text: 'Please set "text" attribute in the custom element'
};
attrs = ['color', 'text'];
constructor() {
super();
console.log("myScrollingText.constructor()");
// attributes aren't available in constructor.
}
connectedCallback() {
try {
console.log("myScrollingText.connectedCallback()");
this.setAttributes();
console.log("myScrollingText.connectedCallback(): attrObj=" + JSON.stringify(this.attrObj));
this.appendChild(this.createStyle(this.attrObj.color));
this.appendChild(this.createScrollingTextInsideTextContainer(this.attrObj.text));
} catch (error) {
console.log("myScrollingText.connectedCallback(): catch: " + error);
}
}
setAttributes() {
let value = "";
for (let attr of this.attrs) {
console.log("setAttributes(): attr=" + attr);
try {
value = this.getAttribute(attr);
console.log("setAttributes(): value=" + value);
if (this.attrObj.hasOwnProperty(attr) && value && (value !== '')) {
this.attrObj[attr] = value;
}
} catch (error) {
// ignore and use default
}
}
}
createStyle(color) {
const styleElement = document.createElement('style');
styleElement.innerHTML = `
#scroll-container {
border: 3px solid black;
border-radius: 5px;
overflow: hidden;
}
#scroll-text {
font-size: 34px;
color: ${color};
/* animation properties */
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
-moz-animation: my-animation 15s linear infinite;
-webkit-animation: my-animation 15s linear infinite;
animation: my-animation 15s linear infinite;
}
/* for Firefox */
#-moz-keyframes my-animation {
from { -moz-transform: translateX(100%); }
to { -moz-transform: translateX(-100%); }
}
/* for Chrome */
#-webkit-keyframes my-animation {
from { -webkit-transform: translateX(100%); }
to { -webkit-transform: translateX(-100%); }
}
#keyframes my-animation {
from {
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
to {
-moz-transform: translateX(-100%);
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}
`;
return styleElement;
}
createScrollingTextInsideTextContainer(text) {
const textContainerDiv = document.createElement('div');
textContainerDiv.id = 'scroll-container';
textContainerDiv.appendChild(this.createScrollingText(text));
return textContainerDiv;
}
createScrollingText(text) {
const textDiv = document.createElement('div');
textDiv.id = 'scroll-text';
textDiv.textContent = text;
return textDiv;
}
}
customElements.define('my-scrolling-text-v3', MyScrollingTextV3CustomElement);
<my-scrolling-text-v3 color="#0f0" text="This is the text value from my-scrolling-text-v3 element"></my-scrolling-text-v3>
I know it is deprecated, but it still works.
A LOT less code and no wrapping
marquee {
color: #0f0;
border: 3px solid black;
border-radius: 5px;
overflow: hidden;
font-size: 34px;
}
<marquee>This is the text value from my-scrolling-text-v3 element</marquee>
After looking at different css examples and trying different properties, I found the combination of properties that make it behave the way that I want it to.
The trick was to add these two properties:
#scroll-container {
display:flex;
}
#scroll-text {
flex-shrink: 0;
}
And so the final solution with complete code is like below:
class MyScrollingTextV3CustomElement extends HTMLElement {
attrObj = {
color: '#000',
text: 'Please set "text" attribute in the custom element'
};
attrs = ['color', 'text'];
constructor() {
super();
console.log("myScrollingText.constructor()");
// attributes aren't available in constructor.
}
connectedCallback() {
try {
console.log("myScrollingText.connectedCallback()");
this.setAttributes();
console.log("myScrollingText.connectedCallback(): attrObj=" + JSON.stringify(this.attrObj));
this.appendChild(this.createStyle(this.attrObj.color));
this.appendChild(this.createScrollingTextInsideTextContainer(this.attrObj.text));
} catch (error) {
console.log("myScrollingText.connectedCallback(): catch: " + error);
}
}
setAttributes() {
let value = "";
for (let attr of this.attrs) {
console.log("setAttributes(): attr=" + attr);
try {
value = this.getAttribute(attr);
console.log("setAttributes(): value=" + value);
if (this.attrObj.hasOwnProperty(attr) && value && (value !== '')) {
this.attrObj[attr] = value;
}
} catch (error) {
// ignore and use default
}
}
}
createStyle(color) {
const styleElement = document.createElement('style');
styleElement.innerHTML = `
#scroll-container {
display: flex;
border: 3px solid black;
border-radius: 5px;
overflow: hidden;
}
#scroll-text {
font-size: 2em;
color: ${color};
flex-shrink: 0;
/* animation properties */
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
-moz-animation: my-animation 15s linear infinite;
-webkit-animation: my-animation 15s linear infinite;
animation: my-animation 15s linear infinite;
}
/* for Firefox */
#-moz-keyframes my-animation {
from { -moz-transform: translateX(100%); }
to { -moz-transform: translateX(-100%); }
}
/* for Chrome */
#-webkit-keyframes my-animation {
from { -webkit-transform: translateX(100%); }
to { -webkit-transform: translateX(-100%); }
}
#keyframes my-animation {
from {
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
to {
-moz-transform: translateX(-100%);
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}
`;
return styleElement;
}
createScrollingTextInsideTextContainer(text) {
const textContainerDiv = document.createElement('div');
textContainerDiv.id = 'scroll-container';
textContainerDiv.appendChild(this.createScrollingText(text));
return textContainerDiv;
}
createScrollingText(text) {
const textDiv = document.createElement('div');
textDiv.id = 'scroll-text';
textDiv.textContent = text;
return textDiv;
}
}
customElements.define('my-scrolling-text-v3', MyScrollingTextV3CustomElement);
<my-scrolling-text-v3 color="#0f0" text="This is the text value from my-scrolling-text-v3 element"></my-scrolling-text-v3>
I am developing a ReactJs app, I need to animate a bus in a visual path.
The bus should make stops. So the bus first go from A -> B , then when the user click a button it goes from B -> C , ect..
I have already made the animations and the logic
.bus_0 {
animation: move 3s linear forwards;
}
.bus_1 {
animation: move2nd 3s linear forwards;
}
#keyframes move {
20% {
transform: translate(50px, 0px);
}
40% {
transform: translate(50px, 0px) rotate(-90deg);
}
80% {
transform: translate(50px, -130px) rotate(-90deg);
}
100% {
transform: translate(50px, -125px) rotate(0deg);
}
}
#keyframes move2nd {
20% {
transform: translate(100px, 0px);
}
40% {
transform: translate(100px, 0px) rotate(-90deg);
}
100% {
transform: translate(100px, -50px) rotate(-90deg);
}
}
Here I add classNames based on an index
let bus = document.getElementById('bus');
bus && bus.classList.add(`bus_${data.selectedIndex}`);
The problem is when the first animation starts, the bus reachs point B , but for the second animation , it starts from point A.
Example the bus first position (0, 0), after the first animation (100, 100), when the second animation plays it start from (0, 0) but i need it the start from the last position reached.
There must be a better way probably but that is what i got and i think it will solve your problem
So i collect boxes x and y coordinates when animation button clicks and after the animationend event, i collect both x and y coordinates again and calculate difference of them and add to box style.
const firstButton = document.querySelectorAll('button')[0];
const secondButton = document.querySelectorAll('button')[1];
const myBox = document.querySelector('div')
let rectBefore;
let rectAfter;
let positionBeforeX;
let positionBeforeY;
let positionAfterX;
let positionAfterY;
let differenceX;
let differenceY;
firstButton.addEventListener('click', () => {
rectBefore = myBox.getBoundingClientRect();
positionBeforeX = rectBefore.left;
positionBeforeY = rectBefore.top;
myBox.classList.toggle('first');
})
secondButton.addEventListener('click', () => {
rectBefore = myBox.getBoundingClientRect();
positionBeforeX = rectBefore.left;
positionBeforeY = rectBefore.top;
myBox.classList.toggle('second');
})
myBox.addEventListener('animationend', (event) =>{
rectAfter = myBox.getBoundingClientRect();
positionAfterX = rectAfter.left;
positionAfterY = rectAfter.top;
differenceX = positionAfterX - positionBeforeX;
differenceY = positionAfterY - positionBeforeY;
if(myBox.style.left !== ""){
myBox.style.left = `${parseInt(myBox.style.left.split('px')) + differenceX}px`;
myBox.style.top = `${parseInt(myBox.style.top.split('px')) + differenceY}px`;
}
else{
myBox.style.left = `${differenceX}px`;
myBox.style.top = `${differenceY}px`;
}
myBox.classList.remove(`${event.animationName}`);
})
*,
*::before,
*::after {
box-sizing: border-box;
}
body{
min-height: 100vh;
position: relative;
display: grid;
place-content: center;
}
button{
position: absolute;
background-color: greenyellow;
width: 5rem;
height: 5rem;
}
button:nth-of-type(1){
top:5rem;
right: 10rem;
margin-right: 1rem;
}
button:nth-of-type(2){
top:5rem;
right: 5rem;
}
.box{
position:relative;
width: 100px;
height: 100px;
background-color: blue;
}
.first {
animation: first 3.0s linear forwards;
}
.second {
animation: second 3.0s linear forwards;
}
#keyframes first {
20% {
transform: translate(50px, 0px);
}
40% {
transform: translate(50px, 0px) rotate(-90deg);
}
80% {
transform: translate(50px, -130px) rotate(-90deg);
}
100% {
transform: translate(50px, -125px) rotate(0deg);
}
}
#keyframes second {
20% {
transform: translate(100px, 0px);
}
40% {
transform: translate(100px, 0px) rotate(-90deg);
}
100% {
transform: translate(100px, -50px) rotate(-90deg);
}
}
<div class="box"></div>
<button>First Animation</button>
<button>Second Animation</button>
I have a basic fixed animation on an element that runs when the user click on "space" :
&.pop {
animation: pop 1s ease-in 20ms 1 normal both;
}
#keyframes pop {
0% {
transform: rotate(0deg);
transform-origin: 30px;
}
20% {
transform: rotate(-30deg);
transform-origin: 30px;
}
40% {
transform: rotate(-10deg) translate(-2px, -20px);
transform-origin: 30px;
}
60% {
transform: rotate(0deg) translate(0, -40px);
transform-origin: 30px;
}
80% {
transform: rotate(3deg) translate(2px, -20px);
transform-origin: 30px;
}
100% {
transform:translate(0,0);
transform-origin: 30px;
}
}
Now, i want to add different other transform animations onkeydown that will run simultaneously with the current animation, for example :
&.spin {
animation: spin 500ms ease-out 20ms 1 forwards;
}
#keyframes spin {
0% {
transform: rotateY(0);
}
100% {
transform: rotateY(180deg);
}
}
So my problam is that when i am adding the second "spin" class, it runs over my first "pop" animation.
what will be the way to add it instead of running over ?
if i understood your question correctly:
you can use multiple animations within the transform :
just like this :
transform: rotate(90deg) translate(150px, -230px);
or you can use another approach:
you can wrap your target element with two outer divs and assign an animation for every div..
just like this
<div class="apply_this_animation">
<div class="apply_this_animation_also">
<img src="https://via.placeholder.com/300x300" alt="#" />
</div>
</div>
and use this in you CSS just like this:
<style>
.apply_this_animation {
transform: rotate(90deg);
}
.apply_this_animation_also {
transform: translate(150px, -230px);
}
</style>
Read More
I've used one template from W3 Schools in order to build a theme with Bootstrap for WordPress
http://www.w3schools.com/bootstrap/bootstrap_theme_company.asp
One feature is the animation to slide some elements within a div in the webpage as you scroll it, using jQuery.
Currently the animation is implemented only from bottom to top, but I'm struggling to implement from right to left and vice versa as well.
Here is the code already working for bottom to top animation:
jQuery(function($) {
$(window).scroll(function () {
$(".slideanim-bottom").each(function () {
var pos = $(this).offset().top;
var winTop = $(window).scrollTop();
if (pos < winTop + 600) {
$(this).addClass("slide");
}
});
});
});
.slideanim {
visibility: hidden;
}
.slide {
animation-name: slide;
-webkit-animation-name: slide;
animation-duration: 1s;
-webkit-animation-duration: 1s;
visibility: visible;
}
#keyframes slide {
0% {
opacity: 0;
-webkit-transform: translateY(70%);
}
100% {
opacity: 1;
-webkit-transform: translateY(0%);
}
}
#-webkit-keyframes slide {
0% {
opacity: 0;
-webkit-transform: translateY(70%);
}
100% {
opacity: 1;
-webkit-transform: translateY(0%);
}
}
<div class="row slideanim-bottom">
Does anyone know how to implement the same thing for left to right and vice versa as well? I think it is just a matter of adding some code in the js.
Thanks!
Just change translateY to translateX like this:
#keyframes slide {
0% {
opacity: 0;
-webkit-transform: translateX(70%);
}
100% {
opacity: 1;
-webkit-transform: translateX(0%);
}
}
#-webkit-keyframes slide {
0% {
opacity: 0;
-webkit-transform: translateX(70%);
}
100% {
opacity: 1;
-webkit-transform: translateX(0%);
}
}
With code above you will get animation from right to left.
If you want animation from left to right than set negative percentage.
For example: -webkit-transform: translateX(-70%);
Also, because you do horizontal animations there will be visible horizontal scroller while animation plays so you should set overflow:hidden for your cointainer. In your case it is .container-fluid class.
You can see full example on your template page here: https://jsfiddle.net/uzxbn9da/
Have you tried changing translateY to translateX?
This would most likely modify the movement from top-down to left-right. You would have to tweak the percentage values to achieve the desired effect though.
Like this:
#keyframes slide {
0% {
opacity: 0;
-webkit-transform: translateX(70%);
}
100% {
opacity: 1;
-webkit-transform: translateX(0%);
}
}
#-webkit-keyframes slide {
0% {
opacity: 0;
-webkit-transform: translateX(70%);
}
100% {
opacity: 1;
-webkit-transform: translateX(0%);
}
}
I have a slider that I've been trying to get working. It's demo was 3 slides, but I am trying to add 4. When I add it in, the 4 item is either
In the back permanently
Under the right-sides image
I'm not quite sure how I can fix this, if there is a way.
To help describe what I'm looking for, imagine the below is my diagram:
[back img]
[left img] [right img]
[front img]
I am trying to make it so it revolves. Currently, you can see the front/left/right images, which is what I need, but you can also see the back image.
I essentially need the back image to be hidden, so whichever image is in that spot, hide it.
Here is the set up in HTML
<div class='p_slider'>
<div class='p_slider__item'>
<img src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/iwatch1.png'>
</div>
<div class='p_slider__item'>
<img src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/iwatch2.png'>
</div>
<div class='p_slider__item'>
<img src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/iwatch3.png'>
</div>
<div class='p_slider__item'>
<img src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/iwatch3.png'>
</div>
</div>
The positioning in CSS
.p_slider__item:nth-of-type(1) {
-webkit-transform: scale(0.6);
-ms-transform: scale(0.6);
transform: scale(0.6);
left: -200px;
-webkit-filter: blur(2px);
opacity: 0.8;
z-index: 1;
}
.p_slider__item:nth-of-type(2) {
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
left: 0px;
z-index: 2;
}
.p_slider__item:nth-of-type(3) {
-webkit-transform: scale(0.6);
-ms-transform: scale(0.6);
transform: scale(0.6);
left: 200px;
z-index: 1;
-webkit-filter: blur(2px);
opacity: 0.8;
}
.p_slider__item:nth-of-type(4) {
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
left: 0px;
z-index: 2;
}
I have quite a bit more code invested in this, but to keep it short, I also have this JS Fiddle Link. I know this is pretty custom work so I appreciate all the help I get! Thanks!
What I've Tried
updated fiddle with 4 items all moving here: DEMO
So I now have 4 items in rotation, but the slider wants to do this.
Slide front image to right
Slide left image to center
Slide (new center) img to Left and swap with that left
Slide (new center) to right, Slide Left to center
You can simplify the code for rotating by defining classes like left,right,front and back for the positions respectively and add and remove them to elements based on rotateLeft() or rotateRight() functions.
CSS:
.back
{
-webkit-transform: scale(0.4);
-ms-transform: scale(0.4);
transform: scale(0.4);
left:0px;
z-index: 1;
-webkit-filter: blur(2px);
}
.front
{
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
left: 0px;
z-index: 3;
}
.left
{
-webkit-transform: scale(0.6);
-ms-transform: scale(0.6);
transform: scale(0.6);
left: -200px;
opacity: 0.8;
z-index: 2;
-webkit-filter: blur(2px);
}
.right
{
-webkit-transform: scale(0.6);
-ms-transform: scale(0.6);
transform: scale(0.6);
left: 200px;
z-index: 2;
-webkit-filter: blur(2px);
opacity: 0.8;
}
JS:
// 3D Slider for Reece
on = 0; // Init
time = 500; // Set the delay before the next click is accepted to 1 second
// Right
$('.right').click(function () {
rotateRight(); // Call
on = 1; // Set delay on
});
// Left
$('.left').click(function () {
rotateLeft(); // Call
on = 1; // Set delay on
});
play = setInterval(function () {
rotateLeft()
}, 3000)
// Rotate left
function rotateLeft() {
if (on == 0) {
var frontElem = $('.p_slider__item.front');
var leftElem = $('.p_slider__item.left');
var backElem = $('.p_slider__item.back');
var rightElem = $('.p_slider__item.right');
frontElem.removeClass('front').addClass('left');
leftElem.removeClass('left').addClass('back');
backElem.removeClass('back').addClass('right');
rightElem.removeClass('right').addClass('front');
setTimeout(function () {
on = 0; // Accept clicks again
}, time)
}
}
// Rotate right
function rotateRight() {
if (on == 0) {
var frontElem = $('.p_slider__item.front');
var leftElem = $('.p_slider__item.left');
var backElem = $('.p_slider__item.back');
var rightElem = $('.p_slider__item.right');
frontElem.removeClass('front').addClass('right');
leftElem.removeClass('left').addClass('front');
backElem.removeClass('back').addClass('left');
rightElem.removeClass('right').addClass('back');
setTimeout(function () {
on = 0; // Accept clicks again
}, time)
}
}
$('.p_slider__item img').hover(function () {
clearInterval(play)
})
$('.p_slider__item img').mouseenter(function () {
$(this).animate({ 'top': '-14px' }, 300);
})
$('.p_slider__item img').mouseout(function () {
$(this).stop(true, false).animate({ 'top': '0px' }, 300)
play = setInterval(function () {
rotateLeft()
}, 3000)
})
JSFiddle: http://jsfiddle.net/pL03g26f/2/