it-swarm.com.ru

Анимация изображения AngularJS на src change

У меня есть приложение AnuglarJS, где я загружаю/меняю некоторые изображения из веб-сервиса ...

Контроллер

.controller('PlayerCtrl', function($scope, programService) {
    ....
    programService.refresh(function(data) {
        $scope.program = data;
    });
    ....

Шаблон

<img src="{{program.image}}" />

Когда мое приложение обновляется из веб-сервиса, изображения меняются, как и ожидалось, я просто хочу сделать постепенное исчезновение/исчезновение, когда это происходит, как это можно сделать?

Можно ли всегда делать постепенное исчезновение/изменение изображения при смене источника изображения?

10
pkdkk

Спасибо за ответы - 

Я закончил тем, что делал это, и это работает;)

--- Директива ---

.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");
            });
        }
    };
})

--- Шаблон ---

<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;
}
18
pkdkk

Обновите 1.5.x - с помощью Angular 1.5.x, вы можете использовать ngAnimateSwap для достижения этого эффекта.

11
Aides

Как уже упоминал Кристоф , вы должны смотреть, используя $watch при смене источника изображения. Но сначала убедитесь, что вы используете ng-src вместо src для тега 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() {});
})
0
Dinesh

Я знаю, что уже поздно, но согласно ответу @Aides я публикую здесь рабочий пример того, как можно добиться анимации с изменением ng-src с использованием ngAnimateSwap (с Angular 1.5.x). Я надеюсь, что это поможет кому-то в будущем:

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

Рабочий плункер здесь .

0
Seeker

Мое решение этой проблемы - следить за изменениями в ng-src и использовать функцию тайм-аута для добавления класса, который выполняет эффект fadeIn.

HTML

<img ng-src="your-logic-will-go-here" class="animate-show ng-hide-add" fade-in>

Угловой код

.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
Arun

В случае, если другие захотят выполнить анимацию при смене фонового изображения, я опубликую то, что я использовал в конечном итоге.

Эта директива предполагает, что она прикреплена к шаблону, например так:

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

Мы хотим установить источник фонового изображения для <div>, но прикрепить событие onload, чтобы мы знали, когда появилось новое изображение. Для этого мы используем <img> с классом .hidden, который имеет .hidden {display: none;}. Затем мы используем следующую директиву для динамической установки источника фонового изображения div и выполняем переход на белый, а затем на белый при изменении изображения:

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

    });
  };
}]);

Работа с Angular заставляет меня любить React еще больше ...

0
duhaime

Основываясь на ответе pkdkk и источниках Angular.js 1.3.6, мое решение таково (часть CSS-анимации используется для стандартной 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
                    });
                });
            });
        }
    }
});
0
Vladius