CSS Animation with Vue.js - javascript

I'm learning Vue Js.
Actualy I'm making a chat example application with SCSS and Vue Js.
On my project I've decided to set some CSS animations to the messages box.
Here is the snippet of the animation code:
SCSS:
.push {
...
animation-duration: 0.3s;
animation-timing-function: linear;
animation-fill-mode: forwards;
&.received {
...
animation-name: inFromLeft;
}
&.sent {
...
animation-name: inFromRight;
}
}
#keyframes inFromRight {
0% {
right: -100%;
}
100% {
right: 0;
}
}
#keyframes inFromLeft {
0% {
left: -100%;
}
100% {
left: 0;
}
}
HTML / VUE:
<div id="chat">
<div v-for="(message, index) in messages" :key="index" class="push" :class="type(message)">
...
</div>
</div>
All the message are stored in the users object in array(s) format. (with vue data).
The problem is that some messages use the animation and some messages not.
I think this problem is related to vue and his method to load array(s).
Here is a dimostration of the final result:
https://www.youtube.com/watch?v=EYsBk4HboD8
Can someone help me to understand the problem and how to fix?
(I prefer use CSS animations and avoid to use the vue transition at the moment).
Thank you!

The problem is in :key="index", changing the key to be unique per-message. should fix the issue
Explanation: Vue tracks every unique element in the loop through keys to avoid removing and re-rendering elements unless they really got changed, setting messages keys as their index makes Vue think that no new element was added if element in index 3 was removed and a new element was added with the same key
read more about this here https://v2.vuejs.org/v2/guide/list.html#Array-Change-Detection

Related

Render a component after a timeout through pure CSS

I'm aware that there is a way to achieve the effect of a component being rendered after a given timeout but I would like to do it in pure CSS through transitions. The problem is that when looking at tutorials for using css transitions - you usually have to hover over the element in order to trigger the animation - but in my case - I simply want the element to become visible after 2 seconds from being rendered. How can I achieve this?
animation can help :
p {
opacity:0;
animation:show 5s 2s forwards;
}
#keyframes show {
to {opacity:1}
}
<p>see me</p>
See https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode
The animation-fill-mode CSS property specifies how a CSS animation should apply styles to its target before and after its execution.
A simple component is in this CodePen. You can simply apply the css animation on opacity.
var SomeComponent = React.createClass({
render: function() {
return (
<div className="myClass">My Component</div>
);
}
});
React.render(
<SomeComponent />,
document.getElementById('root'));
.myClass {
opacity:0;
animation:show 2s 1s forwards;
}
#keyframes show {
to {
opacity:1
}
}
<div id="root"></div>

Opacity transition works on fade out, but not fade in

