creating css keyframes in loop - css

I am trying to create a bunch of animations that should be calculated.
I am omitting the actual calculation of those animations here as they are not relevant.
The problem I am having is in producing the correct #keyframes constructs.
here is my stripped back less:
.Entry(#animCount, #frameResolution)
{
.CreateAnim(#animNum) when (#animNum =< #animCount)
{
#keyframesname: ~'MyAnimation-#{animNum}';
.frame(#frame) when (#frame =< 100%)
{
#{frame}
{
hello1: #frame;
hello2: #animNum;
}
// .frame( ((#frame + #frameResolution)) );
}
#keyframes #keyframesname {
.frame(0%);
}
.CreateAnim(((#animNum + 1 )));
}
.CreateAnim(1);
}
and this is how it might be called:
.Entry(3, 50%);
I'm compiling it like so:
lessc -m=strict-legacy bug.less bug.css
I expected output such as this:
#keyframes MyAnimation-1 {
0% {
hello1: 0%;
hello2: 1;
}
}
#keyframes MyAnimation-2 {
0% {
hello1: 0%;
hello2: 2;
}
}
#keyframes MyAnimation-3 {
0% {
hello1: 0%;
hello2: 3;
}
}
But in fact MyAnimation-1 also contains all the keyframes from MyAnimation-2 and MyAnimation-3, while MyAnimation-2 contains also contains all the keyframes from MyAnimation-3
Is this a bug in less, or have I done something wrong?
$lessc --version
lessc 3.9.0 (Less Compiler) [JavaScript]

Related

How I can make animation for background?

I have a menu form. To add and remove items from this menu, I use React Transition Group
ReactJS:
<TransitionGroup>
{
menu.map(meal =>
<CSSTransition
key={meal.id}
timeout={500}
classNames="meMeals"
>
<Meal meal={meal} deleteFromMenu={deleteMealFromMenu}/>
</CSSTransition>
)
}
</TransitionGroup>
CSS:
.meMeals-enter {
opacity: 0;
transform: translateY(-30px);
}
.meMeals-enter-active {
opacity: 1;
transform: translateY(0);
transition: all 500ms ease-in;
}
.meMeals-exit {
opacity: 1;
transform: translateY(0);
}
.meMeals-exit-active {
opacity: 0;
transform: translateY(-30px);
transition: all 500ms ease-in;
}
and I am completely satisfied with the behavior of the menu items.
Now I want the background element (grey) as well as the add button to move smoothly as the menu item appears or disappears. How can i do this?
I solved the problem by writing a method that is not directly related to the TransitionGroup, but works in parallel. I also set my window:
transition: 0.5s;
whatever the animation
Now I call this method every time the list changes....
function replaceMenuSize(value) {
const menuSize = menuEditorRef.current.getBoundingClientRect().height
if (value > 0) {
menuEditorRef.current.setAttribute("style", "height: " + (menuSize + 41) + "px")
} else {
menuEditorRef.current.setAttribute("style", "height: " + (menuSize - 41) + "px")
}
}

How to animate a MatDialog on close using scss/sass?

I am tending to override the scss-animations inside #angular/material/dialog. I have tried many ways and read many articles but I am still unable to reach to a solution. When the MatDialog popup opens, it has its own animations but when I close it, it closes immediately (without animation).
Firstly, the dialog opens by means of my NotifierService which looks like the following:
notifier.service.ts
#Injectable()
export class NotifierService {
...
constructor(
private dialog: MatDialog,
private dialogRef: MatDialogRef<OverlayComponent>
) { }
...
public open(notification: Notification): void {
this.dialogRef = this.dialog.open(NotificationComponent, {
...
panelClass: 'notifications-popup',
data: {
notification: notification
}
});
}
...
}
In my global scss file I have the following code:
styles.scss
...
#keyframes fadeOut {
0% { width: 85%; height: 85vh; }
100% { width: 0%; height: 0%; }
}
#keyframes fadeIn {
0% { width: 0vh; height: 0vh; }
100% { width: 85%; height: 85vh; }
}
...
div.notifications-popup {
animation: fadeIn 0.15s forwards !important;
animation-delay: 0.15s;
}
...
In my NotificationComponent I have the following above all:
notification.component.ts
...
#Component({ ... })
export class NotificationComponent {
...
public close(): void {
this.fadeOutOnClose(); // Theoretically this should animate the closure of the dialog??????
this.matDialogRef.close(this.data.overlay);
}
public fadeOutOnClose(): void {
const view = document.getElementsByClassName('notifications-popup');
for (let i = 0; i < view.length; i++) {
this.renderer.setStyle(view[i], 'animation', 'fadeOut 1s forwards !important');
this.renderer.setStyle(view[i], 'animation-delay', '1s');
}
}
...
}
...
Does anyone have any ideas about how to animate the closure of a MatDialog?
Unfortunately, it's not an easy task. That's why I chose this library for my projects:
https://www.npmjs.com/package/ng-dialog-animation

