How do you animate with AngularJs? - javascript

I've got some frustration with ng-animate. I've spent two days reading about it, and I still don't understand how it works. Here is what I'm doing.
I have an element that I can drag around with my mouse. When the element reaches a specific threshold (130px left or right), I want to reset and animate it back to it's original position (0).
My element isn't entering, or leaving the Dom; and even though it's "moving" it's not changing it's position within the DOM, so it's not really "ng-move"ing.
UPDATE
By popular request, here's some code
app.directive('ngSwipeMessage', function ($touch, $animate) {
const leftThreshold = -130;
const rightThreshold = 130;
return {
restrict: 'A',
link: function ($scope, element, attr, controller) {
var handler = $touch.bind(element, {
start: function (touch, ev) {
console.log("start");
},
end: function (touch, ev) {
console.log("end");
// if they stop moving, then reset
//$animate.addClass(element, "ng-move ng-move-active");
},
move: function (touch, ev) {
console.log("move");
element.css({
left: touch.distanceX
});
if (touch.distanceX < leftThreshold || touch.distanceX > rightThreshold) {
// fire our handler action and reset the element position
//$animate.addClass(element, "ng-move ng-move-active");
}
}
});
$scope.$on('$destroy', function () {
console.log("destroying");
handler();
});
}
};
});
And here is the CSS
#list-messages .message.ng-move {
-webkit-transition: 0.2s linear all;
-moz-transition: 0.2s linear all;
-o-transition: 0.2s linear all;
transition: 0.2s linear all;
/* future proof */
}
#list-messages .message.ng-move.ng-move-active {
left: 0 !important;
}
So the things I've tried using is $animate.leave/enter/move but they appear to actually want to leave, enter, or move around the DOM. I've started experimenting with addClass/removeClass, which has shown some promise. Overall, creating a custom animation isn't (in my opinion) documented very well.
Any help is appreciated. Thanks.

Related

how to know opacity value using javascript?

I am using transition: opacity 5s; property. I want to show different alert or console message when my opacity value is 0.4 or 0.6 or .2 . on button click I am doing transition but I want to know opacity progress so that i will show those message ?
is there any way to do this
var btn = document.querySelector("button");
var par = document.querySelector("#parId");
btn.addEventListener("click", (e) => {
par.classList.add("removed");
});
par.addEventListener("transitionend", () => {
par.remove();
});
#parId {
transition: opacity 5s;
}
.removed {
opacity: 0;
}
we are getting transitionend callback if there any progress callback where I will check opacity value ?
There is no event that can be listened to to give what you want - unless you are going to use a linear transition. In that case you can carve your changes of opacity up into 0.2s slots, changing opacity on transitionend to the next value down - 0.8, 0.6 etc.
Your code however takes the default for the transition-timing-function property which is ease - not linear - so transitionend is of no use to you.
This snippet polls the opacity changes every tenth of a second and writes the current opacity to the console so you can see what is happening.
A couple of points: you will have to check for when the opacity goes just less than one of your break points, you are unlikely every to hit it just at exactly 0.6s or whatever; also notice that the console carries on being written to after the element has totally disappeared. The timing will not be exact, things are happening asynchronously.
<style>
#parId {
transition: opacity 5s;
width: 50vw;
height: 50vh;
background: blue;
opacity: 1;
display: inline-block;
}
.removed {
opacity: 0;
}
</style>
<div id="parId"></div>
<button>Click me</div>
<script>
var btn = document.querySelector("button");
var par = document.querySelector("#parId");
btn.addEventListener("click", (e) => {
let interval = setInterval(function () {
const opacity = window.getComputedStyle(par).opacity
console.log(opacity);
if (opacity == 0) {clearInterval(interval);}
}, 100);
par.style.opacity = 0;
});
</script>
You could potentially check periodically like this, although your interval will need to be at least the speed of the opacity animation or be quicker than it to catch the values.
var par = document.querySelector("#parId");
setInterval(function() {
console.log(window.getComputedStyle(par).opacity);
}, 100)
#parId{
opacity: 0.2;
transition: opacity 3s ease-in-out;
}
#parId:hover {
opacity: 1;
}
<div id="parId">
test
</div>
Take a look in this example
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event
You could define your animation stages as diferent ranimations on css then call them in chain via javascript. Before, you must set an event listener for the animationend event, and every time the event is fired you check the #parId opacity.
You could do it.with jQuery to, totaly in javascript

