I have a ng-bootstrap Carousel in my Angular project and I would like to change a few things but am at a loss of how to go about it.
First, I would like to have a fade effect when the slide changes, at the moment the next image just appears.
Secondly, I want to have my own arrows and slide indicator or change the style! I have attempted to do that via CSS but none of my code seems to get accepted.
Below my slideshow-component:
images = [1, 2, 3, 4, 5, 6, 7].map(() => `https://picsum.photos/900/500?random&t=${Math.random()}`);
paused = false;
unpauseOnArrow = false;
pauseOnIndicator = false;
pauseOnHover = true;
@ViewChild('carousel', {static : true}) carousel: NgbCarousel;
togglePaused() {
if (this.paused) {
this.carousel.cycle();
} else {
this.carousel.pause();
}
this.paused = !this.paused;
}
onSlide(slideEvent: NgbSlideEvent) {
if (this.unpauseOnArrow && slideEvent.paused &&
(slideEvent.source === NgbSlideEventSource.ARROW_LEFT || slideEvent.source === NgbSlideEventSource.ARROW_RIGHT)) {
this.togglePaused();
}
if (this.pauseOnIndicator && !slideEvent.paused && slideEvent.source === NgbSlideEventSource.INDICATOR) {
this.togglePaused();
}
}
slideshow-component html
<ngb-carousel #carousel interval="3000" [pauseOnHover]="pauseOnHover" (slide)="onSlide($event)">
<ng-template ngbSlide *ngFor="let img of images; index as i">
<div class="picsum-img-wrapper">
<img [src]="img" alt="My image {{i + 1}} description">
</div>
</ng-template>
</ngb-carousel>
slideshow-component css
.picsum-img-wrapper {
img {
width: 100vw;
height: 100vh;
max-width: 100%;
display: block;
margin: 0;
}
}
.carousel-indicators > li {
visibility: hidden;
box-sizing: content-box;
flex: 0 1 auto;
width: 30px;
height: 30px;
border-radius: 20px;
margin-right: 3px;
margin-left: 3px;
text-indent: -999px;
cursor: pointer;
background-color: #fff;
background-clip: padding-box;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
opacity: .5;
transition: opacity .6s ease;
}
a.carousel-control-prev,
a.carousel-control-next {
span {
display: none;
}
}
you need use encapsulation:ViewEncapsulation.None (*)
This allow you override the css. In ngb-carousel, the class that contrl the items are .carousel-item and carousel-item.active. carousel-item has display:none and carouse-item.active has display:block, so you need change by opacity:0 and opacity:1. Use the own .css to make the transition.
Some like (see stackblitz
@Component({selector: 'ngbd-carousel-basic',
templateUrl: './carousel-basic.html',
encapsulation: ViewEncapsulation.None,
styles:[`
.carousel-item
{
display:block;
opacity:0;
transition: opacity 2s;
}
.carousel-item.active
{
display:block;
opacity:1;
transition: opacity 2s;
}
.carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 24 24'%3e%3cpath d='M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-1.568 18.005l-1.414-1.415 4.574-4.59-4.574-4.579 1.414-1.416 5.988 5.995-5.988 6.005z'/%3e%3c/svg%3e");
} .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 24 24'%3e%3cpath d='M0 12c0 6.627 5.373 12 12 12s12-5.373 12-12-5.373-12-12-12-12 5.373-12 12zm7.58 0l5.988-5.995 1.414 1.416-4.574 4.579 4.574 4.59-1.414 1.416-5.988-6.006z'/%3e%3c/svg%3e");
}
`]
}
)
Updated If you want to do the animation at "Angular style", you need override the class too
styles:[`
.carousel-item
{
display:block;
}
.carousel-caption
{
display:block
}
And create an animation like
animations: [
trigger('simpleFadeAnimation', [
state('false', style({opacity: 0})),
transition('*=>false', [
style({opacity: 1}),
animate(600 )
]),
transition('false=>*',
animate(600, style({opacity: 1})))
])
]
The .html it's look like to
<ngb-carousel #carousel *ngIf="images" interval=0 wrap="true" >
<ng-template ngbSlide id="id1">
<div class="picsum-img-wrapper" [@simpleFadeAnimation]="carousel &&carousel.activeId=='id1'">
<img [src]="images[0]" width="100%" alt="Random first slide">
<div class="carousel-caption" >
<h3>First slide label</h3>
<p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>
</div>
</div>
</ng-template>
<ng-template ngbSlide id="id2">
<div class="picsum-img-wrapper" [@simpleFadeAnimation]="carousel &&carousel.activeId=='id2'">
<img [src]="images[1]" width="100%" alt="Random second slide">
<div class="carousel-caption" >
<h3>Second slide label</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</ng-template>
<ng-template ngbSlide id="id3">
<div class="picsum-img-wrapper" [@simpleFadeAnimation]="carousel &&carousel.activeId=='id3'">
<img [src]="images[2]" width="100%" alt="Random third slide">
<div class="carousel-caption" >
<h3>Third slide label</h3>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>
</div>
</div>
</ng-template>
</ngb-carousel>
see the new stackblitz
Updated 2 if we want the slides go from left to right we can use an animtion like
animations: [
trigger('simpleTranslation', [
state('outright', style({ transform: `translateX(100%)` })),
state('outleft', style({ transform: `translateX(-100%)` })),
state('inleft', style({ transform: `translateX(0)` })),
state('inright', style({ transform: `translateX(0)` })),
transition('*=>inleft',[
style({transform:`translateX(-100%)`}),
animate('260ms ease-in')
]),
transition('*=>inright',[
style({transform:`translateX(100%)`}),
animate('260ms ease-in')
]),
transition('*=>outright', [
animate('260ms ease-in', style({ transform: `translateX(-100%)` }))
]),
transition('*=>outleft', [
animate('260ms ease-in',style({ transform: `translateX(100%)` }))
]),
])
]
where we need get the Slides in view children and use the slide event
@ViewChildren(NgbSlide) slides: QueryList<NgbSlide>
slideControl: any[] = []
onSlide(event) {
this.slides.forEach((x, index) => {
if (x.id == event.current) {
this.slideControl[index] = 'in' + event.direction
}
if (x.id == event.prev) {
this.slideControl[index] = 'out' + event.direction
}
})
}
the .html like
<ngb-carousel #carousel *ngIf="images" interval=0 wrap="true" (slide)=onSlide($event)>
<ng-template ngbSlide id="id1">
<div class="picsum-img-wrapper" [@simpleTranslation]="slideControl[0]">
<img [src]="images[0]" alt="Random first slide">
<div class="carousel-caption" >
<h3>First slide label</h3>
<p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>
</div>
</div>
</ng-template>
<ng-template ngbSlide id="id2">
<div class="picsum-img-wrapper" [@simpleTranslation]="slideControl[1]">
<img [src]="images[1]" alt="Random second slide">
<div class="carousel-caption" >
<h3>Second slide label</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</ng-template>
...
</ngb-carousel>
See another stackblitz
(*)ViewEncapsultaion.None make that the .css in your .component was for all the app. So use it carefully, if e.g. you write in your component a css h1{color:red}
all yours h1 in your application becomes "red"