Как вы привязываетесь к Angular -UI событиям карусели?
Я использую Angular -UI карусель, и мне нужно сообщить, что мои диаграммы Google перерисовываются после того, как они соскользнули в поле зрения. Несмотря на то, что я читал, я не могу показаться, что это связано с событием.
Смотрите мою попытку:
http://plnkr.co/edit/Dt0wdzeimBcDlOONRiJJ?p=preview
HTML:
<carousel id="myC" interval="myInterval">
<slide ng-repeat="slide in slides" active="slide.active">
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{$index}}</h4>
<p>{{slide.text}}</p>
</div>
</slide>
</carousel>
При загрузке документа:
$('#myC').live('slid.bs.carousel', function (event) { console.log("slid"); } );
Он должен работать примерно так:
http://jsfiddle.net/9fwuq/ - не angular -ui карусель
Возможно, существует более Angular способ зацепиться за то, что моя диаграмма скользнула в поле зрения?
Ответы
Ответ 1
Есть 3 способа, о которых я могу думать, и это зависит от ваших требований.
Для примера см. http://plnkr.co/edit/FnI8ZX4UQYS9mDUlrf6o?p=preview.
-
использовать $scope. $смотреть отдельный слайд, чтобы проверить, стал ли он активным.
$scope.$watch('slides[0].active', function (active) {
if (active) {
console.log('slide 0 is active');
}
});
-
используйте $scope. $watch с пользовательской функцией, чтобы найти активный слайд.
$scope.$watch(function () {
for (var i = 0; i < slides.length; i++) {
if (slides[i].active) {
return slides[i];
}
}
}, function (currentSlide, previousSlide) {
if (currentSlide !== previousSlide) {
console.log('currentSlide:', currentSlide);
}
});
-
используйте настраиваемую директиву для перехвата select() функции директивы карусели.
.directive('onCarouselChange', function ($parse) {
return {
require: 'carousel',
link: function (scope, element, attrs, carouselCtrl) {
var fn = $parse(attrs.onCarouselChange);
var origSelect = carouselCtrl.select;
carouselCtrl.select = function (nextSlide, direction) {
if (nextSlide !== this.currentSlide) {
fn(scope, {
nextSlide: nextSlide,
direction: direction,
});
}
return origSelect.apply(this, arguments);
};
}
};
});
и используйте его следующим образом:
$scope.onSlideChanged = function (nextSlide, direction) {
console.log('onSlideChanged:', direction, nextSlide);
};
и в шаблоне html:
<carousel interval="myInterval" on-carousel-change="onSlideChanged(nextSlide, direction)">
...
Надеюсь, что эта помощь:)
Ответ 2
AngularUI Bootstrap изменил соглашения об именах для контроллеров, поскольку thery префикс всех своих контроллеров с префиксом uib
, поэтому ниже представлено обновленное решение исходного решения, предоставленное runTarm
:
Angular:
.directive('onCarouselChange', function($parse) {
return {
require: '^uibCarousel',
link: function(scope, element, attrs, carouselCtrl) {
var fn = $parse(attrs.onCarouselChange);
var origSelect = carouselCtrl.select;
carouselCtrl.select = function(nextSlide, direction, nextIndex) {
if (nextSlide !== this.currentSlide) {
fn(scope, {
nextSlide: nextSlide,
direction: direction,
nextIndex: this.indexOfSlide(nextSlide)
});
}
return origSelect.apply(this, arguments);
};
}
};
});
Angular с TypeScript:
module App.Directive {
export class CarouselChange implements ng.IDirective {
public require: string = '^uibCarousel';
constructor(private $parse: ng.IParseService) { }
public link: ng.IDirectiveLinkFn = (scope: ng.IScope, element: ng.IAugmentedJQuery, attributes: any, carouselCtrl: any) => {
var fn = this.$parse(attributes.carouselChange);
var origSelect = carouselCtrl.select;
carouselCtrl.select = function(nextSlide, direction) {
if (nextSlide !== this.currentSlide) {
fn(scope, {
nextSlide: nextSlide,
direction: direction
});
}
return origSelect.apply(this, arguments);
};
}
static Factory(): ng.IDirectiveFactory {
var directive: ng.IDirectiveFactory = ($parse: ng.IParseService) => new CarouselChange($parse);
directive['$inject'] = ["$parse"];
return directive;
}
}
}
Спасибо,
Ответ 3
Следуя ответом, данным runTarm. Если вы хотите узнать индекс следующего слайда, вы должны добавить что-то вроде этого:
.directive('onCarouselChange', function ($parse) {
return {
require: 'carousel',
link: function (scope, element, attrs, carouselCtrl) {
var fn = $parse(attrs.onCarouselChange);
var origSelect = carouselCtrl.select;
carouselCtrl.select = function (nextSlide, direction,nextIndex) {
if (nextSlide !== this.currentSlide) {
fn(scope, {
nextSlide: nextSlide,
direction: direction,
nextIndex:this.indexOfSlide(nextSlide)
});
}
return origSelect.apply(this, arguments);
};
}
};
})
Затем в контроллере вам просто нужно сделать это, чтобы поймать новый индекс:
$scope.onSlideChanged = function (nextSlide, direction, nextIndex) {
console.log(nextIndex);
}
Ответ 4
Мне удалось изменить ответ runTarm так, чтобы он вызывал обратный вызов после того, как слайд закончил сканирование (т.е. скользящая анимация закончилась). Здесь мой код:
.directive('onCarouselChange', function ($animate, $parse) {
return {
require: 'carousel',
link: function (scope, element, attrs, carouselCtrl) {
var fn = $parse(attrs.onCarouselChange);
var origSelect = carouselCtrl.select;
carouselCtrl.select = function (nextSlide, direction) {
if (nextSlide !== this.currentSlide) {
$animate.on('addClass', nextSlide.$element, function (elem, phase) {
if (phase === 'close') {
fn(scope, {
nextSlide: nextSlide,
direction: direction,
});
$animate.off('addClass', elem);
}
});
}
return origSelect.apply(this, arguments);
};
}
};
});
Тайна заключается в использовании обработчика события $animate для вызова нашей функции после завершения анимации.
Ответ 5
здесь альтернативный метод, который использует контроллеры, где-то между runTarm # 2 и # 3.
оригинальный HTML + новый div:
<carousel id="myC" interval="myInterval">
<slide ng-repeat="slide in slides" active="slide.active">
<div ng-controller="SlideController"> <!-- NEW DIV -->
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{$index}}</h4>
<p>{{slide.text}}</p>
</div>
</div>
</slide>
</carousel>
пользовательский контроллер:
.controller('SlideController',
function($log, $scope) {
var slide = $scope.slide;
$scope.$watch('slide.active', function(newValue) {
if (newValue) {
$log.info("ACTIVE", slide.id);
}
});
});
Ответ 6
И если вы просто хотите начать воспроизведение видео при появлении слайда и приостановить его:
JS
{# Uses angular v1.3.20 & angular-ui-bootstrap v0.13.4 Carousel #}
{% addtoblock "js" %}<script type="text/javascript">
angular.module('videoplay', []).directive('videoAutoCtrl', function() {
return {
require: '^carousel',
link: function(scope, element, attrs) {
var video = element[0];
function setstate(visible) {
if(visible) {
video.play();
} else {
video.pause();
}
}
// Because $watch calls $parse on the 1st arg, the property doesn't need to exist on first load
scope.$parent.$watch('active', setstate);
}
};
});
</script>{% endaddtoblock %}
{% addtoblock "ng-requires" %}videoplay{% endaddtoblock %}
ПРИМЕЧАНИЕ. Имеются дополнительные биты для Django
HTML:
<carousel interval="15000">
<slide>
<video class="img-responsive-upscale" video-auto-ctrl loop preload="metadata">
<source src=
...