How to animate Vuetify <v-badge /> on state change?

In my navbar, I have a "Cart" item with a <v-badge /> on it that displays how many items are in the cart. When a user adds or removes to the cart, the number correctly increments and decrements. On state change of that number however, I'd like to be able to "bounce" the badge to provide the user with feedback that the item has been added or removed from the cart. I've been looking at the Vue docs for animations and transitions, I'm just not quite understanding how I'd go about achieving this.
I've attempted wrapping the badge in a <transition /> element and applying some keyframes animations I found on CSS Tricks, however it's still not working.
html:
<v-tabs
class="hidden-sm-and-down"
optional>
<v-tab
v-for="(item, i) in items"
:key="i"
:exact="item.title === 'Home'"
:to="item.to"
:ripple="false"
active-class="text--primary"
class="font-weight-bold nav-link"
min-width="96"
nuxt
text>
<transition
name="ballmove"
enter-active-class="bouncein"
leave-active-class="rollout">
<v-badge
v-if="item.badge && hasCartItems"
color="red"
:content="cartItems"
:value="cartItems"
class="default-badge"
overlap>
{{ item.title }}
</v-badge>
<span v-else>{{ item.title }}</span>
</transition>
</v-tab>
</v-tabs>
scss:
#mixin ballb($yaxis: 0) {
transform: translate3d(0, $yaxis, 0);
}
#keyframes bouncein {
1% { #include ballb(-400px); }
20%, 40%, 60%, 80%, 95%, 99%, 100% { #include ballb() }
30% { #include ballb(-80px); }
50% { #include ballb(-40px); }
70% { #include ballb(-30px); }
90% { #include ballb(-15px); }
97% { #include ballb(-10px); }
}
#keyframes rollout {
0% { transform: translate3d(0, 300px, 0); }
100% { transform: translate3d(1000px, 300px, 0); }
}
#keyframes ballroll {
0% { transform: rotate(0); }
100% { transform: rotate(1000deg); }
}
.rollout {
width: 60px;
height: 60px;
animation: rollout 2s cubic-bezier(0.55, 0.085, 0.68, 0.53) both;
div {
animation: ballroll 2s cubic-bezier(0.55, 0.085, 0.68, 0.53) both;
}
}
.bouncein {
animation: bouncein 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
.ballmove-enter {
#include ballb(-400px);
}
So I ended up going more of an old-school way. I took out the <transition /> wrapper around the <v-badge />, then added a watch function as such:
watch: {
cartItems: function(newValue, oldValue) {
const badge = document.querySelector('.v-badge__badge');
if (newValue !== oldValue) {
badge.classList.add('bounce');
this.delay(500).then(() => {
badge.classList.remove('bounce');
});
}
}
},
and my scss looks like:
#mixin ballb($yaxis: 0) {
transform: translate3d(0, $yaxis, 0);
}
#keyframes bouncein {
0%, 50% { #include ballb(-3px); }
25%, 75%, 100% { #include ballb() }
}
.bounce {
animation: bouncein 500ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
This gives the little "shake" of the badge I was looking for, however if someone has a more native Vue way of handling it, I'd absolutely love to see it.
In Vue 2.6.11, here is how I got a bit of a bounce, with some help from this answer from #Bill Criswell.
From his answer I got that I needed the :key on the badge element to force a re-render. The rest is straight out of Vue.js example here.
<transition name="bounce">
<v-badge
:key="item.comments.length"
v-if="item.comments && item.comments.length > 0"
>
<span slot="badge">
{{ item.comments.length }}
</span>
<v-icon>mdi-comment </v-icon>
</v-badge>
</transition>
And the associated SCSS just copied from the Vue example above:
.bounce-enter-active {
animation: bounce-in 0.5s;
}
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
#keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}

React - JSS have element fade in when rendered

I have an element which should render when the page is loaded:
{this.state.pageLoaded && <MyComponent className={classes.container} /> }
When this component is rendered I would like for it to fade in. So I am trying to apply some jss, but can't get it quite work.
This is my JSS:
const styles = theme => ({
'#keyframes fadein': {
from: { opacity: 0 },
to : { opacity: 1 }
},
/* Firefox < 16 */
'#-moz-keyframes fadein': {
from: { opacity: 0 },
to : { opacity: 1 }
},
/* Safari, Chrome and Opera > 12.1 */
'#-webkit-keyframes fadein': {
from: { opacity: 0 },
to : { opacity: 1 }
},
/* Internet Explorer */
'#-ms-keyframes fadein': {
from: { opacity: 0 },
to : { opacity: 1 }
},
/* Opera < 12.1 */
'#-o-keyframes fadein': {
from: { opacity: 0 },
to : { opacity: 1 }
},
container: {
//How do I insert like -webkit-animation in here????
animation: '$fadein',
},
});
I do not know if my syntax is correct as I am confused with how to apply things with special character like #keyframes, --webkit-animation, etc... so that different browsers will work.
When I run the page no animations happen and I get the following warninings in my console:
Warning: [JSS] Unknown rule #-moz-keyframes fadein
Warning: [JSS] Unknown rule #-webkit-keyframes fadein
Warning: [JSS] Unknown rule #-ms-keyframes fadein
Warning: [JSS] Unknown rule #-o-keyframes fadein
To achieve this in JSS, you need to declare a key-frames property to your styles object like so;
export default ({
'#keyframes ring': {
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(360deg)',
},
},
someClassName: {
animationDelay: '-0.2s',
animationDuration: '1s',
animationIterationCount: 'infinite',
animationName: '$ring', <-- HERE IS HOW YOU REFERENCE TO IT
animationTimingFunction: 'cubic-bezier(0.5, 0, 0.5, 1)',
},
});
You can apply this effect with some css.
.fade-in {
animation: fade-in 2s;
}
#keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Just add fade-in className to your component and add this code to your css file.
Since you do not want to use css. You may save some time by adding something like http://react-animations.herokuapp.com/ or https://digital-flowers.github.io/react-animated-css.html to your app.
By following the documentation you can add animations to your react project.
I would go this route if you are unwilling to add css or sass to the project.

CSS animation onclick and reverse next onclick

I am using a spritesheet and keyframes to animate the image on a button when it is clicked.
When the button is clicked I want the frames to run in one direction and leave the button on the last image in the spritesheet, and when it is clicked again I want the same frames to run backwards, leaving the button on the first image on the spritesheet.
I am currently trying to use jquery to change the class on the button to an animating class when it is clicked, but this doesn't seem to be working.
fiddle: http://jsfiddle.net/CGmCe/10295/
JS:
function animate(){
$('.hi').addClass('animate-hi');
}
CSS:
.hi {
width: 50px;
height: 72px;
background-image: url("http://s.cdpn.io/79/sprite-steps.png");
}
.animate-hi {
animation: play 2s steps(10);
}
#keyframes play {
from { background-position: 0px; }
to { background-position: -500px; }
}
Make sure you are using an animation-capable browser. For me this works in Firefox.
The following might be just what you wanted:
http://jsfiddle.net/CGmCe/10299/
Code:
function animateButton() {
var button = $('.hi');
if (button.hasClass('animate-hi')) {
button.removeClass('animate-hi').addClass('animate-hi-reverse');
} else if (button.hasClass('animate-hi-reverse')) {
button.removeClass('animate-hi-reverse').addClass('animate-hi');
} else {
button.addClass('animate-hi');
}
};
$(document).ready(function() {
$('.hi').on("click", function() {
animateButton();
});
});
.hi {
width: 50px;
height: 72px;
background-image: url("http://s.cdpn.io/79/sprite-steps.png");
}
.animate-hi {
animation: play 2s steps(10);
}
.animate-hi-reverse {
animation: play-reverse 2s steps(10);
}
#keyframes play {
from {
background-position: 0px;
}
to {
background-position: -500px;
}
}
#keyframes play-reverse {
from {
background-position: -500px;
}
to {
background-position: 0px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="http://s.cdpn.io/79/sprite-steps.png" />
<button class="hi" type="button"></button>
Make a counter variable which checks if the button is clicked or not.
And based on the counter value add class to the element for example:
var counter=0;
$('.btn').on('click',function(){
if(counter=0)
{
$('.hi').addClass('animate-hi');
counter = 1;
}
else
{
counter = 0;
$('.hi').removeClass('animate-hi');
}
});
Make sure to declare the counter variable outside the function. Else every time its value initialized to 0.

Resources