This is frustrating me to no end. Before I post the code, here's a summary:
The goal, in simple terms: when I double click X, I want it to fade out; when I click Y, I want X to fade in.
The method: I'm using CSS to create the actual fade-in and fade-out "animations." I'm using JavaScript to apply the classes when necessary using a little trickery.
The problem: the fade-in transition doesn't work -- the element just appears instantly. What is driving me insane is the fact that the fade-in, when instantly added back onto a faded-out object, works perfectly. I'll explain this better as a comment in the JS code.
(Yes, I've added opacity: 1 and transition: opacity onto the base elements. It had no effect at all.)
The code:
CSS
*.fade-out {
opacity: 0;
transition: opacity 400ms;
}
*.fade-in {
opacity: 1;
transition: opacity 400ms;
}
*.hide {
display: none;
visibility: hidden;
}
JavaScript
$( '#ArtistEmblem' ).on( 'dblclick', function() {
fadeOut($( '#ArtistEmblem' ));
fadeIn($( '#btnShowLogo' ));
});
$( '#btnShowLogo' ).on( 'click', function() {
fadeOut($( '#btnShowLogo' ));
fadeIn($( '#ArtistEmblem' ));
});
function fadeOut(element) {
element.addClass( 'fade-out' );
setTimeout( function () {
element.addClass( 'hide' );
/*
* I tried immediately adding the 'fade-in' class here
* and it worked -- as soon as the element faded out, it faded
* back in (using the CSS transition). However, outside of this,
* it REFUSES to work; everything appears instantly
*/
console.log('timer triggered');
}, 400);
}
function fadeIn(element) {
element.removeClass( 'hide' );
element.removeClass( 'fade-out' );
element.addClass( 'fade-in' );
}
Relevant HTML
<div id="ArtistEmblem">
<img src="img/logo_artist_2.png" />
</div>
<div id="PopMenu" class="collapse">
<article>
<header>
<b>Debug Menu</b>
</header>
<section>
<button id="btnOpenOverlay">Open Overlay</button>
<button id="btnShowLogo" class="hide">Show Logo</button>
<button id="btnClose">Close Menu</button>
</section>
</article>
</div>
I apologize if this is something obvious but I've wasted far too much time trying to solve it. I am also open to better, faster, or more efficient solutions if that would be the best answer. Thanks in advance!
The problem is that the initial opacity of "hidden" element is 1 by default. You just need to set it to 0. And also remove display: none –
*.hide {
opacity: 0;
}
Also I would do a little refactoring and remove setTimeout:
$('#ArtistEmblem').on('click', function() {
fade($('#btnShowLogo'), $(this));
});
$('#btnShowLogo').on('click', function() {
fade($('#ArtistEmblem'), $(this));
});
function fade(inElement, outElement) {
inElement.removeClass('hide');
inElement.addClass('fade-in');
outElement.removeClass('fade-in');
outElement.addClass('fade-out');
}
If you don't want the hidden element to occupy space and you want it to be displayed-none, then you need to set display: block before starting the fadeOut.
I know you're asking for a JS heavy answer, but I highly recommend toggling a class of "active", "open" or something similar and using CSS with the transition. Less is more here.
Here's an example fiddle of something I've transitions not only the opacity, but also the z-index. That's the key with these transitions if you intend on having any elements below such as buttons that require hovering, clicking, etc.
JS Fiddle
Key parts:
.container {
z-index: -1;
opacity: 0;
transition: z-index .01s 1s, opacity 1s;
}
.container.active {
transition: z-index 0s, opacity 1s;
z-index: 500;
opacity: 1;
}
EDIT
I was just messing around with this type of thing for my own project, and observing how beautiful Stripe handles their navigation bar. Something so simple changes everything, and that's pointer-events. If you're okay with its support, (notable no ie. 10) this is infinitely easier to integrate. Here's another fiddle of the simulation in a nav bar.
The key part is pointer-events: none, as it ignores click events if set to none, almost as if it wasn't there, yet visibly it is. I highly recommend this.
https://jsfiddle.net/joshmoxey/dd2sts7d/1/
Here is an example using Javascript Animate API. Animate API is not supported in IE/Edge though.
var element = document.getElementById("fade-in-out")
var button = document.getElementById("x")
button.addEventListener("click", function(event) {
element.animate([{opacity: 1, visibility: "visible"},{opacity: 0, visibility: "hidden"}], {duration: 2000})
setTimeout(function() { element.remove() }, 2000)
})
button.addEventListener("dblclick", function(event) {
element && element.animate([{opacity: 0}, {opacity: 1}], {duration: 2000})
})
<input id="x" type="button" value="Click here" />
<div id="fade-in-out"> FADE ME </div>

Fading a component in and fading another one out React.js

I just recently started getting into using React.js and to make it easier for myself I'm trying to recreate projects I've made in the past, but instead of using jQuery like I did in the past I'm completely avoiding jQuery and using only React.
I tend to do animations where a div would fade in as another fades out like this:
$("#start").click(function() {
$("#h1").fadeOut(750);
$("#h2").delay(500).fadeIn(750);
$("#h1").css("z-index", 0);
$("#h2").css("z-index", 1);
});
I was wondering how can I reproduce this fade in and out effect without jQuery
(I know CSS animations could change the opacity, but the opacity isn't the only thing I'm trying to change, this affects the display property as well).
A simple way is to use CSS transitions. Basically you just add a class to an element, and define a transition in the CSS and it does the rest for you
There is a tutorial here
https://www.w3schools.com/css/css3_transitions.asp
Which does a good job of explaining how it all works with examples and a playground for you to try your own
The CSS Transition group add-on might help, it let's you define transitions like this:
JS:
<ReactCSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{items}
</ReactCSSTransitionGroup>
CSS:
.example-enter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
One option would be to use a framework, like react-bootstrap, which includes a lot of the UI components you need for any given project. It includes a Fade component. Documentation can be found here: https://react-bootstrap.github.io/components.html#utilities
class Example extends React.Component {
constructor(...args) {
super(...args);
this.state = {};
}
render() {
return (
<div>
<Button onClick={()=> this.setState({ open: !this.state.open })}>
click
</Button>
<Fade in={this.state.open}>
<div>
<Well>
THIS CONTENT WILL FADE
</Well>
</div>
</Fade>
</div>
);
}
}
ReactDOM.render(<Example/>, mountNode);

I can't get my animation to work on load of my website using jquery

So the problem I am having is that I can't seem to get my jQuery Function to add a class to start my animation? I have tried a lot of different ways to get it to work, none of them are working!
jQuery
$(document).ready(function(){
window.onload = function render(){
$('.title .sub-title').addClass('render');
}
});
CSS
.render {
animation-name: render;
animation-duration: 2s;
animation-timing-function: ease-in-out;
}
#keyframes render {
0% { transform: translateX(-800px); }
100% { transform: translateX( 0px ); }
}
HTML
<div class="site-header-title-wrapper">
<h1 class="title">Template 1</h1><!--Need To add animation
<h4 class="sub-title">- Here is a Template Slogan -</h4><!--Need To add animation to-->
</div>
Please can someone help?
It would be very beneficial!
Try the following:
$(document).ready(function(){
$('.title, .sub-title').addClass('render');
});
The code in your example is targeting a .sub-title element nested within a .title element. Including a comma in your CSS selector should fix this.
Your .sub-title class is commented out. Try this:
<div class="site-header-title-wrapper">
<h1 class="title">Template 1</h1>
<h4 class="sub-title">- Here is a Template Slogan -</h4>
</div>

