$timeout 服务未根据指令更新 angular 控制器
$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>
I had some trouble getting this to work here in Whosebug, 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.
因此,如果您在时间轴有时间转到下一张幻灯片(索引在用户控制之外递增)之前单击下一张、上一张或底部的任何直接转到圆圈按钮,这将正常工作。但是,当时间轴播放下一张幻灯片时,控制器中的索引并不知道此更改,并且变得不同步。有人指出我使用 $timeout 服务来解决这个问题,但它仍然无法正常工作。非常感谢任何帮助。
演示中有相当多的代码需要整理,但您有两个无效的函数引用,例如:
onComplete: updateCurrentIndex(2)
首先,这些是硬编码的值,其次,它们将立即被调用,而不是在 onComplete
触发时如您所期望的那样:
要将函数作为引用传递,您不能使用 ()
,因此正确的方法是:
onComplete: updateCurrentIndex
但是由于您需要传递参数,因此您需要这样的东西:
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);
}
我刚刚弄明白了。我的问题如下:onComplete:updateCurrentIndex、onCompleteParams:[nextIndex]
我是这样传递的:onComplete: updateCurrentIndex(2)
是的,它正在立即执行。现在可以使用了。
"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 Whosebug, 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.
因此,如果您在时间轴有时间转到下一张幻灯片(索引在用户控制之外递增)之前单击下一张、上一张或底部的任何直接转到圆圈按钮,这将正常工作。但是,当时间轴播放下一张幻灯片时,控制器中的索引并不知道此更改,并且变得不同步。有人指出我使用 $timeout 服务来解决这个问题,但它仍然无法正常工作。非常感谢任何帮助。
演示中有相当多的代码需要整理,但您有两个无效的函数引用,例如:
onComplete: updateCurrentIndex(2)
首先,这些是硬编码的值,其次,它们将立即被调用,而不是在 onComplete
触发时如您所期望的那样:
要将函数作为引用传递,您不能使用 ()
,因此正确的方法是:
onComplete: updateCurrentIndex
但是由于您需要传递参数,因此您需要这样的东西:
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);
}
我刚刚弄明白了。我的问题如下:onComplete:updateCurrentIndex、onCompleteParams:[nextIndex]
我是这样传递的:onComplete: updateCurrentIndex(2)
是的,它正在立即执行。现在可以使用了。