Anime.js - Prevent animation from playing again - javascript

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

Related

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".

GSAP timeline with repeat is breaking the draggable ease flow

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

Media Queries with JavaScript

Hey Everyone I want to know that can I use Media Queries with JavaScript and how especially with Animejs.
var morphing = anime({
targets: '.polymorph',
points: [{
value: '405,219 0,219 0,0 70,0 77.5,0 84,0 151.5,154.5'
}, ],
easing: 'easeOutQuad',
duration: 1500,
loop: false
});
anime({
targets: '#blip',
opacity: 1,
duration: 7000,
translateX: 290,
loop: true
})
I want to change duration and translateX when it is viewed in mobile device
anime ({
targets: '#blip',
opacity: 1,
duration: 7000,
translateX: 290,
loop: true
})
Thanks
You can check the screen size of the window using screen.width() in your javascript code.
You can store the values of 'translateX' property of anime object in any variable. Then according to the screen size, you can set the values in that variable and ultimately assign the variable as the translateX property.
translateX: <your_variable>

Categories

Resources