AngularJS animate image on src change

前端 未结 8 2098
一整个雨季
一整个雨季 2020-12-30 09:26

I have an AnuglarJS app, where I load/change some images from a webservice...

Controller

.controller(\'PlayerCtrl\', function($scope, programService         


        
相关标签:
8条回答
  • 2020-12-30 10:05

    Update 1.5.x - with Angular 1.5.x you can use ngAnimateSwap to achieve this effect.

    0 讨论(0)
  • 2020-12-30 10:07

    I know its late but according to @Aides answer i am posting here an working example that how can you achieve animation with change in ng-src using ngAnimateSwap (with Angular 1.5.x). I hope this helps someone in future:

    HTML Markup:

    <!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);
    

    Working plunker here.

    0 讨论(0)
  • 2020-12-30 10:08

    You can't animate an img src change. You can, however, have multiple images and animate their opacity.

    HTML/angular template

    <div class="image-container">
        <img src="image-one.jpg" ng-show="showImageOne">
        <img src="image-two.jpg" ng-show="showImageTwo">
    </div>
    

    CSS

    .image-container {
        position: relative;
    }
    
    .image-container img {
        position: absolute;
        transition: 1s opacity linear;
    }
    
    .image-container img.ng-hide {
        display: block!important;
        opacity: 0;
    }
    
    0 讨论(0)
  • 2020-12-30 10:12

    In case others end up here wanting to perform animations on change of a background image, I'll post what I ended up using.

    This directive assumes it's attached to a template like this:

    <!-- 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>
    

    We want to set the background image source for the <div>, but attach an onload event so we know when the new image has arrived. To do that, we use an <img> with a .hidden class that has .hidden {display: none;}. Then we use the following directive to dynamically set the div's background image source and perform a fade to white then back from white on image change:

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

    Working with Angular makes me love React all the more...

    0 讨论(0)
  • 2020-12-30 10:12

    My solution to this problem is to watch for changes on ng-src and using a timeout function to add a class which does the fadeIn effect.

    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;
        }
    
    0 讨论(0)
  • 2020-12-30 10:18

    As christoph has mentioned, you should watch using $watch on the image source change. But first make sure you use the ng-src rather than the src for the image tag.

    <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() {});
    })
    
    0 讨论(0)
提交回复
热议问题