安装Swiper
npm install swiper --save
或者
yarn add swiper --save
在angular.json文件添加swiper.js和swiper.css
ts
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { A11yOptions, AutoplayOptions, CoverflowEffectOptions, CubeEffectOptions, FadeEffectOptions, FlipEffectOptions, HashNavigationOptions, HistoryNavigationOptions, KeyboardOptions, LazyOptions, MousewheelOptions, NavigationOptions, PaginationOptions, ScrollbarOptions, SelectableElement, SwiperOptions, VirtualOptions, ZoomOptions } from 'swiper'; declare let Swiper: any; @Component({ selector: 'cat-swiper-slide', templateUrl: './swiper-slide.component.html', styleUrls: ['./swiper-slide.component.scss'] }) export class SwiperSlideComponent implements OnInit, AfterViewInit { mySwiper: any; @ViewChild('paginationEl', {static: true}) paginationEl: ElementRef; @ViewChild('prevButtonEl', {static: true}) prevButtonEl: ElementRef; @ViewChild('nextButtonEl', {static: true}) nextButtonEl: ElementRef; @Input() containerClass: string; @Input() wrapperClass: string; @Input() sliderClass: string; @Input() paginationClass: string; @Input() buttonClass: string; @Input() scrollbarClass: string; @Input() items: any[] = []; /** * Index number of initial slide. */ @Input() initialSlide: number; /** * Could be 'horizontal' or 'vertical' (for vertical slider). */ @Input() direction: 'horizontal' | 'vertical'; /** * Duration of transition between slides (in ms) */ @Input() speed: number; /** * Enabled this option and plugin will set width/height on swiper wrapper equal to total size of all slides. * Mostly should be used as compatibility fallback option for browser that don't support flexbox layout well */ @Input() setWrapperSize: boolean; /** * Enabled this option and swiper will be operated as usual except it will not move, * real translate values on wrapper will not be set. * * Useful when you may need to create custom slide transition */ @Input() virtualTranslate: boolean; /** * Swiper width (in px). * * Parameter allows to force Swiper width. Useful only if you initialize Swiper when it is hidden. * * Setting this parameter will make Swiper not responsive */ @Input() width: number; /** * Swiper height (in px). * * Parameter allows to force Swiper height. Useful only if you initialize Swiper when it is hidden. * * Setting this parameter will make Swiper not responsive */ @Input() height: number; /** * Set to true and slider wrapper will adopt its height to the height of the currently active slide */ @Input() autoHeight: boolean; /** * Set to true to round values of slides width and height to prevent blurry texts on usual resolution screens (if you have such) */ @Input() roundLengths: boolean; /** * Set to true on nested Swiper for correct touch events interception. * Use only on nested swipers that use same direction as the parent one */ @Input() nested: boolean; /** * If enabled (by default) and navigation elements' parameters passed as a string (like ".pagination") * then Swiper will look for such elements through child elements first. * * Applies for pagination, prev/next buttons and scrollbar elements */ @Input() uniqueNavElements: boolean; /** * Tranisition effect. Could be "slide", "fade", "cube", "coverflow" or "flip" */ @Input() effect: 'slide' | 'fade' | 'cube' | 'coverflow' | 'flip'; /** * Fire [Transition/SlideChange][Start/End] events on swiper initialization. * Such events will be fired on initialization in case of your initialSlide is not 0, or you use loop mode */ @Input() runCallbacksOnInit: boolean; /** * When enabled Swiper will be disabled and hide navigation buttons on case there are not enough slides for sliding */ @Input() watchOverflow: boolean; /** * Distance between slides in px. */ @Input() spaceBetween: number; /** * Number of slides per view (slides visible at the same time on slider's container). * If you use it with "auto" value and along with loop: true * then you need to specify loopedSlides parameter with amount of slides to loop (duplicate) */ @Input() slidesPerView: number | 'auto'; /** * Number of slides per column, for multirow layout */ @Input() slidesPerColumn: number; /** * Could be 'column' or 'row'. Defines how slides should fill rows, by column or by row */ @Input() slidesPerColumnFill: 'column' | 'row'; /** * Set numbers of slides to define and enable group sliding. Useful to use with slidesPerView > 1 */ @Input() slidesPerGroup: number; /** * If true, then active slide will be centered, not always on the left side. */ @Input() centeredSlides = false; /** * Add (in px) additional slide offset in the beginning of the container (before all slides) */ @Input() slidesOffsetBefore: number; /** * Add (in px) additional slide offset in the end of the container (after all slides) */ @Input() slidesOffsetAfter: number; /** * Normalize slide index. See #1766 */ @Input() normalizeSlideIndex: boolean; /** * When enabled it center slides if the amount of slides less than `slidesPerView`. * Not intended to be used loop mode and slidesPerColumn */ @Input() centerInsufficientSlides: boolean; /** * This option may a little improve desktop usability. * If true, user will see the "grab" cursor when hover on Swiper */ @Input() grabCursor: boolean; /** * Target element to listen touch events on. * * Can be 'container' (to listen for touch events on swiper-container) * or 'wrapper' (to listen for touch events on swiper-wrapper) */ @Input() touchEventsTarget: 'container' | 'wrapper'; /** * Touch ratio */ @Input() touchRatio: number; /** * */ @Input() touchAngle: number; /** * If true, Swiper will accept mouse events like touch events (click and drag to change slides) */ @Input() simulateTouch: boolean; /** * Set to false if you want to disable short swipes */ @Input() shortSwipes: boolean; /** * Set to false if you want to disable long swipes */ @Input() longSwipes: boolean; /** * Ratio to trigger swipe to next/previous slide during long swipes */ @Input() longSwipesRatio: number; /** * Minimal duration (in ms) to trigger swipe to next/previous slide during long swipes */ @Input() longSwipesMs: number; /** * If disabled, then slider will be animated only when you release it, * it will not move while you hold your finger on it */ @Input() followFinger: boolean; /** * If false, then the only way to switch the slide is use of external API functions like slidePrev or slideNext */ @Input() allowTouchMove: boolean; /** * Threshold value in px. If "touch distance" will be lower than this value then swiper will not move */ @Input() threshold: number; /** * If disabled, `touchstart` (`mousedown`) event won't be prevented */ @Input() touchStartPreventDefault: boolean; /** * Force to always prevent default for `touchstart` (`mousedown`) event */ @Input() touchStartForcePreventDefault: boolean; /** * If enabled, then propagation of "touchmove" will be stopped */ @Input() touchMoveStopPropagation: boolean; /** * Enable to release Swiper events for swipe-to-go-back work in iOS UIWebView */ @Input() iOSEdgeSwipeDetection: boolean; /** * Area (in px) from left edge of the screen to release touch events for swipe-to-go-back in iOS UIWebView */ @Input() iOSEdgeSwipeThreshold: number; /** * Enable to release touch events on slider edge position (beginning, end) to allow for further page scrolling */ @Input() touchReleaseOnEdges: boolean; /** * Passive event listeners will be used by default where possible to improve scrolling performance on * mobile devices. * * But if you need to use `e.preventDefault` and you have conflict with it, * then you should disable this parameter */ @Input() passiveListeners: boolean; /** * Set to false if you want to disable resistant bounds */ @Input() resistance: boolean; /** * This option allows you to control resistance ratio */ @Input() resistanceRatio: number; // Swiping / No swiping @Input() preventInteractionOnTransition: boolean; @Input() allowSlidePrev: boolean; @Input() allowSlideNext: boolean; @Input() noSwiping: boolean; @Input() noSwipingClass: string; @Input() noSwipingSelector: string; @Input() swipeHandler: SelectableElement; // Clicks @Input() preventClicks: boolean; @Input() preventClicksPropagation: boolean; @Input() slideToClickedSlide: boolean; // Freemode @Input() freeMode: boolean; @Input() freeModeMomentum: boolean; @Input() freeModeMomentumRatio: number; @Input() freeModeMomentumVelocityRatio: number; @Input() freeModeMomentumBounce: boolean; @Input() freeModeMomentumBounceRatio: number; @Input() freeModeMinimumVelocity: number; @Input() freeModeSticky: boolean; // Progress @Input() watchSlidesProgress: boolean; @Input() watchSlidesVisibility: boolean; // Images @Input() preloadImages: boolean; @Input() updateOnImagesReady: boolean; // Loop @Input() loop: boolean; @Input() loopAdditionalSlides: number; @Input() loopedSlides: number; @Input() loopFillGroupWithBlank: boolean; // Breakpoints @Input() breakpoints: { [index: number]: SwiperOptions; }; @Input() breakpointsInverse: boolean; // Observer @Input() observer: boolean; @Input() observeParents: boolean; // Namespace @Input() containerModifierClass: string; @Input() slideActiveClass: string; @Input() slideDuplicateActiveClass: string; @Input() slideVisibleClass: string; @Input() slideDuplicateClass: string; @Input() slideNextClass: string; @Input() slideDuplicateNextClass: string; @Input() slidePrevClass: string; @Input() slideDuplicatePrevClass: string; // Components @Input() navigation: NavigationOptions | boolean; @Input() pagination: PaginationOptions | boolean; @Input() scrollbar: ScrollbarOptions; @Input() autoplay: AutoplayOptions | boolean; @Input() parallax: boolean; @Input() lazy: LazyOptions | boolean; @Input() fadeEffect: FadeEffectOptions; @Input() coverflowEffect: CoverflowEffectOptions; @Input() flipEffect: FlipEffectOptions; @Input() cubeEffect: CubeEffectOptions; @Input() zoom: ZoomOptions | boolean; @Input() keyboard: KeyboardOptions | boolean; @Input() mousewheel: MousewheelOptions | boolean; @Input() virtual: VirtualOptions | boolean; @Input() hashNavigation: HashNavigationOptions | boolean; @Input() history: HistoryNavigationOptions | boolean; @Input() a11y: A11yOptions | boolean; // Event will be fired when currently active slide is changed @Output() swiperSlideChange: EventEmitter= new EventEmitter (); // Event will be fired in the beginning of animation to other slide (next or previous). @Output() swiperSlideChangeTransitionStart: EventEmitter = new EventEmitter (); // Event will be fired after animation to other slide (next or previous). @Output() swiperSlideChangeTransitionEnd: EventEmitter = new EventEmitter (); // Same as "slideChangeTransitionStart" but for "forward" direction only @Output() swiperSlideNextTransitionStart: EventEmitter = new EventEmitter (); // Same as "slideChangeTransitionEnd" but for "forward" direction only @Output() swiperSlideNextTransitionEnd: EventEmitter = new EventEmitter (); // Same as "slideChangeTransitionStart" but for "backward" direction only @Output() swiperSlidePrevTransitionStart: EventEmitter = new EventEmitter (); // Same as "slideChangeTransitionEnd" but for "backward" direction only @Output() swiperSlidePrevTransitionEnd: EventEmitter = new EventEmitter (); // Event will be fired in the beginning of transition. @Output() swiperTransitionStart: EventEmitter = new EventEmitter (); // Event will be fired after transition. @Output() swiperTransitionEnd: EventEmitter = new EventEmitter (); // Event will be fired when user touch Swiper. Receives 'touchstart' event as an arguments. @Output() swiperTouchStart: EventEmitter = new EventEmitter (); // Event will be fired when user touch and move finger over Swiper in direction opposite to direction parameter. // Receives 'touchmove' event as an arguments. @Output() swiperTouchMoveOpposite: EventEmitter = new EventEmitter (); // Event will be fired when user touch and move finger over Swiper and move it. Receives 'touchmove' event as an arguments. @Output() swiperSliderMove: EventEmitter = new EventEmitter (); // Event will be fired when user touch and move finger over Swiper. Receives 'touchmove' event as an arguments. @Output() swiperTouchMove: EventEmitter = new EventEmitter (); // Event will be fired when user release Swiper. Receives 'touchend' event as an arguments. @Output() swiperTouchEnd: EventEmitter = new EventEmitter (); // Event will be fired when user click/tap on Swiper after 300ms delay. Receives 'touchend' event as an arguments. @Output() swiperClick: EventEmitter = new EventEmitter (); // Event will be fired when user click/tap on Swiper. Receives 'touchend' event as an arguments. @Output() swiperTap: EventEmitter = new EventEmitter (); // Event will be fired when user double tap on Swiper's container. Receives 'touchend' event as an arguments @Output() swiperDoubleTap: EventEmitter = new EventEmitter (); // Event will be fired right after all inner images are loaded. updateOnImagesReady should be also enabled @Output() swiperImagesReady: EventEmitter = new EventEmitter (); // Event will be fired when Swiper progress is changed, as an arguments it receives progress that is always from 0 to 1 @Output() swiperProgress: EventEmitter = new EventEmitter (); // Event will be fired when Swiper reach its beginning (initial position) @Output() swiperReachBeginning: EventEmitter = new EventEmitter (); // Event will be fired when Swiper reach its beginning (initial position) @Output() swiperReachEnd: EventEmitter = new EventEmitter (); // Event will be fired when Swiper reach last slide // Event will be fired when Swiper goes from beginning or end position @Output() swiperFromEdge: EventEmitter = new EventEmitter (); constructor( private elementRef: ElementRef, ) { } ngOnInit() { setTimeout(() => { this.initSwiper(); }, 20); } ngAfterViewInit() { } initSwiper() { // this.mySwiper = new Swiper('.swiper-container', { // slidesPerView: 'auto', // freeMode: true, // loop: true, // autoplayDisableOnInteraction: false, // observer: true, // 修改swiper自己或子元素时,自动初始化swiper // observeParents: true, // 修改swiper的父元素时,自动初始化swiper // // }); let container: HTMLElement = this.elementRef.nativeElement.querySelector('.swiper-container'); this.mySwiper = new Swiper(container, this.buildOption()); } private buildOption(): SwiperOptions { let opt: SwiperOptions = { initialSlide: this.initialSlide, direction: this.direction, speed: this.speed, setWrapperSize: this.setWrapperSize, virtualTranslate: this.virtualTranslate, width: this.width, height: this.height, autoHeight: this.autoHeight, roundLengths: this.roundLengths, nested: this.nested, uniqueNavElements: this.uniqueNavElements, effect: this.effect, runCallbacksOnInit: this.runCallbacksOnInit, watchOverflow: this.watchOverflow, spaceBetween: this.spaceBetween, slidesPerView: this.slidesPerView, slidesPerColumn: this.slidesPerColumn, slidesPerColumnFill: this.slidesPerColumnFill, slidesPerGroup: this.slidesPerGroup, centeredSlides: this.centeredSlides, slidesOffsetBefore: this.slidesOffsetBefore, slidesOffsetAfter: this.slidesOffsetAfter, normalizeSlideIndex: this.normalizeSlideIndex, centerInsufficientSlides: this.centerInsufficientSlides, grabCursor: this.grabCursor, touchEventsTarget: this.touchEventsTarget, touchRatio: this.touchRatio, touchAngle: this.touchAngle, simulateTouch: this.simulateTouch, shortSwipes: this.shortSwipes, longSwipes: this.longSwipes, longSwipesRatio: this.longSwipesRatio, longSwipesMs: this.longSwipesMs, followFinger: this.followFinger, allowTouchMove: this.allowTouchMove, threshold: this.threshold, touchStartPreventDefault: this.touchStartPreventDefault, touchStartForcePreventDefault: this.touchStartForcePreventDefault, touchMoveStopPropagation: this.touchMoveStopPropagation, iOSEdgeSwipeDetection: this.iOSEdgeSwipeDetection, iOSEdgeSwipeThreshold: this.iOSEdgeSwipeThreshold, touchReleaseOnEdges: this.touchReleaseOnEdges, passiveListeners: this.passiveListeners, resistance: this.resistance, resistanceRatio: this.resistanceRatio, preventInteractionOnTransition: this.preventInteractionOnTransition, allowSlidePrev: this.allowSlidePrev, allowSlideNext: this.allowSlideNext, noSwiping: this.noSwiping, noSwipingClass: this.noSwipingClass, noSwipingSelector: this.noSwipingSelector, swipeHandler: this.swipeHandler, preventClicks: this.preventClicks, preventClicksPropagation: this.preventClicksPropagation, slideToClickedSlide: this.slideToClickedSlide, freeMode: this.freeMode, freeModeMomentum: this.freeModeMomentum, freeModeMomentumRatio: this.freeModeMomentumRatio, freeModeMomentumVelocityRatio: this.freeModeMomentumVelocityRatio, freeModeMomentumBounce: this.freeModeMomentumBounce, freeModeMomentumBounceRatio: this.freeModeMomentumBounceRatio, freeModeMinimumVelocity: this.freeModeMinimumVelocity, freeModeSticky: this.freeModeSticky, watchSlidesProgress: this.watchSlidesProgress, watchSlidesVisibility: this.watchSlidesVisibility, preloadImages: this.preloadImages, updateOnImagesReady: this.updateOnImagesReady, loop: this.loop, // 是否是无缝轮播 loopAdditionalSlides: this.loopAdditionalSlides, loopedSlides: this.loopedSlides, loopFillGroupWithBlank: this.loopFillGroupWithBlank, breakpoints: this.breakpoints, breakpointsInverse: this.breakpointsInverse, observer: this.observer, // 修改swiper自己或子元素时,自动初始化swiper observeParents: this.observeParents, // 修改swiper的父元素时,自动初始化swiper containerModifierClass: this.containerModifierClass, slideActiveClass: this.slideActiveClass, slideDuplicateActiveClass: this.slideDuplicateActiveClass, slideVisibleClass: this.slideVisibleClass, slideDuplicateClass: this.slideDuplicateClass, slideNextClass: this.slideNextClass, slideDuplicateNextClass: this.slideDuplicateNextClass, slidePrevClass: this.slidePrevClass, slideDuplicatePrevClass: this.slideDuplicatePrevClass, wrapperClass: this.wrapperClass, // Components // navigation: this.navigation, // pagination: this.pagination, scrollbar: this.scrollbar, autoplay: this.autoplay, parallax: this.parallax, lazy: this.lazy, fadeEffect: this.fadeEffect, coverflowEffect: this.coverflowEffect, flipEffect: this.flipEffect, cubeEffect: this.cubeEffect, zoom: this.zoom, keyboard: this.keyboard, mousewheel: this.mousewheel, virtual: this.virtual, hashNavigation: this.hashNavigation, history: this.history, a11y: this.a11y, }; if (this.pagination === true) { opt.pagination = { el: this.paginationEl.nativeElement, // 分页器,就是小点的位置 type: 'bullets', clickable: true, }; } if (this.loop === true) { let slidesPerView: number = Number(this.slidesPerView); if (slidesPerView) { opt.loopAdditionalSlides = slidesPerView + 1; } } if (this.autoplay === true) { opt.autoplay = { delay: 2000, // 2秒切换一次 disableOnInteraction: false, // 鼠标滑动后继续停止播放 }; } if (this.navigation === true) { opt.navigation = { nextEl: this.nextButtonEl.nativeElement, // 下一张箭头位置 prevEl: this.prevButtonEl.nativeElement, // 上一张箭头位置 }; } // if (this.scrollbar === true) { // opt.scrollbar = { // el: this.scrollbarEl.nativeElement, // 滚动条位置 // }; // } Object.keys(opt) .forEach(key => { if (opt[key] === void 0) { delete opt[key]; } }); console.log(opt); return opt; } }
html
<div class="swiper-container" [ngClass]="containerClass"> <div class="swiper-wrapper" [ngClass]="wrapperClass"> <ng-content>ng-content> div> <div class="swiper-pagination" [ngClass]="paginationClass" [hidden]="!pagination" #paginationEl>div> <div class="swiper-button-prev" [ngClass]="buttonClass" [hidden]="!navigation" #prevButtonEl>div> <div class="swiper-button-next" [ngClass]="buttonClass" [hidden]="!navigation" #nextButtonEl>div> <div class="swiper-scrollbar" [ngClass]="scrollbarClass" *ngIf="scrollbar">div> div>
css
:host { display: block; height: 100%; } .swiper-container { height: 100%; }
使用:
<cat-swiper-slide direction="horizontal" [navigation]="true" [pagination]="false" [loop]="true" [autoplay]="true" [speed]="450" [grabCursor]="true" [spaceBetween]="20" [observer]="true" [observeParents]="true" [slidesPerView]="2.5" *ngIf="projects.length"> <div *ngFor="let item of photoNews" class="swiper-slide self-slide"> // 滑动块内的内容 <div class="image-bg h-100" [nsBackgroundImage]="item.photo">div> <div class="pos-absolute b-0 pd-b-30 w-100 text-center tx-white bg-black-4"> {{item.subject}} div> div> cat-swiper-slide>