Reputation: 586
I'm trying to animate Ngbcarousel navigation indicators (round dots indicating which slide the user is on) such that it scrolls to the right if the user clicks on, for example, the 5th indicator, and continues to scroll to the right if the user clicks on the 6th indicator onwards until it reaches the end.
I've combined the code from https://stackblitz.com/edit/ngu-carousel-ng6-7hxy9p?file=src/app/hello.component.ts with Ngbcarousel such that the navigation appears as dots.
Basically I got it to how I would like it to look like but I'm not sure how I can access Ngbcarousel dom structure and add animations to the ordered list (so when I press the 5th dot, the entire ordered list shifts to the left, showing more dots on the right)
Ideally, should look something like Instagram's carousel -> https://codepen.io/swarad07/pen/xmzQKm
carousel.component.html
<ngb-carousel
#carousel
class="profile-detail-carousel"
[showNavigationArrows]="false"
[showNavigationIndicators]="true"
data-interval="false"
(click)="navigateCarousel($event)"
>
<ng-template ngbSlide *ngFor="let imageID of imageIDs">
<img class="carousel-img" [src]="profile | profileImage: imageID" />
</ng-template>
<ng-template ngbSlide *ngIf="!imageIDs?.length">
<img class="carousel-img" [src]="{} | profileImage" />
</ng-template>
</ngb-carousel>
caroursel.component.ts
navigateCarousel(event) {
// checks what slideNumber was clicked
const slideNumber = parseInt(event && event.path[0].id.match(/\d+/)[0], 10);
if (slideNumber >= 5) {
console.log(this.carousel); // carousel ol element to scroll right
}
}
carousel.component.scss
.profile-detail-carousel .carousel-indicators {
display: flex;
justify-content: left;
bottom: -40px !important;
overflow: hidden;
list-style-type: none;
text-align: center;
padding: 12px;
margin: 0;
width: 105px;
white-space: nowrap;
box-sizing: border-box;
margin: auto;
li {
display: inline-block;
border-radius: 50%;
border: 2px solid rgba(0, 0, 0, 0.55);
padding: 4px;
margin: 0 3px;
transition-timing-function: cubic-bezier(0.17, 0.67, 0.83, 0.67);
transition: 0.4s;
height: 1px;
width: 1px;
&.active {
background: #6b6b6b;
transform: scale(1.2);
}
}
}
Appreciate your help thanks!
Upvotes: 0
Views: 2213
Reputation: 58019
puff are several, several thing to do.
First animate the carousel, see this question in SO
Second animate the indicators. if you want only show a few indicators, I thing that is better aproach create your own indicators
<div class="wrapper">
<div class="selectors" [@move]="{value: trans.value, params: {position:trans.position}}">
<ng-container *ngFor="let t of slidesValue">
<div class="selector" (click)="carousel.select(t)" [style.background-color]="carousel && t==carousel.activeId?'black':'transparent'">
</div>
</ng-container>
</div>
</div>
I create an array "slidesValues" with the name of slides
slidesValue=['id1','id2','id3','id4','id5','id6']
Well, the animation i think is
trigger('move', [
state('true', style({ transform: 'translateX({{position}})' }), { params: { position: '10px' } }),
state('false', style({ transform: 'translateX({{position}})' }), { params: { position: '10px' } }),
transition('* <=>*', animate('260ms ease-in'))
])
And in onSlide(event) I add (numIndicator are the indicator you can see, and a variable pos as the position)
let index=this.slidesValue.findIndex(x=>x==event.current)
if (index!=0 && index!=this.slidesValue.length-1)
{
if (index==this.pos+this.numIndicator-1)
this.pos++;
if (index==this.pos)
this.pos--;
this.trans={value:this.trans.value=!this.trans.value,position:-this.pos+'rem'}
}
I know is easy improve the code, but I left "as is" the final result in stackblitz
Update Really I don't like whe way to control the "position". IT's better that the position depends from "index" only. And as the calculate is a bit comple, I prefer that the array slidesValue becomes an array of object with two properties "name" and "pos", so in ngOnInit
ngOnInit()
{
let increment=this.numIndicator%2==0?0:.5
let first=this.numIndicator/2-increment;
let last=this.data.length-this.numIndicator/2-increment
this.slidesValue=this.data.map((x,index)=>{
return {
name:'id'+index,
pos:(index<first?first:index>last?last:index)
-this.numIndicator/2+increment
}
})
}
And the onSlide(event) becomes:
this.pos=this.slidesValue.find(x=>x.name==event.current).pos
this.trans={value:this.trans.value=!this.trans.value,position:-this.pos+'rem'}
The stackBlitz is updated too
Upvotes: 1