programing

ng-hide CSS 이행이 완료될 때까지 요소를 표시하지 않습니까?

easyjava 2023. 3. 25. 14:10
반응형

ng-hide CSS 이행이 완료될 때까지 요소를 표시하지 않습니까?

간단한 질문이지만 구현에 문제가 있습니다.다음과 같은 DOM 설정이 있는 경우:

<h1 class="fade" ng-repeat="child in parent.children" ng-show="parent.activeChild== child ">@{{ child.title }}</h1>

?activeChild의 of의 parent모델 변경, 모델이 변경되기 에 현재 활성 상태인 아이를 페이드아웃하고 변경 후 새로 활성 상태인 아이를 페이드아웃하려면 어떻게 해야 합니까?

CSS 이행만으로 대략적으로 동작하고 있습니다.

.fade.ng-hide-add {
    transition:opacity 1s ease;
}

.fade.ng-hide-remove {
    transition:opacity 1s ease 1s;
}

.fade.ng-hide-add {
    opacity:1;

    &.ng-hide-add-active {
        opacity:0;
    }
}

.fade.ng-hide-remove {
    opacity:0;

    &.ng-hide-remove-active {
        opacity:1;
    }
}

단, 이로 인해 이 문제가 발생합니다(Plunkr).

GIF

기본적으로, 저는 제 애니메이션을 체인하고 싶습니다.ng-animate 문서를 읽어보려고 했지만 원하는 효과를 전달하는데 필요한 구문에 문제가 있습니다.

Angular docs에서 이런 걸 본 적이 있어요.

app.animation('.fade', [function() {
    return {
        addClass: function(element, className, doneFn) {
        },
        removeClass: function(element, className, doneFn) {
        }
    };
}]);
  • 죠?className? 페이드인/페이드아웃하면서 신청하는 클래스입니까?가가기 기대 ?? ???
  • 죠?doneFn애니메이션이 완성되면 실행되는 기능인가?가들 ??
  • 하면 요?addClass ★★★★★★★★★★★★★★★★★」removeClass 경우, 이미 「」가 되어 있는 는,doneFn

목표

Angular의 ngAnimate 모듈을 사용하여 CSS 또는 JS에서 직접 작업 애니메이션을 생성하고 싶습니다.어떻게 하면 좋을까요?

왜 따로 쓰세요?<h1>각 제목에 대해. 한 에 쓸 수 요.<h1>태그를 지정하여 제목을 표시합니다.

당신의 문제에 대한 데모를 작성했고, 당신의 요구 사항을 성공적으로 완료했습니다.

갱신필

": " "를 되어 있습니다.ngAnimate★★★★★★★★★★를 사용하는 경우ngAnimate '클래스', '클래스', '클래스'가 됩니다..ng-hide 요소를 숨깁니다.

여기 앱용 컨트롤러가 있습니다.

app2.controller("testController", ["$scope", "$timeout", function ($scope, $timeout) {

    $scope.heading = {};
    $scope.heading.show = true;

    $scope.parent = {};
    $scope.parent.children = ["A", "B", "C", "D"];
    $scope.parent.activeChild = "A";

    $scope.changeHeading = function (child) {
        $timeout(function () {
            $scope.parent.activeChild = child;
            $scope.heading.show = true;
        }, 1000);

    }
}]);

그리고 당신의 html 페이지는 이렇게 되어 있어야 합니다.

<div ng-controller="testController">
    <h1 class="myAnimateClass" ng-show="heading.show" ng-class="{fadeIn : heading.fadeInModel==true, fadeOut : heading.fadeOutModel}"> {{parent.activeChild}} </h1>
    <p ng-repeat="child in parent.children" ng-click="heading.show = false;changeHeading(child)">{{child}}</p>
</div>

CSS3를 사용하여 페이드인 및 페이드아웃 애니메이션을 구현했습니다.

.myAnimateClass {
    -webkit-transition: opacity 1s ease-in-out;
    -moz-transition: opacity 1s ease-in-out;
    -o-transition: opacity 1s ease-in-out;
    -ms-transition: opacity 1s ease-in-out;
    transition: opacity 1s ease-in-out;
    opacity:1;
}

.myAnimateClass.ng-hide {
    opacity: 0;
}

설명.

하기 위해 신신요 to to to, to는 to to to 했습니다.ng-class ★★★★★★★★★★★★★★★★★」$timeout J자단위로JS.

저는 요.<h1>태그를 지정하여 제목을 표시합니다. 돼요.$scope.parent.activeChild

두 변수를 했습니다.$scope.heading.fadeOutModel ★★★★★★★★★★★★★★★★★」$scope.heading.fadeInModel를 및 fadeIn ★★★★★★★★★★★★★★★★★」fadeOut역동적으로

할 때 했습니다.fadeOut당신의 표제까지.js app.js의 기능했습니다.changeHeading().

.1000페이드 아웃 애니메이션을 완료하는 데 밀리초입니다.이 지나면 새합니다.fadeIn그래서 페이드인 애니메이션을 시작합니다.

도움이 되길 바랍니다!!!

선택에 따라 특정 요소를 표시하는 보다 ng-animate한 방법은 다음을 사용하는 것입니다.ngSwitch이 지시어는 스코프식을 기반으로 템플릿의 DOM 구조를 조건부로 스왑하기 위해 사용됩니다.여기 예가 있습니다.

HTML

<button ng-repeat="item in items" ng-click="parent.selection = item">{{ item }}</button>
<div class="animate-switch-container" ng-switch on="parent.selection">
  <div class="animate-switch" ng-switch-when="foo">foo</div>
  <div class="animate-switch" ng-switch-when="bar">bar</div>
</div>

자바스크립트

$scope.items = ['foo', 'bar'];
$scope.parent = {
  selection: $scope.items[0]
}

CSS

.animate-switch-container {
  position:relative;
  height:40px;
  overflow:hidden;
}
.animate-switch {
  padding:10px;

}
.animate-switch.ng-animate {
  transition:opacity 1s ease;

}
.animate-switch.ng-leave.ng-leave-active,
.animate-switch.ng-enter {
  opacity: 0;
}
.animate-switch.ng-leave,
.animate-switch.ng-enter.ng-enter-active {
  opacity: 1;
}

이것은 체인은 아니지만 Angular의 ngAnimate 모듈을 사용하여 직접 작업하는 애니메이션입니다.또한 Angular의 웹사이트에 그 가 있습니다.

하시면 됩니다..animation자바스크립트를 들어, 「」, 「」의 .addClass ★★★★★★★★★★★★★★★★★」removeClass

app.animation('.fade', [function() {
    return {
        addClass: function(element, className, doneFn) {
        },
        removeClass: function(element, className, doneFn) {
        }
    };
}]);

는 다음 중 하나의 메서드에서 요소에서 클래스를 추가 또는 삭제하고 있음을 검출하면 Angular에 의해 호출됩니다.

  • {{ }}들어 예를 들면, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.<span class="{{shouldFade ? 'fade' : ''}}">....
  • 「」를 사용합니다.ng-class예컨대<span ng-class="{fade: shouldFade}">...
  • 「 」의 $animate명령어로 서비스를 제공합니다.예.$animate.addClass(element, 'fade') ★★★★★★★★★★★★★★★★★」$animate.removeClass(element, 'fade')

className이 뭐죠?페이드인/페이드아웃하면서 신청하는 클래스인가요?내가 기대하는 수업이요?

이 예에서는 다음과 같이 됩니다.fade이 예에서는 이미 이것이 관련된 클래스 이름임이 분명하기 때문에 조금 이상합니다.클래스를 는, 그 이 .

