/* eslint-disable react/prop-types */ /* eslint-disable react/no-multi-comp */ import 'weui'; import React from 'react'; import classNames from 'classnames'; import Swipers from 'swiper'; import 'swiper/dist/css/swiper.min.css'; import './style/swiper.css'; let INSTANCE_ID = 0; class SwiperItem extends React.Component { render() { const { className, style, itemId, children, ...restProps } = this.props; const cls = classNames('swiper-slide', className); return (
{children}
); } } const createEvent = (type) => { let e; try { e = new TouchEvent(type); } catch (err) { e = document.createEvent('Event'); e.initEvent(type, true, true); } return e; }; class Swiper extends React.Component { constructor() { super(...arguments); this.$el = null; this._id = INSTANCE_ID + 1; INSTANCE_ID++; this._$current = 0; this._$width = 0; this._$height = 0; } componentDidMount() { const { autoplay = false, interval = 5000, duration = 500, current = 0, displayMultipleItems = 1, vertical, spaceBetween, } = this.props; const that = this; const opt = { // 指示器 pagination: { el: `.taro-swiper-${this._id} > .swiper-container > .swiper-pagination` }, direction: vertical ? 'vertical' : 'horizontal', loop: true, slidesPerView: parseFloat(displayMultipleItems, 10), initialSlide: parseInt(current, 10), speed: parseInt(duration, 10), observer: true, observeParents: true, on: { slideChange() { const e = createEvent('touchend'); try { Object.defineProperty(e, 'detail', { enumerable: true, value: { current: this.realIndex, }, }); } catch (err) {} that._$current = this.realIndex; that.handleOnChange(e); }, transitionEnd: () => { const e = createEvent('touchend'); try { Object.defineProperty(e, 'detail', { enumerable: true, value: { current: this.mySwiper.realIndex, }, }); if (this.mySwiper.isBeginning) { this.mySwiper.slideToLoop(this.props.children.length - 1, 0); } else if (this.mySwiper.isEnd) { this.mySwiper.slideToLoop(0, 0); } } catch (err) {} that.handleOnAnimationFinish(e); }, observerUpdate: (e) => { if ( e.target && e.target.className === 'taro_page' && e.target.style.display === 'block' && e.target.contains(this.$el) ) { if (this.props.autoplay) { setTimeout(() => { this.mySwiper.slideTo(this._$current); }, 1000); } } }, }, }; // 自动播放 if (autoplay) { opt.autoplay = { delay: parseInt(interval, 10), stopOnLastSlide: true, disableOnInteraction: false, }; } // 两端距离 if (spaceBetween) { opt.spaceBetween = spaceBetween; } this.mySwiper = new Swipers(this.$el, opt); setTimeout(() => { this.mySwiper.update(); }, 500); } componentWillReceiveProps(nextProps) { if (this.mySwiper) { const nextCurrent = typeof nextProps.current === 'number' ? nextProps.current : this._$current || 0; this.mySwiper.loopDestroy(); this.mySwiper.loopCreate(); // 是否衔接滚动模式 if (nextProps.circular) { if (!this.mySwiper.isBeginning && !this.mySwiper.isEnd) { this.mySwiper.slideToLoop(parseInt(nextCurrent, 10)); // 更新下标 } } else { this.mySwiper.slideTo(parseInt(nextCurrent, 10) + 1); // 更新下标 } const {autoplay} = this.mySwiper; // 判断是否需要停止或开始自动轮播 if (autoplay?.running !== nextProps.autoplay) { if (nextProps.autoplay) { autoplay.start(); } else { autoplay.stop(); } } if (nextProps.autoplay && !autoplay.paused) { autoplay.run(); autoplay.paused = false; } this.mySwiper.update(); // 更新子元素 } } componentDidUpdate(preProps) { if (preProps.children.length === 0 && this.props.children.length > 0) { this.mySwiper.loopDestroy(); this.mySwiper.loopCreate(); } if (!this.mySwiper) return; if (this.props.autoplay) { if (this._$width !== this.mySwiper.width || this._$height !== this.mySwiper.height) { this.mySwiper.autoplay.run(); } } this._$width = this.mySwiper.width; this._$height = this.mySwiper.height; } componentWillUnmount() { this.$el = null; if (this.mySwiper) this.mySwiper.destroy(); } handleOnChange(e) { const func = this.props.onChange; typeof func === 'function' && func(e); } handleOnAnimationFinish(e) { const func = this.props.onAnimationFinish; typeof func === 'function' && func(e); } parsePX(s = '0px') { return parseFloat(s.replace(/r*px/i, ''), 10); } render() { const { className, style, vertical, previousMargin, nextMargin, indicatorColor, indicatorActiveColor, } = this.props; const defaultIndicatorColor = indicatorColor || 'rgba(0, 0, 0, .3)'; const defaultIndicatorActiveColor = indicatorActiveColor || '#000'; const cls = classNames(`taro-swiper-${this._id}`, className); const sty = Object.assign( { paddingTop: vertical ? this.parsePX(previousMargin) : 0, paddingRight: vertical ? 0 : this.parsePX(nextMargin), paddingBottom: vertical ? this.parsePX(nextMargin) : 0, paddingLeft: vertical ? 0 : this.parsePX(previousMargin), overflow: 'hidden', }, style, ); const paginationCls = classNames('swiper-pagination', { 'swiper-pagination-hidden': !this.props.indicatorDots, 'swiper-pagination-bullets': this.props.indicatorDots, }); return (
{ this.$el = el; }} >
.taro-swiper-${this._id} > .swiper-container > .swiper-pagination > .swiper-pagination-bullet { background: ${defaultIndicatorColor} } .taro-swiper-${this._id} > .swiper-container > .swiper-pagination > .swiper-pagination-bullet-active { background: ${defaultIndicatorActiveColor} } `, }} />
{this.props.children}
); } } export { Swiper, SwiperItem };