Sometime ago I used the ngb-carousel and animate to left-rigth and rigth-left (it's time ngb-carousel has no animation) in this SO (the second update) Since 8.0.0 you has animation.
I feel you can not use :enter and :left because only when enter the imagen is loaded. So, based in the before SO, you can define an animation like
const animation = [ state('outright', style({ transform: `translateX(100%)` })), state('outleft', style({ transform: `translateX(-100%)` })), transition('void=>inleft',[ style({transform:`translateX(0)`}), ]), transition('void=>outleft',[ style({transform:`translateX(-100%)`}), ]), transition('*=>inright',[ style({transform:`translateX(-100%)`}), animate('260ms ease-in',style({ transform: `translateX(0)` })) ]), transition('*=>inleft',[ style({transform:`translateX(100%)`}), animate('260ms ease-in',style({ transform: `translateX(0)` })) ]), transition('*=>outleft', [ animate('260ms ease-in', style({ transform: `translateX(-100%)` })) ]), transition('*=>outright', [ animate('260ms ease-in',style({ transform: `translateX(100%)` })) ]), ]
see that a slider can be outleft,outrigth,inleft or inrigth
So I define an array like
slideControl: any[] = this.images.map((x,index)=>index ? 'outleft' : 'inleft')
And when we click next or prev we call to the function onSlide
onNext() { if (this.counter != this.images.length - 1) { this.counter++; this.onSlide(this.counter,this.counter-1,'right') } } onPrevious() { if (this.counter > 0) { this.counter--; this.onSlide(this.counter,this.counter+1,'left') } } onSlide(current,prev,direction) { this.slideControl=this.slideControl.map((x, index) => { return (index == current) ?'in' + direction : (index == prev) ? 'out' + direction : x }) }
The last piece of jigsaw are the .html
<div class="wrapper" > <div *ngFor="let img of images; let i = index" [@animImageSlider]="slideControl[i]"> <img #slide [src]="img" style="height:200px; width:200px" /> </div> </div>
And the .css, See that this animation work if all the images are placed in the position top:0, left:0 of the wrapper
.wrapper{ overflow: hidden; width:200px; } .wrapper::after { display: block; clear: both; content: ""; } .wrapper div{ float:left; margin-right: -100%; }
the stackblitz
Update Well, the function onSlide can be simply:
onSlide(current,prev,direction) { this.slideControl[current]='in' + direction; this.slideControl[prev]='out' + direction }
And there're a point I don't like that it's the "hardcode" with of wrapper. We can take advantage of the event load and use a variable with in the way
width:number=0; onLoad(el:any) { this.width=el.getBoundingClientRect().width }
So, our .html can be like
<div class="wrapper" [style.width.px]="width" > <div *ngFor="let img of images; let i = index" [@animImageSlider]="slideControl[i]"> <img #slide (load)="i==0 && onLoad(slide)" [src]="img" /> </div> </div>
See that the function "onLoad" it's only called for the first slide
NOTE: If we want a "infinite carousel" we can change reemplace the functions next and prev by
change(direction:string) { const incr=direction=='right'?1:-1 const prev=this.counter this.counter=(this.counter+this.images.length+incr)%this.images.length this.slideControl[this.counter]='in' + direction; this.slideControl[prev]='out' + direction }
And use
<button type="button" (click)="change('left')" > Previous </button> <button type="button" (click)="change('right')"> Next </button>
NOTE: I update the stackblitz with this two changes