Background Slideshow with AngularJS and Bootstrap

As part of a project we wanted to have the front page with a nice rotating background for the jumbotron. There are a number of carousel components and scripts that can be easily found online but mostly they use the img tag and/or require a root absolute div which means it won’t automatically resize to the jumbotron content. I wanted a jumbotron that would resize to the content and also provide a nice seamless transition for the images. So, I sat down and rolled my own.

Firstly you need to set up a jumbotron component:

.jumbotron-slideshow {
position: relative;
background-color: transparent; // replace the standard bootstrap background color
.slideshow {
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* Layer the images so that the visible one is below all the others,
* but the previously active one fades out to reveal the visible one
* below */
transition: opacity 1s;
opacity: 0;
&.visible {
transition: none;
opacity: 1;
z-index: -1;
}
}
}
.jumbotron-slideshow { position: relative; background-color: transparent; // replace the standard bootstrap background color .slideshow { background-size: cover; background-repeat: no-repeat; background-position: 50% 50%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; /* Layer the images so that the visible one is below all the others, * but the previously active one fades out to reveal the visible one * below */ transition: opacity 1s; opacity: 0; &.visible { transition: none; opacity: 1; z-index: -1; } } }
.jumbotron-slideshow {
    position: relative;
    background-color: transparent;  // replace the standard bootstrap background color

    .slideshow {
        background-size: cover;
        background-repeat: no-repeat;
        background-position: 50% 50%;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        
        /* Layer the images so that the visible one is below all the others,
         * but the previously active one fades out to reveal the visible one
         * below */
        transition: opacity 1s;
        opacity: 0;
        
        &.visible {
            transition: none;
            opacity: 1;
            z-index: -1;
        }
    }   
}       

And then the HTML:

<div class="jumbotron jumbotron-slideshow">
<div ng-bg-slideshow="[ 'images/bg1.jpg', 'images/bg2.jpg', ... ]" interval=5000></div>
... content that you want ...
<div class="jumbotron jumbotron-slideshow"> <div ng-bg-slideshow="[ 'images/bg1.jpg', 'images/bg2.jpg', ... ]" interval=5000></div> ... content that you want ...
<div class="jumbotron jumbotron-slideshow">
    <div ng-bg-slideshow="[ 'images/bg1.jpg', 'images/bg2.jpg', ... ]" interval=5000></div>

    ... content that you want ...

Create the angular template to generate the image divs:

<div ng-repeat="img in images"
class="slideshow" ng-class="{ visible: active_image == $index }" ng-style="{ 'background-image': 'url(' + img + ')' }">
</div>
<div ng-repeat="img in images" class="slideshow" ng-class="{ visible: active_image == $index }" ng-style="{ 'background-image': 'url(' + img + ')' }"> </div>
<div ng-repeat="img in images"
        class="slideshow" ng-class="{ visible: active_image == $index }" ng-style="{ 'background-image': 'url(' + img + ')' }">
    </div>  

And finally the Angular component:

app.directive("ngBgSlideshow", function($interval) {
return {
restrict: 'A',
scope: {
ngBgSlideshow: '&',
interval: '=',
},
templateUrl: 'views/components/slideshow.html',
link: function( scope, elem, attrs ) {
scope.$watch( 'ngBgSlideshow', function(val) {
scope.images = val();
scope.active_image = 0;
});
var change = $interval(function() {
scope.active_image++;
if( scope.active_image >= scope.images.length )
scope.active_image = 0;
}, scope.interval || 1000 );
scope.$on('$destroy', function() {
$interval.cancel( change );
});
}
};
});
app.directive("ngBgSlideshow", function($interval) { return { restrict: 'A', scope: { ngBgSlideshow: '&', interval: '=', }, templateUrl: 'views/components/slideshow.html', link: function( scope, elem, attrs ) { scope.$watch( 'ngBgSlideshow', function(val) { scope.images = val(); scope.active_image = 0; }); var change = $interval(function() { scope.active_image++; if( scope.active_image >= scope.images.length ) scope.active_image = 0; }, scope.interval || 1000 ); scope.$on('$destroy', function() { $interval.cancel( change ); }); } }; });
app.directive("ngBgSlideshow", function($interval) {
    return {
        restrict: 'A',
        scope: {
            ngBgSlideshow: '&',
            interval: '=',
        },
        templateUrl: 'views/components/slideshow.html',
        link: function( scope, elem, attrs ) {
            scope.$watch( 'ngBgSlideshow', function(val) {
                scope.images = val();
                scope.active_image = 0;
            });

            var change = $interval(function() {
                scope.active_image++;
                if( scope.active_image >= scope.images.length )
                    scope.active_image = 0;
            }, scope.interval || 1000 );
        
            scope.$on('$destroy', function() {
                $interval.cancel( change );
            });
        }
    };  
});         

Note: If you want to be able to programatically change the interval you’ll need to add a watch that recreates the interval when the interval attribute changes.

2 thoughts on “Background Slideshow with AngularJS and Bootstrap”

  1. I am stuck trying to get the images to appear on the screen. My question is:
    Does the list of images come from –> ng-bg-slideshow=”[ ?

    So when you reference the images in the ng-repeat –> ng-repeat=”img in images” each img is coming from the above list provided to “ng-bg-slideshow”?

    Or are you initializing the list in a controller which is not shown in the provided code?

Leave a Reply

Your email address will not be published. Required fields are marked *