CSS3 changing animation duration (speed) mid-animation - javascript

I'm not sure if this is a duplicate or not, so forgive me.
Question
Is it possible to change the animation-duration without resetting the animation? If not, is it possible to wait until the final keyframe is completed before removing the animation and re-adding it to start the animation at the slower speed (or even wait until any keyframe is complete)?
Background
I'm making an app that allows people to create groups. I work at a church, and different groups are for different demographics (e.g. children, men, women, all adults, etc). Groups may be for a single demographic or many. Groups may also specify whether childcare is handled by the group or if the parent must take care of it.
We've found that when creating a group intended for adults but that provides childcare at the house the group meets at, people select "Children" which indicates to us that the group is for children, which it is not.
I only have 570px by 456px to work with (against my objections, the group submission page is loaded in a popup iframe), so I had to get creative with layout. Previously (ie, before bootstrap), I had an ugly layout with smaller inputs, and an ugly message explaining that, in the case described above, they should not select children, and it worked to a degree.
Now, I have a blue info button that uses a bootstrap popover to display the message.
This works to a lesser degree, as I suspect people are not clicking the button, as "Who's invited?" seems fairly self explanatory.
My solution is to make the info-sign bounce if they select more than one demographic, and bounce twice as fast if one of the selected checkboxes is "Children".
Code
I've created the classes and added the (simplified) JavaScript to do this.
var iGlyph = $("#glyphInfo");
var btnBounce = $("#btnToggleBounce");
var btnFast = $("#btnToggleFast");
var spanDur = $("#spanDuration");
var spanClass = $("#spanClass");
function updateText() {
spanDur.text(iGlyph.css("animation-duration"));
spanClass.text(iGlyph.prop("class"));
}
$(function() {
btnBounce.click(function() {
iGlyph.toggleClass("bounce");
updateText();
});
btnFast.click(function() {
iGlyph.toggleClass("bounce-fast");
updateText();
});
updateText();
});
/* LESS-generated CSS */
.bounce {
-webkit-animation: bounceKeyframe infinite;
-o-animation: bounceKeyframe infinite;
animation: bounceKeyframe infinite;
-webkit-animation-duration: 0.7s;
animation-duration: 0.7s;
}
.bounce.bounce-fast {
-webkit-animation-duration: 0.35s;
animation-duration: 0.35s;
}
#keyframes bounceKeyframe {
0% {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
35% {
-webkit-transform: translate(0, -0.9em);
-ms-transform: translate(0, -0.9em);
-o-transform: translate(0, -0.9em);
transform: translate(0, -0.9em);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
70% {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
}
}
#-webkit-keyframes bounceKeyframe {
0% {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
35% {
-webkit-transform: translate(0, -0.9em);
-ms-transform: translate(0, -0.9em);
-o-transform: translate(0, -0.9em);
transform: translate(0, -0.9em);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
70% {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
}
}
#-moz-keyframes bounceKeyframe {
0% {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
35% {
-webkit-transform: translate(0, -0.9em);
-ms-transform: translate(0, -0.9em);
-o-transform: translate(0, -0.9em);
transform: translate(0, -0.9em);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
70% {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="text-align: center; margin-top: 5%">
<div class="btn btn-info">
<span id="glyphInfo" class="glyphicon glyphicon-info-sign" style="line-height: 22px"></span>
</div>
</div>
<div style="text-align: center">
animation-duration: <span id="spanDuration"></span>
</div>
<div style="text-align: center">
classes: <span id="spanClass"></span>
</div>
<div style="text-align: center; margin-top: 15px">
<div class="btn btn-default" id="btnToggleBounce">Toggle Bounce</div>
<div class="btn btn-default" id="btnToggleFast">Toggle Fast</div>
</div>
This works in Firefox, though when you toggle .bounce-fast, the animation restarts (skips). Not surprisingly, Internet Explorer bounces the icon completely off screen (looks like it doesn't like using both em and px units), but animation-duration-wise, it acts the same as Chrome, which uses whatever animation-duration was set to when the animation rule was set, and never overrides it until the animation rule is unset.
Problem
So, ideally, I would be able to set the animation-duration somehow without having to reset the animation completely. I want a smooth transition from one speed to the other, without the icon jumping.
Is this possible?

Unfortunately there is no way to do this with pure CSS animations. The nature of CSS animations is that the calculations for the transition only have to happen once (when the animation is called) in order to speed them up.
If you want to change speed of animations you'll need to use Javascript (which is nearly as fast, sometimes faster than, CSS animations)
I particularly like Greensock and Velocity

Related

indexOf check failing after anonymizing functions [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I developed a simple javascript animation, swapping animations on a carousel and fading them in/out. I'm trying to anonymize the functions as I'm wanting to use some of the same functions for a different purpose.
I've got everything working, except when the first image is supposed to be swapped for the second in nextItem(), the first image loads again. When I check the console, -1 is being displayed for the indexOf check I put in even though the text in items[0] (or images[0] in this case) matches the page-img div's src attribute
function fadeIn(elem, dly) {
elem.fadeIn(dly);
}
function fadeOut(elem, dly) {
elem.fadeOut(dly);
}
function swapImg(elem, images) {
timer = setInterval(function() {
fadeOut(elem, 300);
setTimeout(function() {
nextItem.call(this, elem, images);
fadeIn(elem, 100);
}, 400);
}, 5000);
}
function nextItem(elem, items) {
let itemSrc = elem.attr("src");
let i = items.indexOf(itemSrc); //-1??
if (i + 1 < items.length) {
elem.attr("src", items[i+1]);
} else {
elem.attr("src", items[0]);
}
}
const images=["http://placehold.it/350?text=img1",
"http://placehold.it/350?text=img2",
"http://placehold.it/350?text=img3"];
document.body.addEventListener("load", swapImg($('#page-img'), images));
.zoom {
height: 350px;
width: 350px;
}
.zoom.visible > img {
overflow: hidden;
animation-delay: .1s;
-webkit-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-name: move;
animation-name: move;
animation-direction: alternate;
-moz-animation-direction: alternate;
-webkit-animation-direction: alternate;
-o-animation-direction: alternate;
-ms-transform-origin: middle center;
transform-origin: middle center;
-webkit-transform-origin: middle center;
-o-transform-origin: middle center;
-moz-transform-origin: middle center;
}
.zoom > img {
height: auto!important;
width: 100%!important;
}
#-webkit-keyframes move {
from {
transform: scale(1);
text-indent: -9999px;
ms-transform: scale(1);
-webkit-transform: scale(1);
-o-transform: scale(1);
-moz-transform: scale(1);
}
to {
transform: scale(1.15);
-ms-transform: scale(1.15);
-webkit-transform: scale(1.15);
-o-transform: scale(1.15);
-moz-transform: scale(1.15);
}
}
#keyframes move {
from {
transform: scale(1);
-ms-transform: scale(1);
-webkit-transform: scale(1);
-o-transform: scale(1);
-moz-transform: scale(1);
}
to {
transform: scale(1.15);
-ms-transform: scale(1.15);
-webkit-transform: scale(1.15);
-o-transform: scale(1.15);
-moz-transform: scale(1.15);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="zoom visible imagen1" id="zoom-div">
<img src="http://placehold.it/350?text=img1" alt="" id="page-img">
</div>
I see it works here just fine. However, on my live server, I'm adding the listener in the html after the script containing this code is loaded, as I want this file to be reusable and not load the same listener for every page (some pages will be swapping text for example and won't have a fade in/out)
It's because your first image url isn't in the array. http://placehold.it/350?text=img1 should be http://placeholder.com/350?text=img1 then the first indexOf equals 0 not -1

how to trigger animation when the user scrolls to page section

I'm using a simple animate.css animation on a div on my website.
It all works fine however I want to trigger the animation when the user scrolls to that particular section on the site, rather than what it does currently which is running as soon as the website loads.
https://jsfiddle.net/u4ff2tfk/6/
This is the code so far:
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.bounce {
-webkit-animation-name: bounce;
animation-name: bounce;
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
#keyframes bounce {
from, 20%, 53%, 80%, to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
40%,
43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -30px, 0);
transform: translate3d(0, -30px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
-webkit-transform: translate3d(0, -15px, 0);
transform: translate3d(0, -15px, 0);
}
90% {
-webkit-transform: translate3d(0, -4px, 0);
transform: translate3d(0, -4px, 0);
}
}
<div data-anchor="intro-section-1" class="section intro-section-1">
<div class="float-left ">
<div id="executive-nav">
<p onclick="openSideNavBlue()" class="nav-section-title">Executive Summary</p>
</div>
<div class="intro-text animated bounce">
<p>It’s our sixth annual report and as the years go by, each iteration becomes an increasingly useful snapshot that captures the IT landscape both as it was over the last 12 months, and in transition from the years before it.
<br>
<br>There are 48 fewer respondents in this year’s survey than in 2015, although the number of respondents vary between large, medium and small organisations has stayed relatively consistent.
</div>
</div>
<div class="float-right">
<p class="intro-title">Welcome to
<br>the 2016
<br>Databarracks
<br>Data Health
<br>Check</p>
<a href="#intro-section-2">
<img class="blue-arrow" src="img/blue-arrow.svg">
</a>
</div>
</div>
See this fiddle http://jsfiddle.net/apaul34208/ozww5cvj/18/
The basic idea is to create a container. Within that container give some specifications of where exactly you want the animation to be I.E
var imagePos = $(this).offset().top;
var imageHeight = $(this).height();
var topOfWindow = $(window).scrollTop();
You want to loop through this and then have an if statement checking the boundary conditions. If it is indeed within the boundary, you can add a class which will have the necessary info for the transformation. I added the working fiddle on top.
I'm not the best at css, but maybe you could try using jQuery to do the animation? It could then be basically whatever animation you'd prefer like maybe slideIn, fadeIn etc, and you could easily define it with an if statement.

Skew effect dissapears when applying an animation

I have applied a transform: -webkit-transform: skewY(170deg) on an element.
Its working fine.
Afterwards, i add to the skewed element a class that animates a scaleOut.
This is the animation:
.partialScaleOutAnimation{
-webkit-animation: partialScaleOut 0.5s;
}
#-webkit-keyframes partialScaleOut {
0%{
-webkit-transform: scale(1);
}
100%{
-webkit-transform: scale(0.3);
}
}
for some reason when applying the animation, the skewed effect disappears. Why?

Trouble getting CSS animation to work when AJAX call

So I am making a website and can make the CSS animation work for when the page is first called but I want it to call everytime the AJAX function is called. Here is the javascript XML call which works
function XML(infoId)
{
var xmlHttp = xmlHttpObjCreate();
if (!xmlHttp) {
alert("The browser doesn't support this action.");
return;
}
xmlHttp.onreadystatechange=function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
elemObj = document.getElementById('textbox');
elemObj.innerHTML = xmlHttp.responseText;
elemObj.className = "bounceInUp";
}
}
// Append GET data to identify which quote we want
var reqURL = "FILE_NAME_HERE_?infoId=" + infoId;
xmlHttp.open("GET", reqURL, true);
xmlHttp.send();
}
Here is an example of what calls the function
Here is the CSS animation code which is named is "bounceInUp"
#textbox {
width: 100%;
background-color: transparent;
height: 200px;
color: #0000FF;
font-weight: bold;
font-size: 22px;
overflow: auto;
padding: 10;
-webkit-animation: bounceInUp 1200ms ease-out;
-moz-animation: bounceInUp 1200ms ease-out;
-o-animation: bounceInUp 1200ms ease-out;
animation: bounceInUp 1200ms ease-out;
}
#-webkit-keyframes bounceInUp {
0%, 60%, 75%, 90%, 100% {
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
0% {
opacity: 0;
-webkit-transform: translate3d(0, 3000px, 0);
transform: translate3d(0, 3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
75% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
90% {
-webkit-transform: translate3d(0, -5px, 0);
transform: translate3d(0, -5px, 0);
}
100% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
#keyframes bounceInUp {
0%, 60%, 75%, 90%, 100% {
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
0% {
opacity: 0;
-webkit-transform: translate3d(0, 3000px, 0);
transform: translate3d(0, 3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
75% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
90% {
-webkit-transform: translate3d(0, -5px, 0);
transform: translate3d(0, -5px, 0);
}
100% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.bounceInUp {
-webkit-animation-name: bounceInUp;
animation-name: bounceInUp;
}
I apologize for all the code but I want to make sure everything is here that someone may need to help me. So as of right now the css animation only runs when the page is first loaded not when the XML function is called.
It looks like you are already attaching the animation via the #textbox CSS selector. And your AJAX call adds a class name that appears to have the exact same animation properties that are already applied to the textbox via the #textbox rule.
In order to get your animation to fire again, I suspect you need to clear the animation CSS property off of your #textbox before the AJAX call is sent, then your AJAX call will reapply the animation. You can do this a variety of ways, one off the top of my head would be to create a separate class that clears the animation and apply that classname to #textbox before you do your xmlHttp.send(), that way the textbox is back to a non-animated state before your success handler from the AJAX call reapplies the animation.
To simplify it, you may just want to remove the animation properties from the #textbox CSS rule and just apply and remove the .bounceInUp class name to the element when you want the animation to run. I think that's a cleaner approach.
You can use classList:
this.classList.remove('bounceInUp');
this.classList.add('bounceInUp');
That will re-apply the class and make the bounce happen again. It is simpler and more readable than setTimeout. You're fine with classList since you're using keyframes - each will work on IE10 and above.

Scroll-controlled text animation

How do I trigger and control text animation with scrolling?
<p class="class">TEXT</p>
transform:translateX(-500px);opacity:0;
transform:translateX(0px);opacity:1;
You can use Skrollr.
Import the library, then something like
<p class="class" data-X_start=" transform:translateX(-500px);opacity:0;" data-X_end=" transform:translateX(0px);opacity:1;">
TEXT</p>
would start the animation when your scroll bar is at X_start and finish it when you reach X_end.
You must set your initial style values.
Modify style values by:
a. Adding Class
b. Adding inline style property
c. use css3 animation style property
or
Use external js library.
do not forget cross-browser compability by using prefixes.
Example (using jQuery):
//css
.class {
-moz-transform: translateX(-500px);
-ms-transform: translateX(-500px);
-o-transform: translateX(-500px);
-webkit-transform: translateX(-500px);
transform:translateX(-500px);
opacity:0;
-moz-transition: all 0.5s ease-out;
-o-transition: all 0.5s ease-out;
-webkit-transition: all 0.5s ease-out;
transition: all 0.5s ease-out;
}
.class.animated {
-moz-transform: translateX(0px);
-ms-transform: translateX(0px);
-o-transform: translateX(0px);
-webkit-transform: translateX(0px);
transform: translateX(0px);
opacity: 1;
}
//html
<p class="class">TEXT</p>
//js - animate on scrol event
$( "#target" ).scroll(function() {
$(".class").toggleClass("animate");
});

Categories