How to stop one eventListener when start another on the same element?

I'm creating some kind of gallery in js as a practice. I found an error and I don't know how to solve it.
Full code of on JSFiddle ->
Code
Background
I add two eventListeners to my img wrapper,
wrapper looks like that:
<div class="gallery-item"> <-- wrapper
<img src=""> <-- image
<div> <-- overlay
</div>
</div>
and listeners like that (listeners I'm adding during creating wrappers in js):
imageWrapper.addEventListener('mouseenter', enableOverlay, false);
imageWrapper.addEventListener('mouseleave', disableOverlay, false);
Listeners invokes functions, which are responsible for displaying overlay over image. First of them show overlay with fade effect and the second one hide it with the same effect.
enableOverlay
function enableOverlay(e) {
var el = this.childNodes[1].style;
el.display = 'block';
(function fadeIn() {
if (el.opacity < 1) {
el.opacity = parseFloat(el.opacity) + Number(0.1);
setTimeout(fadeIn, 30);
}
}());
}
disableOverlay
function disableOverlay(e) {
var el = this.childNodes[1].style;
(function fadeOut() {
if (el.opacity > 0) {
el.opacity = parseFloat(el.opacity) - Number(0.1);
setTimeout(fadeOut, 30);
} else {
el.display = 'none';
}
}());
}
Problem
On first sight everything is ok if I'm slowly move mouse over images - one function ends (opacity = 1) and the second is starting until opacity = 0. But when I'm moving mouse fast over images, overlays start to blink - opacity increases and decreases by 0.1 (value in IIFEs) and script loop.
As I figured out, reason of this behavior is that enableOverlay dosen't finish (el.opacity dosen't reach 1) and in the same time disableOverlay starts. And I don't know how to fix this situation.
I was trying to deal with it using flags which represents the state of fading function and breaks IFFEs, but it didn't help.
Long story short, can anyone help me with this problem or show me a way of thinking to solve it?
EDIT
In my opinion, my problem is 'how to stop function in one eventListener when another eventListeners is fired'. Changing opacity is only a sample.
You can use css transition.
function enableOverlay(e) {
var el = this.childNodes[1].style;
el.opacity = '1';
}
function disableOverlay(e) {
var el = this.childNodes[1].style;
el.opacity = '0';
}
.gallery-item img+div {
cursor: pointer;
opacity: 0;
-webkit-transition: opacity .3s ease;
-moz-transition: opacity .3s ease;
-o-transition: opacity .3s ease;
-ms-transition: opacity .3s ease;
transition: opacity .3s ease;
}
https://jsfiddle.net/zjqpxzmj/
Just added an attribute to track the event.
Fiddle
function disableOverlay(e) {
var el = this.childNodes[1].style;
var that = this.childNodes[1];
that.setAttribute('op','fadeOut');
(function fadeOut() {
if (el.opacity > 0 && that.getAttribute('op')==='fadeOut') {
el.opacity = parseFloat(el.opacity) - Number(0.1);
setTimeout(fadeOut, 30);
} else {
el.display = 'none';
}
}());
}
In your case, catching the latest setTimeout and calling clearTimeout on it from the other function should help.

Jquery Fadein/FadeOut simultaneously

