简体   繁体   English

$超时服务未从指令更新角度控制器

[英]$timeout service not updating angular controller from directive

 "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. 我在使它在stackoverflow中工作时遇到了一些麻烦,但是提供了有效的codepen链接。 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. 我的问题是,与$ timeout结合使用并在每个子时间轴末尾的onComplete发生的updateCurrentIndex(nextIndex)在播放时似乎无法传达索引的正常增量。

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. 我已经指出$ timeout服务是解决此问题的一种方法,但是它仍然无法正常工作。 Any help greatly appreciated. 任何帮助,不胜感激。

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: 首先,这些是硬编码的值,其次,它们不会像您期望的那样在onComplete触发时立即被调用:

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);
}

I just figured it out. 我只是想通了。 My problem was the following: onComplete:updateCurrentIndex, onCompleteParams:[nextIndex] 我的问题如下:onComplete:updateCurrentIndex,onCompleteParams:[nextIndex]

I was passing it this: onComplete: updateCurrentIndex(2) 我正在通过它:onComplete:updateCurrentIndex(2)

and yes it was executing immediately. 是的,它立即执行。 it works now. 现在有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM