GSAP timeline with repeat is breaking the draggable ease flow - javascript

I see that using the "repeat:-1" in timeline is breaking the draggable behavior ease flow.
https://codepen.io/GreenSock/pen/WNedayo?editors=1111
If use "repeat:-1" to loop the animation in above code pen code. observe that drag ease is breaking.
.to("#Handle", {
duration: 100,
x: 1000,
repeat:-1,
ease: "none"
});

You need to put repeat in right place:
handle.t1 = gsap.timeline({
repeat: -1,
onStart() {
console.log('start');
},
onComplete() {
console.log('complete');
}
})
.to("#Handle", {
duration: 100,
x: 1000,
ease: "none"
});

Related

Anime.js - Prevent animation from playing again

let gameInit = anime.timeline({
easing: "easeInOutExpo",
duration: 3000,
});
gameInit
.add({
targets: ".buttondiv",
scale: [0, 1],
delay: 1000,
duration: 750,
})
.add(
{
targets: "#srps-div",
opacity: [0, 1],
translateY: [-50, 0],
duration: 750,
},
"-=200"
)
.add(
{
targets: "#srps-tag",
opacity: [0, 1],
duration: 750,
},
"-=800"
)
.add(
{
targets: "#code-tag",
opacity: [0, 1],
duration: 750,
},
"-=950"
);
gameInit.finished.then(function () {
let buttonBounce = anime.timeline({
duration: 1200,
easing: "easeInOutExpo",
loop: true,
direction: "alternate",
delay: 3000,
});
buttonBounce.add({
targets: ".buttondiv",
scale: [1, 1.25],
});
});
document.querySelector(".buttondiv").onclick = function(){gameStart()};
gameStart = () => {
let startGameAni = anime.timeline({
duration: 1250,
easing: "easeOutBack",
direction: 'fowards',
loop: false
});
startGameAni
.add({
targets: ".buttondiv",
translateX: [0, -3000],
opacity: [1, 0]
})
.add({
targets: "#choiceprompt",
opacity: [0, 1],
translateX:[3000, 0]
},);
};
This is my current animejs file.
gameInit are a couple of simple animations that are called once the user goes to the website. Once gameInit is done, buttonBounce will start and do a short scaling effect every 3 seconds.
When the player hits the button, it moves out of the frame to the left. The choiceprompt comes in from the right. This is done with startGameAni.
Please check a short video here with the issue:
https://streamable.com/cyidwj
[EXPIRES IN 24 HOURS]
My questions:
How do I keep the prompt on screen? When I click anywhere near the choiceprompt, especially in the middle, it starts the animation again. I don't want that. It magically lets the button reappear again and does the animation again with the prompt appearing again. How can I force anime to not replay the animation upon a mouseclick?
I've just fixed it myself. For those that are interested:
Even if the animation sends something off screen, the element is still there, perhaps hidden, on its original position and may interfere with other elements that are closeby. I've changed the initial position in the animation to be offscreen and bring it onscreen during the animation.
When the animation containing the swipe was finished, I've added another animation in the timeline which sent the unused elements 3000 pixels above the
main element. Now it was out of the way, and everything worked like it should:
document.querySelector(".buttondiv").onclick = function () {
gameStart();
};
gameStart = () => {
let startGameAni = anime.timeline({
duration: 1200,
easing: "easeInOutBack",
direction: "fowards",
loop: false,
});
startGameAni
.add({
targets: ".buttondiv",
translateX: [0, -3000],
opacity: [1, 0],
})
.add({
targets: "#choiceprompt",
opacity: [0, 1],
translateX: [3000, 0],
})
.add({
targets: ".buttondiv",
marginTop: [0, -3000],
});
};

framer motion is not transitioning when switched between keyframe animations

I have 2 keyframe animation variants and when I switch between them I want it to happen with the transition. How can I make it transition all the props when switched from one keyframe animation to another (currently it happens instantly)?
const variants = {
...,
horizontalWiggle: {
x: ["40px", "80px"],
y: [0, 0],
transition: { duration: 0.5, yoyo: Infinity }
},
verticalWiggle: {
x: [0, 0],
y: ["8px", "40px"],
transition: { duration: 0.5, yoyo: Infinity }
}
}
Using with framer motion as so:
<motion.div
className="wiggle"
variants={variations}
initial="init"
animate={vertical ? "verticalWiggle" : "horizontalWiggle"}
/>
Link to the sandbox: https://codesandbox.io/s/long-surf-405lho?file=/src/App.js
You have two options:
You should not specify 0 for axis which you do not want to animate. That way there will be no instant jump and will be smooth animation between variants.
The idea is start new animation (new variant) from last position of previous variant. Another words: you need to stop old animation and start new animation from the same value (the same keyframe). That way there also will be no instant jump.
Full example here:
NOTE: if you need to animate between variants - you could create one more variant with animation from STATE-1 to STATE-2.
Like here:
Short Example:
const variations = {
...
horizontalWiggle: {
x: [0, 40, 80, 0],
transition: { duration: 1, repeat: Infinity }
},
verticalWiggle: {
y: ["0px", "20px", "40px", "0px"],
transition: { duration: 1, repeat: Infinity }
}
};

Trigger anime.js animation when element enters viewport with waypoints

I'm triggering an animation on multiple elements when they are visible in the viewport with waypoints but I run into some problems with animations not working correctly.
What is happening here is that the animations look smooth and correct but are fired on all elements when I scroll a new .sequential element in the viewport. Even the ones that are already animated This is obviously because I target that class in the code. You can see that flickering.
This is how it looks: https://watch.screencastify.com/v/cIKae7lQKMtw4zCXlTlG
This is the code:
$('.sequential').waypoint(function() {
var CSStransforms = anime({
targets: '.sequential',
opacity: [0, 1],
translateY: [50, 0],
delay: anime.stagger(100),
easing: 'cubicBezier(.71,-0.77,.43,1.67)'
});
}, {
offset: '100%'
});
What I need to do is to instead target 'this.element' in the code instead of the class. It works but the animation is fired at the same time if multiple elements are visible and the animation is not looking as good.
This is how it looks: https://watch.screencastify.com/v/69SVdcXsTywYeYuC6LwQ
This is the code:
$('.sequential').waypoint(function() {
var CSStransforms = anime({
targets: this.element,
opacity: [0, 1],
translateY: [50, 0],
delay: anime.stagger(100),
easing: 'cubicBezier(.71,-0.77,.43,1.67)'
});
}, {
offset: '100%'
});
How can I make the animation be more sequential even if there are multiple elements visible?
If anyone is looking. This is how I finally solved it. turns out I had to target a wrapping element with waypints before I could call the animation.
$(".anime").waypoint(function() {
anime.timeline({
loop: false
}).add({
targets: this.element.querySelectorAll('.sequential'),
translateY: [50, 0],
opacity: [0, 1],
duration: 500,
delay: (el, i) => 100 * i,
easing: 'cubicBezier(.71,-0.77,.43,1.67)'
});
}, {
offset: '100%'
});

Framer Motion: Animation Will not Loop

I'm trying to loop an animation with the Framer Motion library after a small delay. The animation itself will play when it's mounted, on the webpage refresh, however does not repeat.
Iv'e looked through the docs and this seems to be similar syntax.
const AnimateTrial = {
initial: {
opacity: 0,
x: -100,
y: -35,
scale: 0.9,
},
animate: (i) => {
const delay = 5 + i * 0.5;
return {
opacity: 1,
x: -10,
y: -35,
transition: {
opacity: { delay, duration: 1.5 },
x: { delay, duration: 1.5},
repeatType: "Infinity",
repeatDelay: 5,
},
};
}
Does anyone have an idea? Everything works minus bottom two lines!
The properties inside your transition object are not right. Use repeat in place of repeatType, Write it something like this
transition={{ repeat: Infinity, repeatDelay: 5 }}
If you check the docs repeateType property accepts only "loop" "reverse" "mirror" and not "Infinity".

Loop animation with velocity.js

I'm trying to do that kind of loop animation with velocity.js: translate object on X axis from 0 to 473, then from 0 to 473 and so on.
I've succeeded to do that like this (code below) but on Android Chrome and iOS Chrome browsers the loop starts over with some delay (lag). Can someone help?
function start() {
$(".el").velocity(
{
translateX: [ -473, 0 ]
},
{
duration: 8000,
delay: 0,
easing: "linear",
complete: reset
});
}
function reset() {
$(".el").css("transform", "translate(0px, 0px)");
start();
}
start();
Since you're using forcefeeding, the .css() call is redundant.
Removing that line removes the initial lag on Chrome for Android:
$el = $(".el");
function start() {
$el.velocity(
{
translateX: [ -473, 0 ]
},
{
duration: 8000,
delay: 0,
easing: "linear",
complete: start
});
}
start();
And you can see a live version here.
Writing an answer if someone looks here again.
There's now an option in Velocity 1.2.0 to loop by setting loop: true or to an integer to loop a number of times, e.g.
$el = $(".el");
function start() {
$el.velocity(
{
translateX: [ -473, 0 ]
},
{
duration: 8000,
delay: 0,
easing: "linear",
loop: true
});
}
start();

Categories

Resources