Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit d97b658

Browse files
committed
docs(ngAnimate): add docs for animation anchoring
1 parent 90e424b commit d97b658

File tree

2 files changed

+205
-0
lines changed

2 files changed

+205
-0
lines changed

docs/app/assets/css/docs.css

+4
Original file line numberDiff line numberDiff line change
@@ -695,3 +695,7 @@ ul.events > li {
695695
padding-bottom:0px;
696696
}
697697
}
698+
699+
iframe[name="example-anchoringExample"] {
700+
height:400px;
701+
}

src/ngAnimate/module.js

+201
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,207 @@
392392
*
393393
* To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}.
394394
*
395+
* ## Animation Anchoring (via `ng-animate-ref`)
396+
*
397+
* ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between
398+
* structural areas of an application (like views) by pairing up elements using an attribute
399+
* called `ng-animate-ref`.
400+
*
401+
* Let's say for example we have two views that are managed by `ng-view` and we want to show
402+
* that there is a relationship between two components situated in different views. By using the
403+
* `ng-animate-ref` attribute we can identify that the two components are paired together and we
404+
* can then attach an animation, which is triggered when the view changes.
405+
*
406+
* ```html
407+
* <!-- index.html -->
408+
* <div ng-view class="view-animation">
409+
* </div>
410+
*
411+
* <!-- home.html -->
412+
* <a href="#/banner-page">
413+
* <img src="./banner.jpg" ng-animate-ref="banner">
414+
* </a>
415+
*
416+
* <!-- banner-page.html -->
417+
* <img src="./banner.jpg" ng-animate-ref="banner">
418+
* ```
419+
*
420+
* Now, when the view changes (once the link is clicked), ngAnimate will examine the
421+
* HTML contents to see if there is a match reference between any components in the view
422+
* that is leaving and the view that is entering. It will then attempt to trigger a CSS
423+
* animation on the `.view-animation-anchor` CSS class (notice how `.view-animation` is
424+
* a shared CSS class on the ng-view element? This means that view-animation will apply to
425+
* both the enter and leave animations).
426+
*
427+
* The two images match since they share the same ref value. ngAnimate will now apply a
428+
* suffixed version of each of the shared CSS classes with `-anchor`. Therefore we will
429+
* have a shared class of `view-animation-anchor` which we can use to setup our transition animation.
430+
*
431+
* We can now attach a transition onto the `.view-animation-anchor` CSS class and then
432+
* ngAnimate will handle the entire transition for us as well as the addition and removal of
433+
* any changes of CSS classes between the elements:
434+
*
435+
* ```css
436+
* .view-animation-anchor {
437+
* /&#42; this animation will last for 1 second since there are
438+
* two phases to the animation (an `in` and an `out` phase) &#42;/
439+
* transition:0.5s linear all;
440+
* }
441+
* ```
442+
*
443+
* There are two stages for an anchor animation: `out` and `in`. The `out` stage happens first and that
444+
* is when the element is animated away from its origin. Once that animation is over then the `in` stage
445+
* occurs which animates the element to its destination. The reason why there are two animations is to
446+
* give enough time for the enter animation on the new element to be ready.
447+
*
448+
* The example above sets up a transition for both the in and out phases, but we can also target the out or
449+
* in phases directly via `ng-anchor-out` and `ng-anchor-in`.
450+
*
451+
* ```css
452+
* .view-animation-anchor.ng-anchor-out {
453+
* transition: 0.5s linear all;
454+
*
455+
* /&#42; the scale will be applied during the out animation,
456+
* but will be animated away when the in animation runs &#42;/
457+
* transform: scale(1.2);
458+
* }
459+
*
460+
* .view-animation-anchor.ng-anchor-in {
461+
* transition: 1s linear all;
462+
* }
463+
* ```
464+
*
465+
*
466+
*
467+
*
468+
* ### Anchoring Demo
469+
*
470+
<example module="anchoringExample"
471+
name="anchoringExample"
472+
id="anchoringExample"
473+
deps="angular-animate.js;angular-route.js"
474+
animations="true">
475+
<file name="index.html">
476+
<a href="#/">Home</a>
477+
<hr />
478+
<div class="view-container">
479+
<div ng-view class="view"></div>
480+
</div>
481+
</file>
482+
<file name="script.js">
483+
angular.module('anchoringExample', ['ngAnimate', 'ngRoute'])
484+
.config(['$routeProvider', function($routeProvider) {
485+
$routeProvider.when('/', {
486+
templateUrl: 'home.html',
487+
controller: 'HomeController as home'
488+
});
489+
$routeProvider.when('/profile/:id', {
490+
templateUrl: 'profile.html',
491+
controller: 'ProfileController as profile'
492+
});
493+
}])
494+
.run(['$rootScope', function($rootScope) {
495+
$rootScope.records = [
496+
{ id:1, title: "Miss Beulah Roob" },
497+
{ id:2, title: "Trent Morissette" },
498+
{ id:3, title: "Miss Ava Pouros" },
499+
{ id:4, title: "Rod Pouros" },
500+
{ id:5, title: "Abdul Rice" },
501+
{ id:6, title: "Laurie Rutherford Sr." },
502+
{ id:7, title: "Nakia McLaughlin" },
503+
{ id:8, title: "Jordon Blanda DVM" },
504+
{ id:9, title: "Rhoda Hand" },
505+
{ id:10, title: "Alexandrea Sauer" }
506+
];
507+
}])
508+
.controller('HomeController', [function() {
509+
//empty
510+
}])
511+
.controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) {
512+
var index = parseInt($routeParams.id, 10);
513+
var record = $rootScope.records[index - 1];
514+
515+
this.title = record.title;
516+
this.id = record.id;
517+
}]);
518+
</file>
519+
<file name="home.html">
520+
<h2>Welcome to the home page</h1>
521+
<p>Please click on an element</p>
522+
<a class="record"
523+
ng-href="#/profile/{{ record.id }}"
524+
ng-animate-ref="{{ record.id }}"
525+
ng-repeat="record in records">
526+
{{ record.title }}
527+
</a>
528+
</file>
529+
<file name="profile.html">
530+
<div class="profile record" ng-animate-ref="{{ profile.id }}">
531+
{{ profile.title }}
532+
</div>
533+
</file>
534+
<file name="animations.css">
535+
.record {
536+
display:block;
537+
font-size:20px;
538+
}
539+
.profile {
540+
background:black;
541+
color:white;
542+
font-size:100px;
543+
}
544+
.view-container {
545+
position:relative;
546+
}
547+
.view-container > .view.ng-animate {
548+
position:absolute;
549+
top:0;
550+
left:0;
551+
width:100%;
552+
min-height:500px;
553+
}
554+
.view.ng-enter {
555+
transition:0.5s linear all;
556+
transform:translateX(100%);
557+
}
558+
.view.ng-enter.ng-enter-active {
559+
transform:translateX(0%);
560+
}
561+
.view.ng-leave {
562+
transition:0.5s linear all;
563+
}
564+
.view.ng-leave.ng-leave-active {
565+
transform:translateX(-100%);
566+
}
567+
.view-anchor {
568+
transition:0.5s linear all;
569+
}
570+
</file>
571+
</example>
572+
*
573+
* ### How is the element transported?
574+
*
575+
* When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting
576+
* element is located on screen via absolute positioning. The cloned element will be placed inside of the root element
577+
* of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The
578+
* element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match
579+
* the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied
580+
* to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class
581+
* is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element
582+
* will become visible since the shim class will be removed.
583+
*
584+
* ### How is the morphing handled?
585+
*
586+
* CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out
587+
* what CSS classes differ between the starting element and the destination element. These different CSS classes
588+
* will be added/removed on the anchor element and a transition will be applied (the transition that is provided
589+
* in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will
590+
* make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that
591+
* do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since
592+
* the cloned element is placed inside of root element which is likely close to the body element).
593+
*
594+
* Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body.
595+
*
395596
*
396597
* ## Using $animate in your directive code
397598
*

0 commit comments

Comments
 (0)