Not smooth transition after the last slide in Swiper loop mode - javascript

I am trying to set a smooth transition for internal content when swiping (transform: scale). I added the required css rule. This works, but after switching the last slide, there is an abrupt scale change. (not smoothly).
In the source code of the library in the file swiper/src/core/loop/loopFix.js I found line number 28: const slideChanged = swiper.slideTo(newIndex, 0, false, true);
From this, I realized that the looping of the slides occurs according to the following principle: after the last slide, we instantly switch to the previous one (speed = 0) and an animation is produced that shows that we have passed the circle.
My code example: https://stackblitz.com/edit/swiper-demo-9-vertical-slider-x3g4my
Steps to reproduce the problem:
Swipe two slides down
Swipe a third time down and notice the sudden change in scale
Is there any way to fix this problem?

I had a similar issue with Swiper when looping the slide items and doing transitions/transforms on the active slide.
I found that I could add .swiper-slide-duplicate-active as well.
I tried updating your demo and if seems the following change makes the transition smooth.
.swiper-slide .content {
transform: scale(0.5);
}
.swiper-slide-active .content,
.swiper-slide-duplicate-active .content {
transform: scale(1);
}

Related

Image slider with Web Animations API

I've used WAAPI to create an image slider for a (kind of) sing along game. The slider is linked with a song, so the animation timing is very important. Using WAAPI keyframes (which are very similar to CSS keyframes) the timing offset is on a scale of 0-1, hence the calculations necessary for creating the keyframes dynamically in the code pen below. The slider should continuously loop each next slide, including sliding from the last slide to the first slide again. The problem is that the animation doesn't seamlessly continue from slide5 back to slide0.
Here is how I dynamically set the keyframes:
var keyframes = []
var pause = 0.18
var anim = 0.02
var slideHeight = 150
var translateBy = 0
var a = {transform: 'translateY(0)'} //set initial keyframe before loop
keyframes.push(a)
var offsetPercent = 0 //offset var to increment by anim & pause vars.
for(let i=0; i<songVars.fileLength; i++) {
var b = {
offset: offsetPercent+= anim,
transform: 'translateY('+ translateBy +'px)'
}
var c = {
offset: offsetPercent+= pause,
transform: 'translateY('+ translateBy +'px)'
}
keyframes.push(b, c)
translateBy-= slideHeight;
}
var d = {transform: 'translateY('+ translateBy +'px)'};
keyframes.push(d)
This code pen shows that the image slider does not loop seamlessly from the last image back to the first image. That is because I can't find a way to achieve continuous, seamless looping with the WAAPI keyframes. The first slide (slide0) is initially out of view as the CSS is set to top: 100%; transform: translateY(-100%);. I did this because the slide should begin by sliding up from the bottom of the container div.
I originally had the slides beginning at position 0, so the slide0 does start from the bottom, but it doesnt work with the timing and runs out of time, and also takes a long time for the first slide to get into position: https://codepen.io/nancy-collins/pen/bGVKBQq
I also tried the slides beginning at position -300px, so the slide0 is in view and doesnt slide up from the bottom, but when it reaches slide5 it jumps to slide0, like this: https://codepen.io/nancy-collins/pen/vYNrvaa
I know that sliders are a common discussion on here but there are none with WAAPI. It's a very new API, but should surely be able to achieve a looping slider. Thanks.
For this effect I think there are a couple of approaches you could try. One is to generate different keyframes for each animation (example CodePen here).
However, I think you might find it easier if you position all the items on top of one another (using position: absolute; top: 0; left: 0 and using position: relative; width: 300px on the parent element). Then you can apply the same animation to each item but simply change the delay so that they are staggered appropriately.
Using this approach, the translation positions would not change based on the number of slides. You would position all the frames just below the viewport, then animate them up in three steps, and then return them to their original position just below the viewport. The keyframe offsets, however, would change based on the number of slides so that you could create a suitably long "flat" section at the end where you are waiting for the other slides to finish before repeating.

