"use strict";
angular.module("appBanner", [])
.controller('bannerCtrl', function($scope) {
$scope.slides = ["auto", "boatowners", "commercial"];
$scope.currentIndex = 0;
$scope.setCurrentSlideIndex = function (index) {
$scope.currentIndex = index;
$scope.currentSlideIndex = $scope.slides[$scope.currentIndex];
}
$scope.isCurrentSlideIndex = function (index) {
return $scope.currentIndex === index;
};
$scope.prevSlide = function () {
$scope.currentIndex = ($scope.currentIndex > 0) ? --$scope.currentIndex : $scope.slides.length - 1;
$scope.setCurrentSlideIndex($scope.currentIndex);
};
$scope.nextSlide = function () {
$scope.currentIndex = ($scope.currentIndex < $scope.slides.length - 1) ? ++$scope.currentIndex : 0;
$scope.setCurrentSlideIndex($scope.currentIndex);
};
})
.directive('banner', function($timeout) {
return {
link: function postLink(scope, element, attrs) {
var progressBar = angular.element(".progress");
var bannerNav = angular.element(".bannerNav");
var navCircle = angular.element(".bannerNav.navCircle");
var imgSlides = angular.element(".imgSlide");
var slideTime = 1.5;
TweenMax.set(imgSlides, {
autoAlpha: 0,
display: "none"
});
TweenMax.set(progressBar, {
autoAlpha: 0
});
var tlMaster = initMasterTimeline(imgSlides, progressBar, slideTime);
scope.getWidth = function() {
return $(element).width();
};
scope.play = function(newIndexValue) {
tlMaster.play(newIndexValue);
};
scope.$watch('slideshowHover', function(newValue) {
if (newValue === true) TweenMax.to(bannerNav, 0.5, {
autoAlpha: 0.85
})
else TweenMax.to(bannerNav, 0.5, {
autoAlpha: 0.25
})
});
scope.$watch('currentSlideIndex', function(newIndexValue) {
scope.play(newIndexValue);
});
scope.$watch(scope.getWidth, function(width) {
element.css('height', width * 0.4);
});
function updateCurrentIndex(index) {
$timeout(function() {
scope.setCurrentSlideIndex(index);
});
}
function setProgress(timeline, progressBar) {
TweenMax.set(progressBar, {
scaleX: timeline.progress()
});
}
function initMasterTimeline(imgSlides, progressBar, slideTime) {
var tlAuto = initAutoTimeline(imgSlides, progressBar, slideTime);
var tlBoatowners = initBoatownersTimeline(imgSlides, progressBar, slideTime);
var tlCommercial = initCommercialTimeline(imgSlides, progressBar, slideTime);
var tlMaster = new TimelineMax({
repeat: -1
});
tlMaster.set(progressBar, {
scaleX: 0,
transformOrigin: "left"
})
.add(tlAuto, "auto")
.add(tlBoatowners, "boatowners")
.add(tlCommercial, "commercial");
return tlMaster;
}
function initAutoTimeline(imgSlides, progressBar, slideTime) {
var stayTime = 10; //for now, can make each timeline as long as you want later
var tlAuto = new TimelineLite({
onUpdate: setProgress,
onUpdateParams: ["{self}", progressBar]
});
var autoNavCircle = $(".navCircle")[0];
tlAuto.set(imgSlides[0], {
display: "block"
})
.to(progressBar, slideTime, {
autoAlpha: 1
}, 0)
.to(imgSlides[0], slideTime, {
autoAlpha: 1
}, 0)
.to(imgSlides[0], slideTime, {
autoAlpha: 0
}, stayTime)
.to(progressBar, slideTime, {
autoAlpha: 0
}, stayTime)
.set(imgSlides[0], {
display: "none",
onComplete: updateCurrentIndex(1)
})
return tlAuto;
}
function initBoatownersTimeline(imgSlides, progressBar, slideTime) {
var stayTime = 10; //for now, can make each timeline as long as you want later
var tlBoatowners = new TimelineLite({
onUpdate: setProgress,
onUpdateParams: ["{self}", progressBar]
});
var boatownersNavCircle = $(".navCircle")[1];
tlBoatowners.set(imgSlides[1], {
display: "block"
})
.to(progressBar, slideTime, {
autoAlpha: 1
}, 0)
.to(imgSlides[1], slideTime, {
autoAlpha: 1
}, 0)
.to(imgSlides[1], slideTime, {
autoAlpha: 0
}, stayTime)
.to(progressBar, slideTime, {
autoAlpha: 0
}, stayTime)
.set(imgSlides[1], {
display: "none",
onComplete: updateCurrentIndex(2)
});
return tlBoatowners;
}
function initCommercialTimeline(imgSlides, progressBar, slideTime) {
var stayTime = 10; //for now, can make each timeline as long as you want later
var tlCommercial = new TimelineLite({
onUpdate: setProgress,
onUpdateParams: ["{self}", progressBar]
});
var commercialNavCircle = $(".navCircle")[2];
tlCommercial.set(imgSlides[2], {
display: "block"
})
.to(progressBar, slideTime, {
autoAlpha: 1
}, 0)
.to(imgSlides[2], slideTime, {
autoAlpha: 1
}, 0)
.to(imgSlides[2], slideTime, {
autoAlpha: 0
}, stayTime)
.to(progressBar, slideTime, {
autoAlpha: 0
}, stayTime)
.set(imgSlides[2], {
display: "none",
onComplete: updateCurrentIndex(0)
});
return tlCommercial;
}
}
}
})
#slideshow{
position: relative;
}
.imgSlide{
position: absolute;
width: 100%;
}
.progress{
position: absolute;
width: 100%;
height:3px;
background: #F1F1F1;
z-index: 5;
}
.navCircleContainer {
position: absolute;
display: flex;
justify-content: space-between;
padding: 5px;
bottom: 2.5px;
left: 12.5%;
width: 75%;
height: auto;
}
.navCircle {
opacity: 0.25;
}
div.navCircle {
position: relative;
border-radius: 100%;
background:#F1F1F1;
}
.navCircle.active {
opacity:1;
}
@media only screen and (min-width: 768px) {
div.navCircle{
width: 30px;
height: 30px;
}
}
@media only screen and (max-width: 767px) {
div.navCircle{
width: 15px;
height: 15px;
}
}
.navCircle span {
position: absolute;
color:#F1F1F1;
font-weight: bold;
left: 50%;
-moz-transform: translateX(-50%);
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
}
@media only screen and (min-width: 768px) {
.navCircle span {
bottom: 30px;
}
}
@media only screen and (max-width: 767px) {
.navCircle span {
bottom: 20px;
}
}
.navArrow {
position: absolute;
top: 50%;
color:#F1F1F1;
-moz-transform: translateY(-50%);
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
#navArrowLeft {
left: 0%;
}
#navArrowRight {
right: 0%;
}
img {
width: 100%;
height: auto;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.15.0/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/jquery.gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<div ng-app="appBanner" ng-controller="bannerCtrl" banner id="slideshow" ng-mouseover="slideshowHover = true" ng-mouseleave="slideshowHover = false" ng-init="slideshowHover = false">
<!-- green field with lake -->
<img class="imgSlide" src="http://cdn.morguefile.com/imageData/public/files/i/imma/08/l/14089545069hw66.jpg" >
<!-- waterfall -->
<img class="imgSlide" src="http://cdn.morguefile.com/imageData/public/files/i/imma/preview/fldr_2012_09_09/file3231347173227.jpg" >
<!-- red sunset -->
<img class="imgSlide" src="http://cdn.morguefile.com/imageData/public/files/i/imma/preview/fldr_2012_07_22/file541342984669.jpg" >
<div class="progress"></div>
<div id="navArrowLeft" class="navArrow bannerNav" ng-click="prevSlide()">
<div class="hidden-xs">
<i class="fa fa-angle-double-left fa-5x"></i>
</div>
<div class="hidden-sm hidden-md hidden-lg">
<i class="fa fa-angle-double-left fa-2x"></i>
</div>
</div>
<div id="navArrowRight" class="navArrow bannerNav" ng-click="nextSlide()">
<div class="hidden-xs">
<i class="fa fa-angle-double-right fa-5x"></i>
</div>
<div class="hidden-sm hidden-md hidden-lg">
<i class="fa fa-angle-double-right fa-2x"></i>
</div>
</div>
<div class="navCircleContainer">
<div class="navCircle bannerNav" ng-active="isCurrentSlideIndex === 0" ng-mouseover="navCircleAutoHover = true" ng-mouseleave="navCircleAutoHover = false" ng-init="navCircleAutoHover = false" ng-click="play('auto')"><span class="bannerNav fade" ng-show="navCircleAutoHover === true">Lake</span></div>
<div class="navCircle bannerNav" ng-active="isCurrentSlideIndex === 1" ng-mouseover="navCircleBoatownersHover = true" ng-mouseleave="navCircleBoatownersHover = false" ng-init="navCircleBoatownersHover = false" ng-click="play('boatowners')"><span class="bannerNav fade" ng-show="navCircleBoatownersHover === true">Waterfall</span></div>
<div class="navCircle bannerNav" ng-active="isCurrentSlideIndex === 2" ng-mouseover="navCircleCommercialHover = true" ng-mouseleave="navCircleCommercialHover = false" ng-init="navCircleCommercialHover = false" ng-click="play('commercial')"><span class="bannerNav fade" ng-show="navCircleCommercialHover === true"> Sunset</span></div>
</div>
</div>
I had some trouble getting this to work here in stackoverflow, but the working codepen link is provided. My problem is that the updateCurrentIndex(nextIndex) that works in conjunction with $timeout and happens onComplete at the end of each child timeline does not seem to communicate the normal increments of the index when it plays.
So, this works fine if you click next, previous, or any of the direct go to circle buttons at the bottom before the timeline has time to go to next slide (index incremented outside user control). However, when the timeline plays next slide, the index in the controller is not aware of this change and it becomes out of sync. I have been pointed towards the $timeout service as a way to fix this, but it still is not working. Any help greatly appreciated.
2
Answers
I just figured it out. My problem was the following: onComplete:updateCurrentIndex, onCompleteParams:[nextIndex]
I was passing it this: onComplete: updateCurrentIndex(2)
and yes it was executing immediately. it works now.
There is quite a bit of code to sort out in demo but you have two invalid function references like:
First these are hard coded values and second they will be invoked immediately not when
onComplete
fires as you are expecting:To pass a function as reference you can’t use
()
so correct way would be:But since you need to pass parameters you would need something like: