web animations api, resetting 1st animation at end of chain - javascript

I'm experimenting with the web animations API for the first time, and trying to chain some values together. I'm a little confused as for this simple animation, where it will translate 200px along the X axis, then 200px down along the Y axis once the first animation is complete.
However, at the end of the animation, it resets the X value of the initial animation. I've tried playing around with 'both' | 'forwards' for the fill mode property, as well as setting translateX to 0/200 in the second transform declaration. Feel like I'm missing something quite simple here.
const box = document.getElementById('box');
const animateRight = box.animate(
[{ transform: 'translateX(0)' }, { transform: 'translateX(200px)' }],
{
fill: 'forwards',
easing: 'ease-in-out',
duration: 2000,
}
);
animateRight.finished.then(() => {
box.animate([{ transform: 'translateY(0)' }, { transform: 'translateY(100px)' }], {
composite: 'add',
fill: 'both',
duration: 1500,
});
});
#box {
width: 100px;
height: 100px;
border: 1px solid black;
}
<div id="box"></div>

Related

Animating object coming in from side of screen and then back?

I'm using anime.js to animate several divs from the right side of the screen to where they are defined by the CSS styling. I'm also creating a function to do the reverse, but I'm having several issues.
I understand how to animate an object from it's location to a destination by changing translateX, but I can't figure out how to animate moving to it's original location, like with GSAP.from(). I've tried doing this to set the div off the screen while not visible so I could move them back to the original location, but instead it seems to ignore the negative value and just continues moving in one direction.
showAnswerButtons.set(answer_button_array, {translateX: offset_num})
showAnswerButtons.add({
targets: answer_button_array,
translateX: negative_offset_num,
translateY: negative_offset_num,
duration: 5000,
delay: anime.stagger(200)
});
As an alternative to the last approach, I've also tried playing an animation to move the divs off the screen, so I could reverse the animation to bring them back. I have 4 divs to animate and sometimes I need to take some of them out of the DOM (Or at least make them invisible). So my plan was to animate them off the screen, change the visibility as needed, then bring back only the ones that I want. Unfortunately using timeline.reverse() doesn't do anything and I've read several stories of people with similar issues. I've also tried setting direction: 'reverse' and then timeline.play() with no success.
Could anyone help me with this code please?
<div id="container">
<button id="answer_button_1" class="button"></button>
<button id="answer_button_2" class="button"></button>
<button id="answer_button_3" class="button"></button>
<button id="answer_button_4" class="button"></button>
</div>
.button {
display: flex;
position: relative;
top: 200px;
left: 100px;
height: 50px;
width: 400px;
background-color: black; /*Button Color*/
color: #f5f5f5;
}
#container {
position: absolute;
right: 50%;
left: 50%;
}
var hideAnswerButtons;
var showAnswerButtons;
let hidden = true;
document.addEventListener("click", () => {
hidden = !hidden;
if (hidden) {
showAnswerButtons.play();
} else {
hideAnswerButtons.play();
}
});
defineAnimations();
function defineAnimations() {
let offset_num = 1000;
let negative_offset_num = -100;
let answer_button_array = [
answer_button_4,
answer_button_3,
answer_button_2,
answer_button_1
];
hideAnswerButtons = anime.timeline({ autoplay: false });
hideAnswerButtons.add({
targets: answer_button_array,
translateX: offset_num,
translateY: offset_num,
duration: 5000,
delay: anime.stagger(200),
easing: 'linear'
});
showAnswerButtons = anime.timeline({ autoplay: false });
//showAnswerButtons.add({
//targets: answer_button_array,
//translateX: offset_num,
//translateY: offset_num,
//duration: 0,
//easing: "linear"
//});
showAnswerButtons.set(answer_button_array, {translateX: offset_num})
showAnswerButtons.add({
targets: answer_button_array,
translateX: negative_offset_num,
translateY: negative_offset_num,
duration: 5000,
delay: anime.stagger(200),
easing: 'linear'
});
}
If you want to reverse the animation and bring the div to its orginal place you can just use "direction: 'alternate'". Theres more about it in the anime.js documentation:
https://animejs.com/documentation/

How to increment the progress in javascript progress bar?