How are you?
This is from a previous post and a solution was posted.
JS :
$(document).ready(function() {
var allBoxes = $("div.boxes").children("div");
transitionBox(null, allBoxes.first());
});
function transitionBox(from, to) {
function next() {
var nextTo;
if (to.is(":last-child")) {
nextTo = to.closest(".boxes").children("div").first();
} else {
nextTo = to.next();
}
to.fadeIn(500, function() {
setTimeout(function() {
transitionBox(to, nextTo);
}, 5000);
});
}
if (from) {
from.fadeOut(500, next);
} else {
next();
}
}
JSFIDDLE HERE
However I was trying to extend this a bit, where when box 1 fades out, you can see box 2 fading in slightly at the same time - simultaneously, and as box2 fades out ...box 3 is fading in at the same time with the opacity going from 0 to 1
I'm fine and you? :') .
I have a solution that maybe can help.
Have you tried making 1 class named display and setting display: block; and then put it on the function as toggleClass(). Finally you make a new class named as .transition(I do this with all my project to make them easier) and put it on the div or add it with some code like: $("div").addClass("transition");.
the code for .transition should be like this:
.transition {
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
}
You can also try insted of CSS and jQuery using only CSS.
an example could be using CSS Animations. Define the class of every box and then make a animation and add a delay on every animation so it will show every certain time, make them infinite so the will loop.
Hope you understand :)
Editing line 14 of your jsFiddle to add a delay created a smoother effect so you don't see two at once. Which I surmise is the answer to the question.
Line 14 edits: to.delay(100).fadeIn(500, function () {

what is ng-hide-add, ng-hide-active

I'm animating a div. It has the following definition:
<div ng-show="showTranslations" ng-swipe-right="showTranslationsBlock=false">...</div>
I have the following css defined:
div.ng-hide {
transition: 0.5s linear opacity;
opacity: 0;
}
div.ng-hide-add,
div.ng-hide-remove {
/* this needs to be here to make it visible during the animation
since the .ng-hide class is already on the element rendering
it as hidden. */
display:block!important;
}
This is taken from this tutorial. The animation works. But:
Why do I need these classes .ng-hide-add and .ng-hide-remove?
Why I don't see them added to div's classes?
Why there are also classes ng-hide-add-active and ng-hide-remove-active?
Why there is no transition when the div becomes visible although I've added the following css rule:
div.ng-hide-remove {
opacity: 1;
}
UPDATE
As I can see from the table provided by google's tutorial these classes are added to trigger animation frame (this performs a reflow). Is my understanding correct? Why is animation frame is mentioned there?
I tried to increase the transition period but it didn't add the classes. I didn't see the classes ng-hide-add-active and ng-hide-remove-active added either.
As I understand from the table these are the classes that trigger transition?
UPDATE1
I've explored the Angular's source code and found the following for the ng-hide directive:
var ngHideDirective = ['$animate', function($animate) {
return function(scope, element, attr) {
scope.$watch(attr.ngHide, function ngHideWatchAction(value){
$animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
});
};
}];
As I understand the ng-hide class is added through animation service. But what happens if I don't use animations and $animate service is not available? How Angular is going to handle this situation given the code above and how it is going to add ng-hide class? Or is this $animate.addClass() simply adds a callback to addClass event?
Put your CSS transition on ng-hide-remove, ng-hide-remove-active:
div.ng-hide-remove {
transition: 0.5s linear opacity;
opacity: 0;
}
div.ng-hide-remove-active {
opacity: 1;
}
Similarly, for ng-hide-add and ng-hide-add-active:
div.ng-hide-add {
transition: 0.5s linear opacity;
opacity: 1;
}
div.ng-hide-add-active {
opacity: 0;
}

How do I animate between CSS classes using ngAnimate?

In my app, I want to show a loading indication during loading. I have implemented this successfully:
lyr.ui.directive('loading', ['$timeout', function($timeout) {
return function(scope, element, attr) {
element.addClass('content-loading');
var unbind = scope.$watch(attr.loading, function(value) {
if (value) {
element.removeClass('content-loading');
element.addClass('content-loaded');
$timeout(function() {
element.removeClass('content-loaded');
}, 250);
unbind();
}
});
};
}]);
Plunker: http://plnkr.co/edit/L6opqA?p=preview
However, I think I'm duplicating a lot of ngAnimate code in adding and removing classes, and in hard-coding the removal of content-loaded using a hard-coded timeout.
Is it possible to convert my example to use ngAnimate with less duplicated code?
It's hard to figure this out myself because the documentation on ngAnimate does not focus on JS-triggered animations.
Small note that is not reflected in the plunker: I have to render the element's children during loading, because the element contains a jQuery plugin that calls $.width, which would return 0 for elements that aren't rendered.
I found another plunker that showed me how to do this.
Solution: http://plnkr.co/edit/bzIReo?p=preview
myApp.directive('loading', ['$animate', function($animate) {
return function(scope, element, attr) {
element.addClass('content-loading');
var unbind = scope.$watch(attr.loading, function(value) {
if (value) {
$animate.removeClass(element, 'content-loading');
unbind();
}
});
};
}]);
CSS:
.content-loading {
background-image: url(data:image/gif;base64,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);
background-repeat: no-repeat;
background-position: 20px 10px;
}
.content-loading > * {
opacity: 0;
}
/* Class name generated by ngAnimate */
.content-loading-remove > * {
-webkit-transition: opacity 250ms linear;
-moz-transition: opacity 250ms linear;
transition: opacity 250ms linear;
opacity: 1;
}

Categories

Resources