1+ <!doctype html>
2+ < html ng-app ="Demo " ng-controller ="AppController ">
3+ < head >
4+ < meta charset ="utf-8 " />
5+
6+ < title >
7+ Cross-Fading Images With AngularJS
8+ </ title >
9+
10+ < style type ="text/css ">
11+
12+ p .viewport {
13+ border-radius : 5px 5px 5px 5px ;
14+ box-shadow : 1px 1px 5px # 454545 ;
15+ height : 400px ;
16+ position : relative ;
17+ width : 400px ;
18+ }
19+
20+ p .viewport img .fader {
21+ border-radius : 5px 5px 5px 5px ;
22+ display : none ;
23+ height : 400px ;
24+ left : 0px ;
25+ position : absolute ;
26+ top : 0px ;
27+ width : 400px ;
28+ z-index : 2 ;
29+ }
30+
31+ p .viewport img .fader .show {
32+ display : block ;
33+ transition : opacity 250ms ease ;
34+ }
35+
36+ p .viewport img .fader .fadeOut {
37+ opacity : 0 ;
38+ }
39+
40+ p .viewport img .image {
41+ border-radius : 5px 5px 5px 5px ;
42+ display : block ;
43+ height : 400px ;
44+ width : 400px ;
45+ }
46+
47+ p .nav {
48+ cursor : default ;
49+ text-align : center ;
50+ width : 400px ;
51+ }
52+
53+ p .nav a {
54+ background-color : # FAFAFA ;
55+ border : 1px solid # CCCCCC ;
56+ border-radius : 3px 3px 3px 3px ;
57+ color : # 333333 ;
58+ display : inline-block ;
59+ padding : 4px 9px 2px 9px ;
60+ text-decoration : none ;
61+ }
62+
63+ </ style >
64+ </ head >
65+ < body >
66+
67+ < h1 >
68+ Cross-Fading Images With AngularJS
69+ </ h1 >
70+
71+ < p bn-fade-helper class ="viewport ">
72+
73+ < img
74+ ng-src ="{{ image.source }} "
75+ title ="{{ image.title }} "
76+ class ="image "
77+ />
78+
79+ </ p >
80+
81+ < p class ="nav ">
82+ < a ng-click ="showImage( 1 ) "> 1</ a > -
83+ < a ng-click ="showImage( 2 ) "> 2</ a > -
84+ < a ng-click ="showImage( 3 ) "> 3</ a > -
85+ < a ng-click ="showImage( 4 ) "> 4</ a > -
86+ < a ng-click ="showImage( 5 ) "> 5</ a > -
87+ < a ng-click ="showImage( 6 ) "> 6</ a >
88+ </ p >
89+
90+
91+ <!-- Load jQuery and AngularJS from the CDN. -->
92+ < script
93+ type ="text/javascript "
94+ src ="//code.jquery.com/jquery-2.0.0.min.js ">
95+ </ script >
96+ < script
97+ type ="text/javascript "
98+ src ="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js ">
99+ </ script >
100+ < script type ="text/javascript ">
101+
102+
103+ // Create an application module for our demo.
104+ var app = angular . module ( "Demo" , [ ] ) ;
105+
106+
107+ // -------------------------------------------------- //
108+ // -------------------------------------------------- //
109+
110+
111+ // I control the root of the application.
112+ app . controller (
113+ "AppController" ,
114+ function ( $scope ) {
115+
116+ // I am the collection of images to show.
117+ $scope . images = [
118+ {
119+ source : "frances-1.jpg" ,
120+ title : "What are you smirking about?"
121+ } ,
122+ {
123+ source : "frances-2.jpg" ,
124+ title : "No makeup - no problem."
125+ } ,
126+ {
127+ source : "frances-3.jpg" ,
128+ title : "Grace and beauty."
129+ } ,
130+ {
131+ source : "frances-4.jpg" ,
132+ title : "Another smirk."
133+ } ,
134+ {
135+ source : "frances-5.jpg" ,
136+ title : "What are you looking at?"
137+ } ,
138+ {
139+ source : "frances-6.jpg" ,
140+ title : "Saddness."
141+ }
142+ ] ;
143+
144+ // Default to a random image.
145+ $scope . image = getRandomImage ( ) ;
146+
147+
148+ // ---
149+ // PUBLIC METHODS.
150+ // ---
151+
152+
153+ // I show the image at the given index.
154+ $scope . showImage = function ( index ) {
155+
156+ // Use -1 to adjust image for zero-based array.
157+ $scope . image = $scope . images [ index - 1 ] ;
158+
159+ } ;
160+
161+
162+ // ---
163+ // PRIVATE METHODS.
164+ // ---
165+
166+
167+ // I return a random image from the current collection.
168+ function getRandomImage ( ) {
169+
170+ var imageCount = $scope . images . length ;
171+
172+ var index = Math . floor (
173+ ( Math . random ( ) * imageCount * 2 ) % imageCount
174+ ) ;
175+
176+ return ( $scope . images [ index ] ) ;
177+
178+ }
179+
180+ }
181+ ) ;
182+
183+
184+ // -------------------------------------------------- //
185+ // -------------------------------------------------- //
186+
187+
188+ // I provide a "Fade" overlay for the primary image whenever
189+ // the primary image source changes. This allows for a "softer"
190+ // transition from image to image.
191+ app . directive (
192+ "bnFadeHelper" ,
193+ function ( ) {
194+
195+ // I alter the DOM to add the fader image.
196+ function compile ( element , attributes , transclude ) {
197+
198+ element . prepend ( "<img class='fader' />" ) ;
199+
200+ return ( link ) ;
201+
202+ }
203+
204+
205+ // I bind the UI events to the $scope.
206+ function link ( $scope , element , attributes ) {
207+
208+ var fader = element . find ( "img.fader" ) ;
209+ var primary = element . find ( "img.image" ) ;
210+
211+ // Watch for changes in the source of the primary
212+ // image. Whenever it changes, we want to show it
213+ // fade into the new source.
214+ $scope . $watch (
215+ "image.source" ,
216+ function ( newValue , oldValue ) {
217+
218+ // If the $watch() is initializing, ignore.
219+ if ( newValue === oldValue ) {
220+
221+ return ;
222+
223+ }
224+
225+ // If the fader is still fading out, don't
226+ // bother changing the source of the fader;
227+ // just let the previous image continue to
228+ // fade out.
229+ if ( isFading ( ) ) {
230+
231+ return ;
232+
233+ }
234+
235+ initFade ( oldValue ) ;
236+
237+ }
238+ ) ;
239+
240+
241+ // I prepare the fader to show the previous image
242+ // while fading out of view.
243+ function initFade ( fadeSource ) {
244+
245+ fader
246+ . prop ( "src" , fadeSource )
247+ . addClass ( "show" )
248+ ;
249+
250+ // Don't actually start the fade until the
251+ // primary image has loaded the new source.
252+ primary . one ( "load" , startFade ) ;
253+
254+ }
255+
256+
257+ // I determine if the fader is currently fading
258+ // out of view (that is currently animated).
259+ function isFading ( ) {
260+
261+ return (
262+ fader . hasClass ( "show" ) ||
263+ fader . hasClass ( "fadeOut" )
264+ ) ;
265+
266+ }
267+
268+
269+ // I start the fade-out process.
270+ function startFade ( ) {
271+
272+ // The .width() call is here to ensure that
273+ // the browser repaints before applying the
274+ // fade-out class (so as to make sure the
275+ // opacity doesn't kick in immediately).
276+ fader . width ( ) ;
277+
278+ fader . addClass ( "fadeOut" ) ;
279+
280+ setTimeout ( teardownFade , 250 ) ;
281+
282+ }
283+
284+
285+ // I clean up the fader after the fade-out has
286+ // completed its animation.
287+ function teardownFade ( ) {
288+
289+ fader . removeClass ( "show fadeOut" ) ;
290+
291+ }
292+
293+ }
294+
295+
296+ // Return the directive configuration.
297+ return ( {
298+ compile : compile ,
299+ restrict : "A"
300+ } ) ;
301+
302+ }
303+ ) ;
304+
305+
306+ </ script >
307+
308+ </ body >
309+ </ html >
0 commit comments