I am trying to add a simple javascript progress bar to my website, I found a few scripts, but I always encounter the same problem - I am able to intialize the loader and set it to increment to a given value, but cannot do it in steps. Here is a simple example - https://jsfiddle.net/kimmobrunfeldt/k5v2d0rr/
At the end there is:
bar.animate(1.0);
How can i have it animated in steps? Lets say first to 50% then (after 2 secs) to 75% and then 100%. I've tried
bar.animate(0.5);
bar.animate(0.75);
bar.animate(1);
as well as:
setTimeout(function(){bar.animate(0.5)}, 2000);
setTimeout(function(){bar.animate(0.75)}, 2000);
setTimeout(function(){bar.animate(1)}, 2000);
but it always chooses the last (highest) value, instead of being animated in steps. Any advice appreicated.
bar.animate(0.5);
bar.animate(0.75);
bar.animate(1);
The above code runs simultaneously, and the last one overrides the others.
setTimeout(function(){bar.animate(0.5); console.log("animate")}, 2000);
console.log('timeout 1 called');
setTimeout(function(){bar.animate(0.75); console.log("animate")}, 2000);
console.log('timeout 2 called');
setTimeout(function(){bar.animate(1); console.log("animate")}, 2000);
console.log('timeout 3 called');
Soon as the first timeout is set, it doesn't wait for the delay before setting the next. Check the logs on the console to see what happens.
The problem is that those scripts run simultaneously. Do something like this (or something better):
bar.animate(0.5); // Number from 0.0 to 1.0
setTimeout(function () {
bar.animate(0.75);
}, 2000);
setTimeout(function () {
bar.animate(1.0);
}, 4000);
If you wanted to just animate the bar in sequences for the sake of it, you can do keyframes with CSS too.
The problem is that you're, essentially, queuing up all of your steps to happen simultaneously. Instead, you want to pass a callback to the animate function so when it finishes, you can tell it to move to the next step.
// progressbar.js#1.0.0 version is used
// Docs: http://progressbarjs.readthedocs.org/en/1.0.0/
var bar = new ProgressBar.Line(container, {
strokeWidth: 4,
easing: 'easeInOut',
duration: 1400,
color: '#FFEA82',
trailColor: '#eee',
trailWidth: 1,
svgStyle: {
width: '100%',
height: '100%'
},
text: {
style: {
// Text color.
// Default: same as stroke color (options.color)
color: '#999',
position: 'absolute',
right: '0',
top: '30px',
padding: 0,
margin: 0,
transform: null
},
autoStyleContainer: false
},
from: {
color: '#FFEA82'
},
to: {
color: '#ED6A5A'
},
step: (state, bar) => {
bar.setText(Math.round(bar.value() * 100) + ' %');
}
});
// Keep track of the current value
var value = 0;
setTimeout(function increment() {
value += 0.1;
bar.animate(value, function() {
// Animation has completed, queue up another step
if (value < 1) {
setTimeout(increment, 500);
}
});
}, 1000);
#container {
margin: 20px;
width: 400px;
height: 8px;
position: relative;
}
<script src="https://rawgit.com/kimmobrunfeldt/progressbar.js/1.0.0/dist/progressbar.js"></script>
<div id="container"></div>

How to make that animation passed linearly? without slowing down at the start and the finish?

I need to get a picture crawling smoothly without slowing down at the start and finish.
setInterval(function runIt() {
$(".bffffg").animate({
backgroundPositionX: 300
}, 8000);
$(".bffffg").animate({
backgroundPositionX: 0
}, 0);
}, 1);
.bffffg {
display: block;
position: absolute;
width: 100%;
height: 100%;
background: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="bffffg"></div>
How to apply a linear effect to the animation?
And even apply different effects to it?
If you are looking for setting easing parameter, you may pass it as a separate argument like here:
$('your-selector').animate({
'your-property': 'value'
}, 8000, 'linear');
...or with options object like here:
$('your-selector').animate({
'your-property': 'value'
}, {
duration: 8000,
easing: 'linear'
});
Here is DOC for jQuery .animate() :)

if background = url() - issue on IE