doneFn은 무엇을 의미합니까?애니메이션이 완성되면 실행되는 기능인가?뭐가 들어가는데?

Javascript 애니메이션을 정의한 후 호출하는 기능입니다.예를 들어, 아무것도 하지 않는 애니메이션을 모두 정의하려면:

addClass: function(element, className, doneFn) {
  doneFn();
},

전화를 걸면 Angular에게 애니메이션이 완료되었음을 알립니다. 하면 것은 the, the the른 the the the the가 ng-animate래스입입니니다

이미 doneFn이 있는 경우 addClass 및 removeClass 함수는 어떻게 해야 합니까?

타임아웃이나 서드파티 라이브러리를 사용하여 요소를 변경하는 등의 코드를 입력합니다.하세요.doneFn「1」 「1」:

addClass: function(element, className, doneFn) {
  element.css('opacity', 0.5);
  setTimeout(function() {
    doneFn();
  }, 1000);
},

Angular의 ngAnimate 모듈을 사용하여 CSS 또는 JS에서 직접 작업 애니메이션을 생성하고 싶습니다.

이것은 위의 답변과는 큰 관계가 없습니다!제가 실제 사례를 하고 있다면, 적어도 제가 생각할 수 있는 다른 것은 너무 복잡하기 때문에 요소를 절대적으로 배치하지 않을까 하는 생각이 강하게 듭니다.

실제로 하여 애니메이션을 으로 ngAnimate를 하는 것이 .$animate.addClass ★★★★★★★★★★★★★★★★★」$animate.removeClass완료 시 약속을 반환합니다.요소를 숨길 때 반환되는 약속의 끝에 체인을 연결하려면 중앙 위치에서 호출하여 어떤 요소가 보이고, 숨겨지고, 표시되는지 추적해야 합니다.

이 방법은 2개의 커스텀 디렉티브를 사용하는 것입니다.숨김을 하게 , '보여주다'처럼 사용될 수 있습니다.ngShow 명령어는 할 수 , 이 는 의 체인을 합니다.ng-hide 관련 를의 클래스(및 관련 애니메이션)ng-hide서로 , 할 수 있습니다 을 사용하다ngShowUnique ★★★★★★★★★★★★★★★★★」ngShowUniqueController예를 들어 다음과 같습니다.

<div ng-show-unique-controller>
  <h1 class="fade" ng-repeat="child in parent.children" ng-show-unique="parent.activeChild == child">@{{child.title}}</h1>
</div>

다음과 같이 구현할 수 있습니다.

app.directive('ngShowUniqueController', function($q, $animate) {
  return {
    controller: function($scope, $element) {
      var elements = [];
      var expressions = [];
      var watchers = [];
      var unregisterWatchers = null;
      var visibleElement = null;

      function registerWatchers() {
        unregisterWatchers = $scope.$watchGroup(expressions, function(vals) {
          var newCurrentIndex = vals.indexOf(true);
          var addPromise;

          if (visibleElement) {
            // Set a fixed height, as there is a brief interval between
            // removal of this class and addition of another
            $element.css('height', $element[0].getBoundingClientRect().height + 'px'); 
            addPromise = $animate.addClass(visibleElement, 'ng-hide');
          } else {
            addPromise = $q.when();
          }
          visibleElement = elements[newCurrentIndex] || null;
          if (!visibleElement) return;

          addPromise.then(function() {
            if (visibleElement) {
              $animate.removeClass(visibleElement, 'ng-hide').then(function() {
                $element.css('height', '');
              });
            }
          })
        });
      }   

      this.register = function(element, expression) {
        if (unregisterWatchers) unregisterWatchers();
        elements.push(element[0]);
        expressions.push(expression);
        registerWatchers();

        // Hide elements initially
        $animate.addClass(element, 'ng-hide');
      };

      this.unregister = function(element) {
        if (unregisterWatchers) unregisterWatchers();
        var index = elements.indexOf(element[0]);
        if (index > -1) {
          elements.splice(index, 1);
          expressions.splice(index, 1);
        }
        registerWatchers();
      };
    } 
  };
});

