@@ -10,7 +10,7 @@ import {
1010 OnInit ,
1111 Output
1212} from '@angular/core' ;
13- import { Subscription } from 'rxjs' ;
13+ import { fromEvent , Subscription , withLatestFrom , zipWith } from 'rxjs' ;
1414
1515import { IntersectionService } from '../../services/intersection.service' ;
1616import { IListenersConfig , ListenersService } from '../../services/listeners.service' ;
@@ -58,6 +58,12 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
5858 * @type {'hover' | 'focus' | 'click' }
5959 */
6060 @Input ( ) pause : Triggers | Triggers [ ] | false = 'hover' ;
61+ /**
62+ * Support left/right swipe interactions on touchscreen devices.
63+ * @type boolean
64+ * @default true
65+ */
66+ @Input ( ) touch : boolean = true ;
6167 /**
6268 * Set type of the transition.
6369 * @type {'slide' | 'crossfade' }
@@ -90,6 +96,7 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
9096 private timerId ! : any ;
9197 private intersectingSubscription ?: Subscription ;
9298 private activeItemInterval = 0 ;
99+ private swipeSubscription ?: Subscription ;
93100
94101 constructor (
95102 @Inject ( CarouselConfig ) private config : CarouselConfig ,
@@ -110,13 +117,15 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
110117 this . clearListeners ( ) ;
111118 this . carouselStateSubscribe ( false ) ;
112119 this . intersectionServiceSubscribe ( false ) ;
120+ this . swipeSubscribe ( false ) ;
113121 }
114122
115123 ngAfterContentInit ( ) : void {
116124 this . intersectionService . createIntersectionObserver ( this . hostElement ) ;
117125 this . intersectionServiceSubscribe ( ) ;
118126 this . carouselState . state = { activeItemIndex : this . activeIndex , animate : this . animate } ;
119127 this . setListeners ( ) ;
128+ this . swipeSubscribe ( ) ;
120129 }
121130
122131 private setListeners ( ) : void {
@@ -140,9 +149,11 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
140149 set visible ( value ) {
141150 this . _visible = value ;
142151 }
152+
143153 get visible ( ) {
144154 return this . _visible ;
145155 }
156+
146157 private _visible : boolean = true ;
147158
148159 setTimer ( ) : void {
@@ -185,4 +196,25 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
185196 this . intersectingSubscription ?. unsubscribe ( ) ;
186197 }
187198 }
199+
200+ private swipeSubscribe ( subscribe : boolean = true ) : void {
201+ if ( this . touch && subscribe ) {
202+ const carouselElement = this . hostElement . nativeElement ;
203+ const touchStart$ = fromEvent < TouchEvent > ( carouselElement , 'touchstart' ) ;
204+ const touchEnd$ = fromEvent < TouchEvent > ( carouselElement , 'touchend' ) ;
205+ const touchMove$ = fromEvent < TouchEvent > ( carouselElement , 'touchmove' ) ;
206+ this . swipeSubscription = touchStart$ . pipe ( zipWith ( touchEnd$ . pipe ( withLatestFrom ( touchMove$ ) ) ) )
207+ . subscribe ( ( [ touchstart , [ touchend , touchmove ] ] ) => {
208+ touchstart . stopPropagation ( ) ;
209+ touchmove . stopPropagation ( ) ;
210+ const distanceX = touchstart . touches [ 0 ] . clientX - touchmove . touches [ 0 ] . clientX ;
211+ if ( Math . abs ( distanceX ) > 0.3 * carouselElement . clientWidth && touchstart . timeStamp <= touchmove . timeStamp ) {
212+ const nextIndex = this . carouselState . direction ( distanceX > 0 ? 'next' : 'prev' ) ;
213+ this . carouselState . state = { activeItemIndex : nextIndex } ;
214+ }
215+ } ) ;
216+ } else {
217+ this . swipeSubscription ?. unsubscribe ( ) ;
218+ }
219+ }
188220}
0 commit comments