I am trying to achieve a situation where an animation is triggered if an element has a particular background = url(" "). I am using velocity.js as the animation plugin and am able to achieve this no problem on all browser except IE, in which it fails to recognise the background url in the if statement.
I have two examples in the code below.
The first one (the orange square) uses -
if (box.style.background == "orange")
{ run(); }
to determine whether to run the animation. IE is fine with this.
However the second (the pink triangle) uses -
if (triangle.style.background == "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat")
{ runTriangle(); }
to determine whether to run the animation. IE is the only browser not to run this.
Does anyone have any idea where I'm going wrong here.
JS Fiddle example
HTML
<div id="box"></div>
<div id="triangle"></div>
CSS
#box {
width: 100px;
height: 100px;
position: absolute; }
#triangle {
width: 200px;
height: 100px;
top: 120px;
position: absolute;
z-index: 4; }
JS
window.setInterval(function runAll() {
var box = document.getElementById('box');
box.style.background = "orange";
function run() {
Velocity(box, {left: 300}, {easing: "easeInOutQuad", duration: 1000, delay: 0});
Velocity(box, {left: 10}, {easing: "easeInOutQuad", duration: 1000, delay: 0});
}
if (box.style.background == "orange")
{ run(); }
var triangle = document.getElementById('triangle');
triangle.style.background = "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat";
function runTriangle() {
Velocity(triangle, {left: 300}, {easing: "easeInOutQuad", duration: 1000, delay: 200});
Velocity(triangle, {left: 10}, {easing: "easeInOutQuad", duration: 1000, delay: 0});
}
if (triangle.style.background == "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat")
{ runTriangle(); }
}, 1000);
runAll();
The URLs in IE are different from webkit and/or Gecko, it is not safe to base your logic on the url paths.
if (triangle.style.background == "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat" || triangle.style.background == 'url("http://garyvoss.co.uk/images/triangle.svg") no-repeat' )
{ runTriangle(); }
I've managed to find a convoluted way around the issue.
Using .match I can identify a section of the url path and apply that to the if statement so that if that section is present then the animation runs.
I've create a third example (the green circle) in this JS Fiddle that shows how it works.
var str = circle.style.background;
var res = str.match(/circle/g);
document.getElementById("check").innerHTML = res;
if (document.getElementById("check").innerHTML === "circle")
{ runCircle(); }

Web Animations API - varying animation durations?

I'm experimenting with the Web Animations API which currently works only in Webkit browsers. As one can imagine, the documentation is a bit sparse:
Here's a blog post I found on it
Here's the spec
I'm trying to do two things:
Reverse the animation at a random point in time before the animation ends.
Stagger the duration of the effects in the animation. For example, for a 3 second animation, the first portion of it should be 1.25s and the second portion should be 1.75s.
Here's a working example which uses the Web Animation API. My concern is that the 3 animations are spaced evenly among the 3 seconds. How can I space them out differently without instantiating multiple animationPlayer objects?
$('.box').click(function() {
var animationPlayer = this.animate([{
transform: 'translateX(0px)'
}, {
transform: 'translateX(600px)'
}, {
transform: 'translate(600px, 200px)'
}], 3000);
animationPlayer.onfinish = function(e) {
console.log('complete!');
}
// wiggle wiggle wiggle
setTimeout(function() {
animationPlayer.reverse();
setTimeout(function() {
animationPlayer.reverse();
}, 250);
}, 750);
});
.box {
background-color: red;
width: 200px;
height: 200px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
About your first question, looks like Chrome implementation still hasn't the reverse function. This is consistent with the documentation that you have linked. May be in Canary, but I haven't checked.
Correction: reading an update in your linked blog, looks like it has been added to Chrome. However, it isn't working for me ...
About your second question, specify an offset in your second keyframe
If the first transform must run for 1.25 s, for a total of 3 s, this is 1.25 / 3 = .416, so
$('.box').click(function() {
var animationPlayer = this.animate([{
transform: 'translateX(0px)'
}, {
transform: 'translateX(600px)', offset: 0.416
}, {
transform: 'translate(600px, 200px)'
}], 3000);
animationPlayer.onfinish = function(e) {
console.log('complete!');
}
// wiggle wiggle wiggle
setTimeout(function() {
animationPlayer.reverse();
setTimeout(function() {
animationPlayer.reverse();
}, 250);
}, 750);
});
.box {
background-color: red;
width: 200px;
height: 200px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>

Categories

Resources