strange behaviour while sliding images on carousel

I made a jsfiddle so you can reproduce the bug:
FIDDLE
I implemented a carousel to display 3 images. There's a current image (the image being displayed) and the other two remain hidden until I click one of the lateral arrows, causing the next image to slide from the side overlaying the (now previous) current image.
I've been 2 hours trying to figure out why there are certain specific 'transitions' in which the animation doesn't seem to work. For example, when clicking the left arrow to pass from the first image to the second and from the second to the third the animation works fine, but when clicking it again, the transition from 3 to 1 doesn't perform the slide animation. When moving in the opposite direction (using the right arrow) only one transition is animated. I think the problem has to do with that if in the click event handler function, but couldn't spot what's causing it.
Any help would be greatly appreciated.
TIA
The underlying issue here is related to the z-order of the three images. Your slide animations are only showing up where the image being slid in is above the displayed image; the "broken" transitions are actually occurring, they're just obscured by the "higher" visible image.
You can fix this by explicitly setting the z-index of the new and current image. For example, on the right transition:
prevLandscape.zIndex(1);
currLandscape.zIndex(0);
If you do this, you'll also need to increase the z-index of the arrows so they're above the images.
Fiddle
jsfiddle
The issue is with the hide method you just simply hide it add the slide transition for the hide method.
change this line currLandscape.hide(); to currLandscape.hide("slide");
there seemed to be a problem with the order of the images also. please try this code out. The code is reuse of the previous image arrow code. Just try it out.
$('.arrowRight').on('click',function(e) {
var currLandscape = $(this).siblings(".currImg");
var nextLandscape = currLandscape.nextAll(".hiddenImg").first();
var currDesc= $(".currDesc");
var nextDesc= currDesc.nextAll(".hiddenDesc").first();
if (nextLandscape.length == 0) {
nextLandscape = currLandscape.siblings('.hiddenImg').first();
}
if (nextDesc.length == 0) {
nextDesc= currDesc.siblings('.hiddenDesc').first();
}
nextLandscape.show("slide", { direction: "right" }, 400, function() {
currLandscape.hide("slide");
});
currDesc.fadeOut().removeClass('currDesc').addClass('hiddenDesc');
nextDesc.fadeIn().removeClass('hiddenDesc').addClass('currDesc');
currLandscape.removeClass('currImg').addClass('hiddenImg');
nextLandscape.removeClass('hiddenImg').addClass('currImg');
});

Need help making jQuery Transit transition repeat

