CSS3 Infinite Loop Transition - javascript

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.

Related

Not smooth transition after the last slide in Swiper loop mode

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);
}

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.

CSS transition speed change based on mouse position

I have a div element whose width is determined by the users mouse position inside a defined area. Upon entering this area the transition should be smooth, until the width has catched up to the current mouse position and smooth again when leaving the area and the width goes back to normal. In the time between the transition should be fast, so the width is responsive to the mouse position.
Html
<div class="widthChanging"></div>
<div class="HoverA"></div>
CSS
.widthChanging {
transition: width 300ms cubic-bezier(.45,.1,.14,.61);
}
.HoverA:hover + .widthChanging {
width: calc(0.001 / var(--mouse-x, 0) * 100vw);
transition: width 0s;
}
I get the mouse position using Javascript.
When leaving the "HoverA" area the width returns smoothly, because the transition speed defined in "widthChanging" takes over. Sadly I cant (I think) do the same for entering the "HoverA" area. My only idea would be waiting the transition time before assigning a class with the slower transition time, but this seems like a bad solution to me and would also require more Javascript.
I hope you have some more elegant ideas than me :)
I solved the problem by waiting and then assigning a class with the new transition speed using javascript. I dont think that this is the best way to do it.
Here the codepen https://codepen.io/Teiem/pen/EReJPx
html
<div class="HoverA" onmouseover="SpeedEnter2()" onclick="SpeedEnter2()"onmouseout="SpeedLeave2()"></div>
Javascript
function SpeedEnter2() {
goVar = setTimeout(function(){
document.getElementById("SpeedId2").classList.add('Fast');
}, 300);
Css
.Fast {
transition: width 0s !important;
}

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.

Randomizing CSS3 animation times with javascript/jquery?

I'd like to randomize the duration of a given animation every page refresh. I've been trying it with jquery, but it doesn't seem to be working: I have that doesn't seem to be working.
Relevant css:
#background1 {
-webkit-animation: background1 10s;
}
Animation background1 is defined elsewhere; I'm not trying to change the keyframe animation part.
Jquery:
var bg1 = $('#background1');
var number = Math.floor(Math.random() * 10) + 5;
bg1.css('-webkit-animation', 'background1 ' + number + 's');
Nothing seems to happen. Help out a jquery noob?
When the browser registers your CSS declaration it registers the name of the animation background1 and the duration of 10s and then starts the animation immediately. If you want to restart the animation with a new duration you must wait till the animation finishes, or you must attach a different animation name with the new duration.
You can test at this fiddle: http://jsfiddle.net/mfdj/Phnf5/9/
You can always immediately trigger an animation when you change the name
You can restart the same animation by changing just the duration only if you set a different value for the duration and do so after the the current animation has finished
Since your initial animation is 10s long and you want to immediately trigger a duration with a randomized time you should simply remove this declaration:
#background1 {
-webkit-animation: background1 10s;
}
and you should get the result you want.
Please note that there are some quirks in the way browsers handle reattaching/retriggering css animations with the same name but different durations. For instance, in the example fiddle Chrome handles the shake and flash animations differently. Try starting a 10second animation and then interrupt with a 1second animation of the same name. The shake will finish it's 10s while the flash simply clears the animation. However, if you switch from flash to shake (and vice versa) the animation always starts fresh. These are the quirks of triggering animation with css that you must be aware of.
What other answers said is wrong!....That css is fine, it does what the answer above me said but is overwritten by jquery. In fact, your jquery is almost fine as well too.
You just get the animation function in css wrong.
You are never defining the animation to run. You are attaching animation to element using jquery successfully. But what animation.
Take a look at my example: http://jsfiddle.net/techsin/Lju95/1/
To learn more about it go here: http://css-tricks.com/snippets/css/keyframe-animation-syntax/
In bg1.css('-webkit-animation', 'background1 ' + number + 's'); background1 should refer to animation name not the element name which you are already referring to by bg1, aren't you?
Animation name and animation itself can be defined in css, and then be called with new random value.
To learn jquery easily go to here: https://tutsplus.com/course/30-days-to-learn-jquery/
To learn Html/Css3: go to w3schools.com then http://learncss.tutsplus.com/
As Fox pointed out - remove that declaration. Then, with your JS you can do something like:
var bg1 = $('#background1');
var number = Math.floor(Math.random() * 10) + 5;
bg1.css('-webkit-animation', 'background1 ' + number + 's');
You could also put it in a class to keep things cleaner (kinda)
#background1 .animated {
-webkit-animation-name: background1;
}
// jQ
$('#background1').addClass('animated').css(
'-webkit-animation-duration',
(Math.floor(Math.random() * 10) + 5) + 's'
);

Categories