How to dynamically rotate the circle on every click using Jquery/Javascript/css?

I have a CSS class which forms a circle and I am trying to rotate it dynamically from Jquery by adding a css property .It works fine when I click the button for the first time and rest of the time it's idle. I tried using "cssAmination" function and its of no use. I am not able to figure out where I am going wrong. Please help me out in fixing this code. Thanks in advance.
/*Circle code*/
div.circle{
width: 300px;
height: 300px;
-moz-border-radius:150px;
-webkit-border-radius: 150px;
background:#808080;
border-radius: 150px;
bottom: -150px;
left: -150px;
position: absolute;
}
/*rotate class*/
div.rotateCircle
{
/* Firefox: */
-moz-animation-duration: 2s;
-moz-animation-timing-function: ease-in-out;
-moz-animation-iteration-count: 1;
-moz-animation-play-state: running;
}
#-moz-keyframes moveCircle
{
from {-moz-transform:rotate(0deg);}
to {-moz-transform:rotate(90deg);}
}
//Jquery code:
<script type="text/javascript">
$(document).ready(function(){
$("a").click(function(){
$('div#rotateCircle').css({'-moz-animation-name':'moveCircle'});
});
}); </script>
<body>
<h3>Labs Project</h3>
<div>
<div id=rotateCircle class="circle">
</div>
<div id=rotateCircle class="horizontalLine">
</div>
<div id=rotateCircle class="verticalLine">
</div>
<div class="divButton">
<table>
<tr>
<td><a class="btn" href="#">HOME</a></td>
<td><a class="btn" href="#">Class</a></td>
<td><a class="btn" href="#">CV</a></td>
<td><a class="btn" href="#">CM</a></td>
</tr>
</table>
</div>
</div>
</body>
You should take a look to the JavaScript events for the animations : https://developer.mozilla.org/en/CSS/CSS_animations#Using_animation_events
Basically, I've added a class for the animation's name
#rotateCircle.rotate {
-webkit-animation-name: moveCircle;
-moz-animation-name: moveCircle;
-o-animation-name: moveCircle;
animation-name: moveCircle;
}
And instead of adding the CSS in jQuery, you just add the class and remove it when the animation is finished, with the animationend event :
$(function() {
var $rotateCircle = $('div#rotateCircle');
$("a").click(function(){
$rotateCircle.addClass('rotate')
.on('animationend', function() {
$rotateCircle.removeClass('rotate');
});
});
});
(I've made it look a bit nicer too)
Here is the new working fiddle.
NB: The animationend event is prefixed on some browser, here is a gist I've made to support all the different browser (you'll need Modernizr).
There is a css3 transition property that will make this task really simple. I used webkit for my post, change properties accordingly.
CSS
#rotateCircle.rotate {
-webkit-transform: rotate(0);
-webkit-transition: -webkit-transform 2s; //+ optional path i.e. linear
}
Then with js, all you need is to set the css property to transition on, and it will magically animate to those settings, in this case transform.
$(function() {
var angle = 0;
$("a").click(function(){
angle += 90;
$("div#rotateCircle").css("-webkit-transform", "rotate("+angle+"deg)";
});
});
I didn't test this code, but the transition property is simple to use, and since I've learned it, I rarely use keyframes/css animation properties anymore.

Categories