J'ai une application AnuglarJS, où je charge/modifie des images d'un service Web ...
Manette
.controller('PlayerCtrl', function($scope, programService) {
....
programService.refresh(function(data) {
$scope.program = data;
});
....
Modèle
<img src="{{program.image}}" />
Lorsque les mises à jour de mon application à partir du service Web modifient les images comme prévu, je souhaite simplement créer un fondu enchaîné/fondu enchaîné lorsque cela se produit, comment peut-on le faire?
Est-il possible de toujours faire un fondu/dedans quand une image src change?
Merci pour les réponses -
J'ai fini par le faire et ça marche;)
--- Directive ---
.directive('fadeIn', function($timeout){
return {
restrict: 'A',
link: function($scope, $element, attrs){
$element.addClass("ng-hide-remove");
$element.on('load', function() {
$element.addClass("ng-hide-add");
});
}
};
})
--- Modèle ---
<img ng-src="{{program.image}}" class="animate-show" fade-in />
--- CSS ---
.animate-show.ng-hide-add, .animate-show.ng-hide-remove {
transition: all linear 0.5s;
display: block !important;
}
.animate-show.ng-hide-add.ng-hide-add-active, .animate-show.ng-hide-remove {
opacity: 0;
}
.animate-show.ng-hide-add, .animate-show.ng-hide-remove.ng-hide-remove-active {
opacity: 1;
}
Mise à jour 1.5.x - avec Angular 1.5.x, vous pouvez utiliser ngAnimateSwap pour obtenir cet effet.
Comme Christoph a mentionné , vous devriez regarder en utilisant $watch
sur le changement de source de l'image. Mais d’abord, assurez-vous d’utiliser le ng-src
plutôt que le src
pour la balise image
.
<image id="new" ng-src="program.image" />
$scope.$watch('program.image', function(newValue, oldValue) {
if(newValue===oldValue) return;
$('img#new').hide();
$('img#new').fadeIn("slow", function() {});
})
Je sais qu'il est tard mais selon la réponse de @Aides, je publie ici un exemple pratique qui explique comment créer une animation avec une modification de ng-src
en utilisant ngAnimateSwap
(avec Angular 1.5.x). J'espère que cela aidera quelqu'un à l'avenir:
Balise HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-ngAnimateSwap-directive-production</title>
<link href="animations.css" rel="stylesheet" type="text/css">
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="//code.angularjs.org/snapshot/angular-animate.js"></script>
<script src="script.js"></script>
<script type="text/javascript">
angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
</script>
</head>
<body ng-app="ngAnimateSwapExample" ng-controller="AppCtrl">
<div class="container">
<img ng-animate-swap="activeImage" class="cell swap-animation" ng-src="{{activeImage}}" alt="My Active Image" />
</div>
<div>
Current Image: {{activeImage}}
<br />
<button ng-click="previous()">Previous</button>
<button ng-click="next()">Next</button>
</div>
</body>
</html>
JS (script.js)
:
(function(angular) {
'use strict';
angular.module('ngAnimateSwapExample', ['ngAnimate'])
.controller('AppCtrl', ['$scope', '$timeout', function($scope, $timeout) {
var baseUrl = "http://lorempixel.com/400/200/sports";
$scope.images = [];
$scope.startIndex = 0;
for (var i = 0; i < 5; i++) {
$scope.images.Push(baseUrl + "/" + i);
}
$scope.activeImage = $scope.images[$scope.startIndex];
/*
$interval(function() {
$scope.startIndex++;
if($scope.images[$scope.startIndex] && $scope.images[$scope.startIndex] != undefined){
$scope.activeImage = $scope.images[$scope.startIndex];
}
}, 2000);
*/
$scope.previous = function() {
$scope.startIndex--;
$timeout(function() {
if ($scope.images[$scope.startIndex] && $scope.images[$scope.startIndex] !== undefined) {
$scope.activeImage = $scope.images[$scope.startIndex];
}
}, 500);
};
$scope.next = function() {
$scope.startIndex++;
$timeout(function() {
if ($scope.images[$scope.startIndex] && $scope.images[$scope.startIndex] !== undefined) {
$scope.activeImage = $scope.images[$scope.startIndex];
}
}, 500);
};
}]);
})(window.angular);
Plunker de travail ici .
Ma solution à ce problème consiste à surveiller les modifications apportées à ng-src et à utiliser une fonction de délai d’affichage pour ajouter une classe effectuant l’effet fadeIn.
HTML
<img ng-src="your-logic-will-go-here" class="animate-show ng-hide-add" fade-in>
Angular Code
.directive('fadeIn', function($timeout){
return {
restrict: 'A',
link: function($scope, $element, attrs){
$scope.$watch('selectedFormat.name', function(newValue, oldValue) {
if(newValue!=oldValue) {
$element.removeClass("ng-hide-add");
$element.addClass("ng-hide-remove");
$timeout(function () {
$element.addClass("ng-hide-add");
}, 100);
}
})
}
};
})
CSS
.animate-show.ng-hide-add, .animate-show.ng-hide-remove {
display: inline-block !important;
}
.animate-show.ng-hide-add.ng-hide-add-active, .animate-show.ng-hide-remove {
opacity: 0;
}
.animate-show.ng-hide-add{
transition: all linear 0.7s;
}
.animate-show.ng-hide-add, .animate-show.ng-hide-remove.ng-hide-remove-active {
opacity: 1;
}
Au cas où d'autres voudraient réaliser des animations sur le changement d'une image d'arrière-plan, je posterai ce que j'ai utilisé.
Cette directive suppose qu'elle est attachée à un modèle comme celui-ci:
<!-- Full screen background image and scarecrow for onload event-->
<div class="full-screen-image" data-background-image="{{backgroundImageUrl}}"></div>
<img class="hidden-full-screen-image hidden" data-ng-src="{{backgroundImageUrl}}"></div>
Nous voulons définir la source d'image d'arrière-plan pour le <div>
, mais attacher un événement onload afin de savoir quand la nouvelle image est arrivée. Pour ce faire, nous utilisons un <img>
avec une classe .hidden
qui a .hidden {display: none;}
. Nous utilisons ensuite la directive suivante pour définir de manière dynamique la source d'image d'arrière-plan de la div et effectuer un fondu au blanc puis au blanc à la modification de l'image:
/***
*
* Directive to dynamically set background images when
* controllers update their backgroundImageUrl scope
* variables
*
* Template: <div data-background-image="{{backgroundImageUrl}}" />
* AND <img data-background-image="{{backgroundImageUrl}}" class="image-onload-target hidden" />
*
***/
var angular = require('angular');
angular.module('BackgroundImage', [])
.directive('backgroundImage', [
"$timeout",
function ($timeout) {
return function(scope, element, attrs){
attrs.$observe('backgroundImage', function(value) {
/***
*
* Define a callback to trigger once the image loads.
* The value provided to this callback = the value
* passed to attrs.$observe() above
*
***/
var imageLoadedCallback = function(value) {
// once the image load event triggers, remove the event
// listener to ensure the event is called only once
fadeOut();
target.removeEventListener('load', imageLoadedCallback);
$timeout(function() {
fadeIn(value);
}, 700);
}
/***
*
* Define fade in / out events to be called once a new image
* is passed to the attrs.backgroundImage in the directive
*
***/
var fadeOut = function() {
element.css({'opacity': '0'})
};
var fadeIn = function(value) {
element.css({
'background': 'url(' + value +') no-repeat center center fixed',
'background-size' : 'cover',
'opacity': '1'
});
};
// add an onload event to the hidden-full-screen-image
var target = document.querySelector('.image-onload-target');
target.addEventListener('load', imageLoadedCallback(value));
});
};
}]);
Travailler avec Angular me rend amoureuse Réagis d'autant plus ...
Sur la base de la réponse de pkdkk et des sources Angular.js 1.3.6, ma solution est la même (la partie animation CSS est celle utilisée pour la variable ngShow
):
// Copied from the Angular's sources.
var NG_HIDE_CLASS = 'ng-hide';
var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
app.directive('myFadeIn', function($animate, $timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs){
element.addClass("ng-hide");
element.on('load', function() {
$timeout(function () {
$animate.removeClass(element, NG_HIDE_CLASS, {
tempClasses: NG_HIDE_IN_PROGRESS_CLASS
});
});
});
}
}
});