Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- export class VirtualSliderComponent implements OnChanges, AfterViewInit, OnInit {
- @Input() numberItemsToSkip = 2;
- @Input() margin = 20;
- @Input() itemWidth = 300;
- @Input() itemTemplate;
- @Input() data = [];
- @Input() moveToItemIndex: number;
- @Output() scrollEnds = new EventEmitter();
- @ContentChildren(VirtualSliderItemDirective, { read: ElementRef }) items
- : QueryList<ElementRef<HTMLDivElement>>;
- @ViewChild('slides') slidesContainer: ElementRef<HTMLDivElement>;
- disabledLeftArrow = true;
- disabledRightArrow = false;
- isView$ = new BehaviorSubject(false);
- isData$ = new BehaviorSubject(false);
- isItemIndexToMove$ = new BehaviorSubject(undefined);
- ngOnChanges(changes) {
- if (changes.moveToItemIndex && this.moveToItemIndex) {
- this.isItemIndexToMove$.next(true);
- }
- if (changes.data && this.data) {
- this.isData$.next(true);
- }
- this.disabledRightArrow = false;
- }
- ngAfterViewInit() {
- this.isView$.next(true);
- }
- ngOnInit() {
- this.subscribeOnViewAndIndexToActivate();
- }
- subscribeOnViewAndIndexToActivate() {
- combineLatest(this.isView$, this.isItemIndexToMove$, this.isData$)
- .pipe(filter(res => res[0] && res[1] && res[2]))
- .subscribe(() => {
- setTimeout(() => {
- this.moveToSpecificIndexItem(this.moveToItemIndex);
- });
- });
- }
- moveToSpecificIndexItem(index) {
- const position = (this.itemWidth * index) + (this.margin * index);
- this.slidesContainer.nativeElement.scrollLeft = position;
- }
- onClickLeft() {
- this.slidesContainer.nativeElement.scrollLeft -=
- (this.itemWidth * this.numberItemsToSkip) + (this.margin * this.numberItemsToSkip);
- }
- onClickRight() {
- this.slidesContainer.nativeElement.scrollLeft +=
- (this.itemWidth * this.numberItemsToSkip) + (this.margin * this.numberItemsToSkip);
- }
- onScroll() {
- this.disabledLeftArrow = this.slidesContainer.nativeElement.scrollLeft === 0;
- this.disabledRightArrow = this.slidesContainer.nativeElement.offsetWidth +
- this.slidesContainer.nativeElement.scrollLeft === this.slidesContainer.nativeElement.scrollWidth;
- }
- onScrollEnds(event) {
- if (!this.data || !this.data.length) return;
- if (event.endIndex !== this.data.length - 1) return;
- this.scrollEnds.emit();
- }
- }
- //////
- <div class="wrapper">
- <div class="click-panel click-panel_left" (click)="onClickLeft()" [ngClass]="{'disabled': disabledLeftArrow}">
- <i class="material-icons icon-left">
- keyboard_arrow_left
- </i>
- </div>
- <div class="slides" #slides (scroll)="onScroll()" #scrollingBlock>
- <ng-container *ngIf="data && data.length; else spinner">
- <virtual-scroller
- [horizontal]="true"
- #scroll
- [items]="data"
- [parentScroll]="scrollingBlock"
- (vsEnd)="onScrollEnds($event)">
- <ng-container
- #sliderItem
- *ngFor="let item of scroll.viewPortItems"
- appVirtualSliderItem>
- <ng-content *ngTemplateOutlet="itemTemplate; context: {$implicit: item}"></ng-content>
- </ng-container>
- </virtual-scroller>
- </ng-container>
- </div>
- <div class="click-panel click-panel_right" (click)="onClickRight()" [ngClass]="{'disabled': disabledRightArrow}">
- <i class="material-icons icon-right">
- keyboard_arrow_right
- </i>
- </div>
- </div>
- <ng-template #spinner>
- <div class="spinner">
- <app-spinner></app-spinner>
- </div>
- </ng-template>
- ////
- @import "../../../../../../shared/styles/color";
- @import "../../../../../../shared/styles/mixins";
- :host {
- width: 100%;
- }
- .wrapper {
- display: flex;
- align-items: center;
- width: 100%;
- justify-content: space-between;
- i {
- font-size: 45px;
- cursor: pointer;
- color: $color002;
- @include transition(color);
- }
- .icon-left {
- margin-left: -15px;
- }
- .icon-right {
- margin-right: -15px;
- }
- .active {
- @include transition(color);
- color: $color002;
- }
- .disabled {
- box-shadow: none;
- i {
- @include transition(color);
- color: $color014;
- cursor: default;
- }
- }
- }
- .click-panel {
- height: 230px;
- display: flex;
- align-items: center;
- user-select: none;
- margin-bottom: 20px;
- z-index: 1;
- &_right {
- box-shadow: -11px 0px 20px 11px #1c1e2c;;
- }
- &_left {
- box-shadow: 11px 0px 20px 11px #1c1e2c;;
- }
- }
- .content-wrapper {
- overflow: hidden;
- }
- .slides {
- display: flex;
- overflow-x: scroll;
- scroll-behavior: smooth;
- width: 100%;
- padding-bottom: 20px;
- &::-webkit-scrollbar {
- display: none;
- }
- }
- virtual-scroller {
- width: 100%;
- height: 224px;
- }
- .spinner {
- width: 100%;
- display: flex;
- margin-top: 40px;
- align-items: center;
- justify-content: center;
- }
- ///
- @Directive({
- selector: '[appVirtualSliderItem]'
- })
- export class VirtualSliderItemDirective {
- constructor() {}
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement