skip to Main Content
"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>

Working Codepen Link

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


  1. Chosen as BEST ANSWER

    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.


  2. There is quite a bit of code to sort out in demo but you have two invalid function references like:

    onComplete: updateCurrentIndex(2)
    

    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:

    onComplete: updateCurrentIndex
    

    But since you need to pass parameters you would need something like:

    onComplete: function(arg1,arg2){ // not sure what arguments are available
       var newIndex = // I'm not sure how to get index in this event
       updateCurrentIndex(newIndex);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search