app.directive('ngShowUnique', function($animate) {
  return {
    require: '^ngShowUniqueController',
    link: function(scope, element, attrs, ngShowUniqueController) {
      ngShowUniqueController.register(element, function() {
        return scope.$eval(attrs.ngShowUnique);
      });

      scope.$on('$destroy', function() {
        ngShowUniqueController.unregister(element);
      });
    }
  };
});

이것은, http://plnkr.co/edit/1eJUou4UaH6bnAN0nJn7?p=preview 에서 확인할 수 있습니다.솔직히 말해서 이건 좀 허튼소리야.

번에 하나의 요소만 보여주는 ngRepeat을 사용하는 것은 좋지 않은 생각이라고 생각합니다.하나의 요소만 표시되므로 parent.activeChild 속성을 직접 사용할 수 있습니다.

다음 내용을 확인하십시오.

주의: 이 스니펫을 10분 만에 작성했습니다.최적화되지 않아 버그가 발생할 수 있습니다.스타터로 사용할 수 있습니다. : )

(function(window, angular, APP) {
  APP
    .value('menuObject', {
      name: 'Main Navigation',
      current: null,
      children: [{
        label: 'Don\'t ng-show element until ng-hide CSS transition is complete?',
        url: 'http://stackoverflow.com/questions/33336249/dont-ng-show-element-until-ng-hide-css-transition-is-complete',
        isCurrent: false
      },
      {
        label: 'Hitmands - Linkedin',
        url: 'http://it.linkedin.com/in/giuseppemandato',
        isCurrent: false
      },
      {
        label: 'Hitmands - Github',
        url: 'https://github.com/hitmands',
        isCurrent: false
      },
      {
        label: 'Hitmands - StackOverflow',
        url: 'http://stackoverflow.com/users/4099454/hitmands',
        isCurrent: false
      }
  ]})
  .directive('menu', function(menuObject, $q) {
    function menuCtrl($scope, $element) {
      $scope.parent = menuObject;
      
      this.getCurrentChild = function() {
        return $scope.parent.current;
      };
      this.getDomContext = function() {
        return $element;
      };
      this.setCurrentChild = function(child) {
        return $q.when($scope.parent)
        .then(function(parent) {
          parent.current = child;
          return parent;
        })
        .then(function(parent) {
          return parent.children.forEach(function(item) {
            item.isCurrent = child && (item.label === child.label);
          });
        })
      };
    }
    
    return {
      restrict: 'A',
      templateUrl: 'embedded-menutemplate',
      scope: {},
      controller: menuCtrl
    };
  })
  .directive('menuItem', function($animate, $q, $timeout) {
    
    function menuItemPostLink(iScope, iElement, iAttributes, menuCtrl) {
      iElement.bind('click', setCurrentTitle);
      iScope.$on('$destroy', function() {
        iElement.unbind('click', setCurrentTitle);
      })
      
      function setCurrentTitle(event) {
        event.preventDefault();
        var title;
        
        return $q
        .when(menuCtrl.getDomContext())
        .then(function(_menuElement) {
          title = angular.element(
            _menuElement[0].querySelector('#menuItemCurrent')
          );
        })
        .then(function() {
          return title.addClass('fade-out');
        })
        .then(function() {
          return $timeout(menuCtrl.setCurrentChild, 700, true, iScope.child);
        })
        .then(function() {
          return title.removeClass('fade-out');
        })
      }
    }
				
    return {
      require: '^menu',
      link: menuItemPostLink,
      restrict: 'A'
    };
  })
;

})(window, window.angular, window.angular.module('AngularAnimationExample', ['ngAnimate']));
nav {
		text-align: center;
	}
	.link {
		display: inline-block;
		background-color: lightseagreen;
		color: black;
		padding: 5px 15px;
		margin: 1em;
	}
	#menuItemCurrent {
		padding: 1em;
		text-transform: uppercase;
		border: 1px solid black;
	}
	#menuItemCurrent span {
		transition: 500ms opacity linear;
		opacity: 1;
	}
	#menuItemCurrent.fade-out span {
		opacity: 0;
	}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script>

<article ng-app="AngularAnimationExample">
  
  <nav menu></nav>

  <script id="embedded-menutemplate" type="text/ng-template">

	<nav >
		<a menu-item class="link" ng-repeat="child in parent.children track by $index" ng-bind="child.label"  ng-href="{{ child.url }}"></a>
	
		<h1 id="menuItemCurrent"><span  ng-bind="parent.current.url || 'NoMenuCurrentSelected'"></span></h1>	
		{{ parent.current || json }}
	</nav>
	
  </script>
</article>

문제는 H1이 부모 내에 위치한 블록레벨 요소이기 때문에 오버랩이 허용되지 않는다는 것입니다.그래서 하나의 애니메이션이 나타나고 있는 애니메이션을 아래로 밀어내리는 것을 볼 수 있습니다.

여기서 더 명확하게 확인할 수 있습니다: 데모

이 문제를 해결하려면 블록 수준 요소 H1을 유지하고 해당 위치를 상대적으로 설정하여 페이지 전체 흐름에서 상대적인 위치를 유지할 수 있습니다.다음으로 자 SPAN 요소를 부모 H1에 대한 절대 위치(absolute positioning)로 설정합니다.이를 통해 모든 스판 요소가 서로 겹칠 수 있습니다.

CSS

.fade {
  opacity: 1;
  position: relative;
}

.fade.ng-hide-add {
    transition:opacity 1s ease;
    position: absolute;
}

.fade.ng-hide-remove {
    transition:opacity 1s ease 1s;
    position: absolute;
}

.fade.ng-hide-add {
  opacity:1;
}

.fade.ng-hide-add.ng-hide-add-active {
  opacity:0;
}

.fade.ng-hide-remove {
    opacity:0;
}

.fade.ng-hide-remove.ng-hide-remove-active {
    opacity:1;
}

HTML

  <body ng-controller="MainCtrl">
    <h1><span class="fade" ng-repeat="child in parent.children" ng-show="parent.activeChild == child ">@{{child.title}}</span></h1>
    <button ng-repeat="child in parent.children" ng-click="parent.activeChild = child">{{ child.title }}</button>
  </body>

그런데 한 가지 문제가 있는데...SPAN 요소에는 절대적인 위치가 있기 때문에 애니메이션 생성 시 흐름에서 삭제되며 부모 H1은 SPAN 콘텐츠에 맞게 크기를 조정할 수 없습니다.이로 인해 SPAN이 예기치 않게 점프합니다.

이 문제를 해결하는 방법은 SPAN 리피터 뒤에 빈 공간을 추가하는 것입니다.따라서 ngRepeat SPAN이 절대적인 위치 결정으로 인해 일반 흐름에서 분리되면 ngRepeat 외부에 있는 빈 공간이 H1의 간격을 유지합니다.

여기 작동하는 플런커가 있습니다.

모든 최신 브라우저에서 지원되는 transitionend 이벤트에 대해 알아보는 것이 좋습니다.

element.addEventListener('transitionend', callback, false);

이에 대한 빠른 답변 - 이 문제를 해결하기 위해 저는 항상 콘텐츠를 절대적인 위치에 두었습니다.이렇게 하면 전환이 이루어졌을 때 동일한 위치에 유지됩니다.

은 돔의 .inline ★★★★★★★★★★★★★★★★★」inline-block가 표시됩니다.

언급URL : https://stackoverflow.com/questions/33336249/dont-ng-show-element-until-ng-hide-css-transition-is-complete

반응형