I'm using jquery on a single page web site to slide the next "page" onto the screen when the user clicks a button. I would like the current page to slide out to the left as the new page slides in from the right, so that there is no empty space shown, but currently I am only able to get the current page to disappear as the next page slides in. The code I'm using is here: http://jsfiddle.net/xoa029jz/5/
function slideToNext() {
var currentPage = $('.current-page');
var nextPage = getNextPage(currentPage.attr('id'));
$(nextPage).css('display', 'block');
$(currentPage).animate({left: '-100%'});
$(currentPage).removeClass('current-page');
$(nextPage).addClass('current-page');
$(nextPage).animate({left: '0%'});
}
Your CSS transitions are fighting with the jQuery animation. Until I hear which you prefer I have turned off the CSS transition.
The other fixes are to set the initial position of the elements about to animate and to wait for the panel to leave completely before removing the current-page class.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/xoa029jz/8/
function slideToNext() {
var currentPage = $('.current-page');
var nextPage = getNextPage(currentPage.attr('id'));
currentPage.css('left', '0%').animate({
left: '-100%'
}, function () {
currentPage.removeClass('current-page');
});
nextPage.css({'display': 'block', 'left': '100%'}).addClass('current-page').animate({
left: '0%'
});
}
I also cleaned up a few redundant items (chained selectors etc).
You are better off just using jQuery animation, initially while you get it working, then adding a plugin (like velocity.js) to make the animations use CSS transitions, rather than try to mix the two.
Related
I am working on a simple slideshow where each slide has its own duration.
I would like to add transitions between the slides using animate.css by adding and removing classes on the current and the next slides.
My problem is that - with my current approach - only the next slide will be animated (it slides in) but the current one is just disappear without any animation.
I have tried to detect the end of the current animation and then change(adding/removing) the classes but in that case there was a huge gap between the slides...
How can make sure that two animations plays at once?`
var slides = $this.find('.slide');
slideIt = function(time) {
setTimeout(function() {
var duration = slides.eq(nextSlide).data('duration');
slides.eq(currentSlide)
.removeClass(animateIn)
.addClass(animateOut)
.hide();
slides.eq(nextSlide)
.removeClass(animateOut)
.addClass(animateIn)
.show();
slideIt(duration);
currentSlide = nextSlide; nextSlide ++;
if (nextSlide == slidesLength) { nextSlide = 0;}
},time);
};
Thank you for the help in advance!
Ps.: While typing this post I have realized that it must be the .hide() but without it only the first slide displayed.
Native CSS animations on two different elements should always run at the same time.
But if you hide an element, it disappears before the animation has even started. You have to add a timer for that.
slides.eq(currentSlide)
.removeClass(animateIn)
.addClass(animateOut);
// save the jQuery instance of the element that should be hidden.
var $currentSlide = slides.eq(currentSlide);
// hide this element later
setTimeout(function() {
$currentSlide.hide();
}, 1000); // 1000 for 1000ms, replace that with the duration of the animateOut animation
If my first answer doesn't satisfy you, because you want so solve that on the CSS side, when there is a second way:
Remove the .hide() in JavaScript.
Make sure your CSS animation ends with a state, there the element cannot be seen anymore (like transform: scale(0) or left: -100%).
Maintain that final state of the CSS animation. To do that, see: Maintaining the final state at end of a CSS3 animation
I have a jQuery simple slider it has 15 picture each five show in a slide. I have a previous button and next button.
Each next click generate a left movement by 855px with a slider animation.
Each previous click generate a right movement by 855px with a slider animation.
This is my jQuery code :
$(document).ready(function(){
$(".prev_button").click(function(){
$("ul.slider").animate({
left: "+=855"
}, 3000, function(){
$("ul.slider").css('left', '0');
li_no = 0;
$("ul.slider").find("li").each(function(){
li_no = li_no + 1;
});
slide_after_this = li_no - 6;
$('ul.slider li:gt('+slide_after_this+')').prependTo('ul.slider'); // << line changed
});
});
$(".next_button").click(function(){
//alert($("ul.slider").css("right"));
$("ul.slider").animate({
right: "+=855"
}, 3000, function(){
//alert($("ul.slider").css("right"));
$("ul.slider").css('right', '0');
$('ul.slider li:not(:nth-child(n+6))').appendTo('ul.slider');
});
});
});
Now I have two problems :
First one is with the previous button (left arrow) When I click it the animation shows and the elements changed but they do not wrapped with each other (I mean does not show the last elements immidiatly before the first element). I can not find the reason of this.
Second problem is with both right and left arrows it is like following :
If I click just the right arrow the slider working fine it animates and change the elements but If I click the both button in order (I mean right then left or left then right ) the elements change but the animation does not show. but I check if the routine go inside the animate function by some alerts and it is going inside but does not animate on the screen .
This is a link that may help you:
http://jsfiddle.net/mpx83tpv/18/
you are really close try overflow:hidden for .slider_container
div.slider_container
{
height:380px;
width:855px;
margin-left:auto;
margin-right:auto;
overflow:hidden;
}
edit js:
also use below code as you are using both right and left in the end the slider has both of them one of them is always zero.
$(document).ready(function(){
$(".prev_button").click(function(){
$("ul.slider").animate({
left: "+=855"
}, 3000);
});
$(".next_button").click(function(){
//alert($("ul.slider").css("right"));
$("ul.slider").animate({
left: "-=855"
}, 3000);
});
});
if you want a infinite scrolling you need to use right and left in this case replace your $("ul.slider").css('right', '0'); line to $("ul.slider").css('right', ''); do same for left as well, as you need the remove them.
for adding the next visible div implement you logic before the animation as you callbacks do it after the animation.
the tricky part would be the prev button for this after calculation of the div count you also need the set new left without animation and then call left move animation.
hope these make sense.
I've been trying to adapt the following code to integrate with my CSS3 slider (animated and timed with keyframes) however as you can't use .animate in js when using css3 animations on the same element I either have to use one or the other.
JS I've adapted for my slider
The current js works in the sense that it navigates through the slides my only issue is that it doesn't 'slide' to each slide it jumps.
I'd really like to keep the slideshow as it is and just want to update my js so that the slide transition works. I'm not great with js so I've been finding it difficult to find a solution.
If anyone could give some advice or a solution to my problem it would be truly appreciated.
DEMO
JS
//grab the width and calculate left value
var item_width = $("#carousel .video-list li").outerWidth();
var left_value = item_width * (-1);
//if user clicked on prev button
$('#previous').click(function () {
//get the right position
var left_indent = parseInt($("#carousel .video-list").css('left')) + item_width;
//slide the item
$("#carousel .video-list").animate({'left' : left_indent}, function () {
//move the last item and put it as first item
$("#carousel .video-list li:first").before($("#carousel .video-list li:last"));
//set the default item to correct position
$("#carousel .video-list").css({'left' : left_value});
});
//cancel the link behavior
return false;
});
//if user clicked on next button
$('#next').click(function () {
//get the right position
var left_indent = parseInt($("#carousel .video-list").css('left')) - item_width;
//slide the item
$("#carousel .video-list").animate({'left' : left_indent}, function () {
//move the first item and put it as last item
$("#carousel .video-list li:last").after($("#carousel .video-list li:first"));
//set the default item to correct position
$("#carousel .video-list").css({'left' : left_value});
});
//cancel the link behavior
return false;
});
I don't see why .animate is needed, because I have used
transition: left 1s ease;
in my CSS to achieve the same things, with a smoother animation than I got with jQuery. I tried deleting the:
//slide the item
$("#carousel .video-list").animate(...
for the left and right. I also added some text to the html divs so that you can see how it's moving better. Sorry that I couldn't get it working, but I really feel that "transition" is what you need to look into. Here's the fiddle :)
...
I think your simplest solution would be to ditch the whole CSS animate, and build your own carousel:
Consider a film strip, which is a bunch of pictures lined up next to each other. Now consider a paper with a box cut-out, the size of one picture. We put the strip behind the paper, and see only one image. If we move the strip, we can change which image we see.
The film strip will be a div with { display: inline-block; } property, containing each of the videos. The box cut-out will be a div with { overflow: hidden } property. To move the strip, we simply use $('#strip').css({'left': positionofstripleft - widthofbox }) in our javascript. And for the animation, a simple setInterval(Nextfunction, 65000) to do what clicking next would do every 65 seconds.
Finally, a CSS transition will make the movements actually animated.
I am building a Parallax website using SuperScrollorama which have some animation frame by frame using jquery and css3...
But after ending up doing so i am stuck in a problem, i am trying to navigate the pages using some scroll plugin...
I have tried Basic jquery using scrollTop event, using Jquery ScrollTo and using Tween Lite ScrollTo plugin to navigate through pages but nothing seems to work...
The issue i get after goggling it is if pages are pinned together as position:fixed; and pages doesnot scroll to that position and stuck between...
With Jquery ScrollTo, my code:-
$('.menus a').click(function(e){
e.preventDefault();
$.scrollTo(this.hash, 2000, {
easing:'easeInOutExpo',
offset:3000,
axis:'y',
queue:true
});
});
With basic scrollTop jquery, my code:-
$('a').bind('click',function(event){
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1500,'easeInOutExpo');
event.preventDefault();
});
Currently my code works like this:- http://jsfiddle.net/tFPp3/6/
As you can see in my demo, the scroll stuck between before reaching the exact position through hash...
What is the solution if i have to play through the pinned elements in Superscrollorama?
You'll have to do 2 animations : one to reach the ancher offset and then, after superscrollorama added new element for animation and recalculate the document height, do the second animation to reach the correct key frame on that page (that you fixed at offset 3000 of that section).
$(function(){
var hashes = [];
$('.menus a').each(function(){
hashes.push(this.hash);
});
console.log('hashes:', hashes);
$('.menus a').click(function(e){
e.preventDefault();
var h = this.hash;
var pageTop = $(h).offset()['top'];
console.log('pageTop=',pageTop);
$.scrollTo( pageTop+1, 2000, {
easing:'easeInExpo',
axis:'y',
onAfter:function(){
setTimeout(function(){
console.log('hashes:', hashes);
var id = hashes.indexOf(h);
console.log('hashes['+(id+1)+']=', hashes[(id+1)]);
var nextPageTop = $(hashes[id+1]).offset()['top'];
console.log('nextPageTop=', nextPageTop);
var keyOffset = pageTop + 3000;
console.log('keyOffset=',keyOffset);
if(keyOffset < nextPageTop ){
$.scrollTo( keyOffset, 2000, {
easing:'easeOutExpo',
axis:'y'
});
}
},100);
}
});
});
});
Note that each section offset changes constantly so, before launching the second animation, we have to test that we are not scrolling till the next section again. We also need a little delay here to let superscrollorama make its sauce before testing respective offsets (saddly it doesn't seem to provide an event to do so).
I had the same issue as you. Here's how I went about fixing it....
First of all we know that Superscrollorama adds a spacer pin before your element, it sets the height of the element which defines how long the user has to scroll through a section (the duration)....So in theory all we have to do is add up all the pin heights that happen BEFORE the element you want to scroll to and then offset from the top of that element...
What I did was....
Find out what element you want to scroll to. Check how many supersrollorama-pin-spacers there are before that pin, work out the heights of all of the pins and then offset it to your initial scrollTo function.
pin = $('#pin-id').prev(); //find the spacer pin
prevPin = pin.prevAll('.superscrollorama-pin-spacer'); //find all the pins before this
heights = []; //create an array to store the pin heights
$.each(prevPin, function( index, value ) {
value = $(this).attr('height'); //get each height
heights.push(value); // push it to array
});
//use eval to join all the heights together
heights = eval(heights.join("+"));
Now we have the height so lets scroll to it.....
TweenMax.to($('html,body'),1, { scrollTop:heights, });
Good Luck! I hope this helps you.
I have had a similar issue and found that janpaepke on the superscrollorama project added an additional toggle to make this easier.
You can manually add the spacers so you don't need to make adjustments by setting the pushFollowers flag in your pin to false.
Example JS
controller.pin($('#pin-id'), 200, {
anim: new TimelineLite().append([TweenMax.fromTo( $('#pin-id'), 2, {css:{opacity: 1}}, {css:{opacity: 0}})]),
offset: 0,
pushFollowers: false
});
Example HTML
<div id="pin-id">
Bunch of Content
</div>
<div style="padding-top: 200px"></div>
For a site I'm making for myself and a friend, I have a div container/wrapper with 2 other divs within it: one occupies the left half and has a black background and the other occupies the right with a white background. Essentially, this lets me get a split colored background. Each div holds half of a logo. Here's the page, temporarily hosted so you guys can see it.
http://djsbydesign.com/tempsite/index.htm
At any rate, I'd like to have links on the left and right hand sides of the page that, on click, cause their respective divs to expand from 50% to 100%. I have a few ideas, but am not sure entirely how to go about doing this (I'm rather new to javascript). The first would be to have the expanding div's z-index set to something higher than the non-expanding one, and then have it expand (somehow), and the other is to have the expanding div expand to 100% while the other shrinks to 0% at an equal rate.
The bottom line is, I have no idea how to go about doing this. I don't mind using mootools or jQuery, for the record.
The following seems to work:
$('#left-bg, #right-bg').click(
function(){
$(this).animate({'width': '100%'},600).siblings().animate({'width':'0'},600);
});
Albeit I'm not sure how you'd plan to bring back the the 'other' div.
JS Fiddle demo.
Edited to add a button (via jQuery) that allows both divs to be reverted to original dimensions:
$('#left-bg, #right-bg').click(
function(){
$(this).animate({'width': '100%'},600).siblings().animate({'width':'0'},600);
$('<button class="show">Show all</button>')
.appendTo('#wrapper');
});
$('.show').live('click',
function(){
$('#left-bg').animate(
{
'width': '50%'
},600);
$('#right-bg').animate(
{
'width': '50%'
},600);
$(this).remove();
});
Updated JS Fiddle.
Edited to address the question left by OP in the comments:
is there a way to have a page redirect after the animation completes?
Yep, just add the line window.location.href = "http://path.to.url.com/";
$('#left-bg, #right-bg').click(
function(){
$(this).animate({'width': '100%'},600).siblings().animate({'width':'0'},600);
$('<button class="show">Show all</button>')
.appendTo('#wrapper');
window.location.href = "http://www.google.com/" // <-- this line redirects.
});
$('.show').live('click',
function(){
$('#left-bg').animate(
{
'width': '50%'
},600);
$('#right-bg').animate(
{
'width': '50%'
},600);
$(this).remove();
});
Updated JS Fiddle.
Edited in response to bug report (in comments):
The one other bug (easy fix) is that any time you click on either of the divs, it creates a new button. So say you clicked on the left half, and it expanded and filled the page, etc., and then you clicked on it again (it being anywhere on the page now). It would attempt to add a second button.
To prevent a second button being added to the div just add an if:
$('#left-bg, #right-bg').click(
function(){
if (!$('.show').length) {
$(this).animate({'width': '100%'},600).siblings().animate({'width':'0'},600);
$('<button class="show">Show all</button>')
.appendTo('#wrapper');
window.location.href = "http://www.google.com/" // <-- this line redirects.
}
});
Which, will only append a button, or indeed animate the divs, so long as the $('.show') selector returns no matches.
However if you're also redirecting to another page by clicking the button it shouldn't be an issue anyway, since none of the jQuery on the original page will exectute/be able to access the page to which the user is redirected (unless it's a page on your own domain, and you've explicitly chosen to add the same button).
If you give absolute positions to your div's such that - 1st is positioned at top left corner and other is positioned at top right corner. And then in click event you can change the position of the other top corner of the div to be expanded.
You can use jquery to do this easily. Check jquery documentation for setting css.
Looks like you've got jQuery included, so use that! It's totes the easiest library to do simple animations with.
Here's an example click function that will slide the right background to be 100% like you said:
$('a#link').click(function(e) {
e.preventDefault();
$('#left-bg').animate({ width : '0%' }, 'slow');
$('#right-bg').animate({ width : '100%' }, 'slow');
});
Obviously to go in the other direction you'd switch the width values in the object passed to the animate functions.
If you're not familiar with the animate function, check the docs, but basically you just pass CSS rules in a key : value object to it, and it'll change the CSS values over time - animating it!
Hope this helps!