// IGNORE THIS CODE
$(document).ready(function(){
$("#sticky-header").hide();
});
// IGNORE THIS CODE
Here is my code: http://jsfiddle.net/de74ezo5/14/
So what I was trying to achieve here was to make the pink header collapse and stay fixed at the top of the page after scrolling past the top red header. I am using Transit with jQuery to create the transition (http://ricostacruz.com/jquery.transit/). I don't know a more efficient way; Easing doesn't satisfy my needs.
The transition, for some reason, isn't repeating after scrolling back to the top, and then past the red header again.
This is what I need help with:
How do I make the transition repeat after scrolling back to the top, and then past the red header again?
How can I adjust the speed of the transition?
The problem is your sticky-header div's css is getting a transform: rule added to it on initial scroll down. When you scroll back up, this rule remains even though you hide it (which only changes display:block to display:none)
Page Load:
<div id="sticky-header" style="display: none;"></div>
Scroll down:
<div id="sticky-header" style="display: block; **transform**: translate(0px, 60px);"></div>
Scroll back up: You can see transform is still there even though display = none
<div id="sticky-header" style="display: none; **transform**: translate(0px, 60px);"></div>
Scroll back down: Rule already fired, will not re-fire unless removed.
<div id="sticky-header" style="display: block; **transform**: translate(0px, 60px);"></div>
In your else, you need to alter the css and remove that transform rule so that it refires:
$('#sticky-header').css({
"display" : "none",
"transform" : ""
});
Also, side performance note:
Every time your window scrolls below 160px, your transition is fired. You can see here as I keep scrolling lower and lower, the event is repeatedly fired (you can see it ran 6 times as I mouse wheeled down the page)
Add a check in there so .transition is only fired once: You can do this with jQuery data:
$(document).data('scrolled', false);
Full code:
$(document).ready(function() {
$("#sticky-header").hide();
$(document).data('scrolled', false);
});
$(window).scroll(function(){
if( $(document).scrollTop() > 160 ) { // do transition
if (!$(document).data('scrolled')) {
$('#sticky-header').show();
$("#sticky-header").transition({ y: 60 });
$(document).data('scrolled', true);
}
}
else { //show original header
$('#sticky-header').css({
"display" : "none",
"transform" : ""
});
$(document).data('scrolled', false);
}
});
FIDDLE

CSS3 Infinite Loop Transition

I am trying to animate a clock but I am having a lot of trouble trying to get the numbers to loop infinitely. I am moving the numbers by incrementing translateY() but when the 59th second is reached all of the other numbers fly past as it transitions back to 0. I would like a smooth transition over to 0 to continue to 1 and so on without showing anything in between.
I've tried transition: none, animation-play-state: paused, transitionEnd event listeners and even delays but I wasn't able to use any to achieve what I'm looking for.
Link to code on JSFiddle http://jsfiddle.net/bwr4yz0s/
The code below outlines one failed attempt:
/*Seconds*/
if (sec === 0){
/*Move to fake 0*/
$("#secn").css({transform: 'translateY(-100px))'});
/*Turn off animation*/
//$("#secn").css({transition: 'none'});
/*Move back to actual 0*/
//$("#secn").css({transform: 'translateY(0px)'});
/*Turn animations back on*/
//$("#secn").css({transition: 'all 0.8s'});
}
else{
vert = sec*20 + 'px';
$("#secn").css({transform: 'translateY(-'+vert+') translateZ(0)'});
}
Any help would be greatly appreciated. Thanks.

Smoothly change CSS animation mid-animation

I'm trying to transition smoothly from one half-completed CSS animation to the next one and I can't find a way to do it without a slight stutter. I have an infinite animation at very high speed that should gently slow down to a stop on click. Right now, I'm always getting a slight hickup while switching animations, likely partially because I need to wait for the next requestAnimationFrame before starting the next animation. Are there other options? Here's approximately what I'm doing:
function onClick(){
// get current location of element
var content = $(".content");
var currentOffset = $(content[0]).css("top");
// set property to stop jumping back to the beginning of current animation
content.css({ top: currentOffset });
// stop the current animation
content.removeClass("anim-infinite");
// update content based on current location
// updateContent(currentOffset);
// setup ease-out animation
window.requestAnimationFrame(function() {
content.addClass("anim-ease-out");
content.css({ top: parseFloat(currentOffset) + 50 });
});
}
And here's the relevant CSS.
#keyframes "spin" {
from { top: 0 };
to { top: -200%; }
}
.anim-infinite{
animation: spin 1s linear infinite;
}
.anim-ease-out{
transition: all 0.25s ease-out;
}
The distances and timespans are reasonable to maintain constant speed between the two animations and I'm using the relevant browser prefixes.
I get the same stutter when I use a "linear" timing function for the second animation. I tried setting an animation-fill-mode:both, without success. It appears to only affect animations that complete.
The stutter gets worse when I try to update the content based on the location of the content - which is dependent on when the animation gets stopped.
While trying to work out a jsFiddle that demos the problem, I found the source of most of the stutter. Anything that happens between removing the anim-infinite class and in the requestAnimationFrame can have a big perf impact, especially if it modifies the DOM in the content and causes the content to reflow. That's obvious in retrospect but the minor DOM updates had a bigger impact than expected.
I still have a slight occasional stutter but it's "good enough" for now.
For reference, here's the fiddle.

Categories