Skip to content

Commit d77b174

Browse files
committed
Adding image cross-fade with AngularJS.
1 parent 34cafb9 commit d77b174

File tree

9 files changed

+333
-0
lines changed

9 files changed

+333
-0
lines changed
29 KB
Loading
18.8 KB
Loading
28.6 KB
Loading
30.8 KB
Loading
31.7 KB
Loading
20.1 KB
Loading
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
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>

demos/index.htm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
<!doctype html>
3+
<html>
4+
<head>
5+
<script type="text/javascript">
6+
7+
location.href = "../";
8+
9+
</script>
10+
</head>
11+
<body>
12+
13+
<p>
14+
Redirecting...
15+
</p>
16+
17+
</body>
18+
</html>

index.htm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,11 @@ <h1>
1212
JavaScript Demos by Ben Nadel (for <a href="http://www.bennadel.com">BenNadel.com</a>)
1313
</h1>
1414

15+
<ol>
16+
<li>
17+
<a href="./demos/image-cross-fade-angularjs/">Cross-Fading Images With AngularJS</a>
18+
</li>
19+
</ol>
20+
1521
</body>
1622
</html>

0 commit comments

Comments
 (0)