¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="u-swiper" |
| | | :style="{ |
| | | backgroundColor: bgColor, |
| | | height: $u.addUnit(height), |
| | | borderRadius: $u.addUnit(radius) |
| | | }" |
| | | > |
| | | <view |
| | | class="u-swiper__loading" |
| | | v-if="loading" |
| | | > |
| | | <u-loading-icon mode="circle"></u-loading-icon> |
| | | </view> |
| | | <swiper |
| | | v-else |
| | | class="u-swiper__wrapper" |
| | | :style="{ |
| | | height: $u.addUnit(height), |
| | | }" |
| | | @change="change" |
| | | :circular="circular" |
| | | :interval="interval" |
| | | :duration="duration" |
| | | :autoplay="autoplay" |
| | | :current="current" |
| | | :currentItemId="currentItemId" |
| | | :previousMargin="$u.addUnit(previousMargin)" |
| | | :nextMargin="$u.addUnit(nextMargin)" |
| | | :acceleration="acceleration" |
| | | :displayMultipleItems="displayMultipleItems" |
| | | :easingFunction="easingFunction" |
| | | > |
| | | <swiper-item |
| | | class="u-swiper__wrapper__item" |
| | | v-for="(item, index) in list" |
| | | :key="index" |
| | | > |
| | | <view |
| | | class="u-swiper__wrapper__item__wrapper" |
| | | :style="[itemStyle(index)]" |
| | | > |
| | | <!-- å¨nvueä¸ï¼imageå¾çç宽度é»è®¤ä¸ºå±å¹å®½åº¦ï¼éè¦éè¿flex:1æå¼ï¼å¦å¤å¿
须设置é«åº¦æè½æ¾ç¤ºå¾ç --> |
| | | <image |
| | | class="u-swiper__wrapper__item__wrapper__image" |
| | | v-if="getItemType(item) === 'image'" |
| | | :src="getSource(item)" |
| | | :mode="imgMode" |
| | | @tap="clickHandler(index)" |
| | | :style="{ |
| | | height: $u.addUnit(height), |
| | | borderRadius: $u.addUnit(radius) |
| | | }" |
| | | ></image> |
| | | <video |
| | | class="u-swiper__wrapper__item__wrapper__video" |
| | | v-if="getItemType(item) === 'video'" |
| | | :id="`video-${index}`" |
| | | :enable-progress-gesture="false" |
| | | :src="getSource(item)" |
| | | :poster="getPoster(item)" |
| | | :title="showTitle && $u.test.object(item) && item.title ? item.title : ''" |
| | | :style="{ |
| | | height: $u.addUnit(height) |
| | | }" |
| | | controls |
| | | @tap="clickHandler(index)" |
| | | ></video> |
| | | <text |
| | | v-if="showTitle && $u.test.object(item) && item.title && $u.test.image(getSource(item))" |
| | | class="u-swiper__wrapper__item__wrapper__title u-line-1" |
| | | >{{ item.title }}</text> |
| | | </view> |
| | | </swiper-item> |
| | | </swiper> |
| | | <view class="u-swiper__indicator" :style="[$u.addStyle(indicatorStyle)]"> |
| | | <slot name="indicator"> |
| | | <u-swiper-indicator |
| | | v-if="!loading && indicator && !showTitle" |
| | | :indicatorActiveColor="indicatorActiveColor" |
| | | :indicatorInactiveColor="indicatorInactiveColor" |
| | | :length="list.length" |
| | | :current="currentIndex" |
| | | :indicatorMode="indicatorMode" |
| | | ></u-swiper-indicator> |
| | | </slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import props from './props.js'; |
| | | /** |
| | | * Swiper è½®æå¾ |
| | | * @description 该ç»ä»¶ä¸è¬ç¨äºå¯¼èªè½®æï¼å¹¿åå±ç¤ºçåºæ¯,å¯å¼ç®±å³ç¨ï¼ |
| | | * @tutorial https://www.uviewui.com/components/swiper.html |
| | | * @property {Array} list è½®æå¾æ°æ® |
| | | * @property {Boolean} indicator æ¯å¦æ¾ç¤ºé¢æ¿æç¤ºå¨ï¼é»è®¤ false ï¼ |
| | | * @property {String} indicatorActiveColor æç¤ºå¨éæ¿æ´»é¢è²ï¼é»è®¤ '#FFFFFF' ï¼ |
| | | * @property {String} indicatorInactiveColor æç¤ºå¨çæ¿æ´»é¢è²ï¼é»è®¤ 'rgba(255, 255, 255, 0.35)' ï¼ |
| | | * @property {String | Object} indicatorStyle æç¤ºå¨æ ·å¼ï¼å¯éè¿bottomï¼leftï¼rightè¿è¡å®ä½ |
| | | * @property {String} indicatorMode æç¤ºå¨æ¨¡å¼ï¼é»è®¤ 'line' ï¼ |
| | | * @property {Boolean} autoplay æ¯å¦èªå¨åæ¢ï¼é»è®¤ true ï¼ |
| | | * @property {String | Number} current å½åæå¨æ»åç indexï¼é»è®¤ 0 ï¼ |
| | | * @property {String} currentItemId å½åæå¨æ»åç item-id ï¼ä¸è½ä¸ current è¢«åæ¶æå® |
| | | * @property {String | Number} interval æ»åèªå¨åæ¢æ¶é´é´éï¼msï¼ï¼é»è®¤ 3000 ï¼ |
| | | * @property {String | Number} duration æ»å忢è¿ç¨æéæ¶é´ï¼msï¼ï¼é»è®¤ 300 ï¼ |
| | | * @property {Boolean} circular ææ¾å°æ«å°¾åæ¯å¦éæ°åå°å¼å¤´ï¼é»è®¤ false ï¼ |
| | | * @property {String | Number} previousMargin åè¾¹è·ï¼å¯ç¨äºé²åºåä¸é¡¹çä¸å°é¨åï¼nvue忝ä»å®ä¸æ¯æï¼é»è®¤ 0 ï¼ |
| | | * @property {String | Number} nextMargin åè¾¹è·ï¼å¯ç¨äºé²åºåä¸é¡¹çä¸å°é¨åï¼nvue忝ä»å®ä¸æ¯æï¼é»è®¤ 0 ï¼ |
| | | * @property {Boolean} acceleration å½å¼å¯æ¶ï¼ä¼æ ¹æ®æ»å¨é度ï¼è¿ç»æ»å¨å¤å±ï¼æ¯ä»å®ä¸æ¯æï¼é»è®¤ false ï¼ |
| | | * @property {Number} displayMultipleItems åæ¶æ¾ç¤ºçæ»åæ°éï¼nvueãæ¯ä»å®å°ç¨åºä¸æ¯æï¼é»è®¤ 1 ï¼ |
| | | * @property {String} easingFunction æå®swiper忢ç¼å¨å¨ç»ç±»åï¼ åªå¯¹å¾®ä¿¡å°ç¨åºææï¼é»è®¤ 'default' ï¼ |
| | | * @property {String} keyName listæ°ç»ä¸æå®å¯¹è±¡çç®æ 屿§åï¼é»è®¤ 'url' ï¼ |
| | | * @property {String} imgMode å¾ççè£åªæ¨¡å¼ï¼é»è®¤ 'aspectFill' ï¼ |
| | | * @property {String | Number} height ç»ä»¶é«åº¦ï¼é»è®¤ 130 ï¼ |
| | | * @property {String} bgColor èæ¯é¢è²ï¼é»è®¤ '#f3f4f6' ï¼ |
| | | * @property {String | Number} radius ç»ä»¶åè§ï¼æ°å¼æå¸¦åä½çå符串ï¼é»è®¤ 4 ï¼ |
| | | * @property {Boolean} loading æ¯å¦å è½½ä¸ï¼é»è®¤ false ï¼ |
| | | * @property {Boolean} showTitle æ¯å¦æ¾ç¤ºæ é¢ï¼è¦æ±æ°ç»å¯¹è±¡ä¸ætitle屿§ï¼é»è®¤ false ï¼ |
| | | * @event {Function(index)} click ç¹å»è½®æå¾æ¶è§¦å indexï¼ç¹å»äºç¬¬å å¼ å¾çï¼ä»0å¼å§ |
| | | * @event {Function(index)} change è½®æå¾åæ¢æ¶è§¦å(èªå¨æè
æå¨åæ¢) indexï¼åæ¢å°äºç¬¬å å¼ å¾çï¼ä»0å¼å§ |
| | | * @example <u-swiper :list="list4" keyName="url" :autoplay="false"></u-swiper> |
| | | */ |
| | | export default { |
| | | name: 'u-swiper', |
| | | mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
| | | data() { |
| | | return { |
| | | currentIndex: 0 |
| | | } |
| | | }, |
| | | watch: { |
| | | current(val, preVal) { |
| | | if(val === preVal) return; |
| | | this.currentIndex = val; // å䏿¸¸æ°æ®å
³èä¸ |
| | | } |
| | | }, |
| | | computed: { |
| | | itemStyle() { |
| | | return index => { |
| | | const style = {} |
| | | // #ifndef APP-NVUE || MP-TOUTIAO |
| | | // 左峿µåºç©ºé´ç忳䏿¯ænvueåå¤´æ¡ |
| | | // åªæé
ç½®äºæ¤äºå¼ï¼æå ä¸å¯¹åºçåè§ï¼ä»¥åç¼©æ¾ |
| | | if (this.nextMargin && this.previousMargin) { |
| | | style.borderRadius = uni.$u.addUnit(this.radius) |
| | | if (index !== this.currentIndex) style.transform = 'scale(0.92)' |
| | | } |
| | | // #endif |
| | | return style |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | getItemType(item) { |
| | | if (typeof item === 'string') return uni.$u.test.video(this.getSource(item)) ? 'video' : 'image' |
| | | if (typeof item === 'object' && this.keyName) { |
| | | if (!item.type) return uni.$u.test.video(this.getSource(item)) ? 'video' : 'image' |
| | | if (item.type === 'image') return 'image' |
| | | if (item.type === 'video') return 'video' |
| | | return 'image' |
| | | } |
| | | }, |
| | | // è·åç®æ è·¯å¾ï¼å¯è½æ°ç»ä¸ä¸ºå符串ï¼å¯¹è±¡çå½¢å¼ï¼é¢å¤å¯æå®å¯¹è±¡çç®æ 屿§åkeyName |
| | | getSource(item) { |
| | | if (typeof item === 'string') return item |
| | | if (typeof item === 'object' && this.keyName) return item[this.keyName] |
| | | else uni.$u.error('è¯·ææ ¼å¼ä¼ éåè¡¨åæ°') |
| | | return '' |
| | | }, |
| | | // è½®æåæ¢äºä»¶ |
| | | change(e) { |
| | | // å½åçæ¿æ´»ç´¢å¼ |
| | | const { |
| | | current |
| | | } = e.detail |
| | | this.pauseVideo(this.currentIndex) |
| | | this.currentIndex = current |
| | | this.$emit('change', e.detail) |
| | | }, |
| | | // åæ¢è½®ææ¶ï¼æåè§é¢ææ¾ |
| | | pauseVideo(index) { |
| | | const lastItem = this.getSource(this.list[index]) |
| | | if (uni.$u.test.video(lastItem)) { |
| | | // å½è§é¢éèæ¶ï¼æåææ¾ |
| | | const video = uni.createVideoContext(`video-${index}`, this) |
| | | video.pause() |
| | | } |
| | | }, |
| | | // å½ä¸ä¸ªè½®æitem为è§é¢æ¶ï¼è·åå®çè§é¢æµ·æ¥ |
| | | getPoster(item) { |
| | | return typeof item === 'object' && item.poster ? item.poster : '' |
| | | }, |
| | | // ç¹å»æä¸ªitem |
| | | clickHandler(index) { |
| | | this.$emit('click', index) |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "../../libs/css/components.scss"; |
| | | |
| | | .u-swiper { |
| | | @include flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: relative; |
| | | overflow: hidden; |
| | | |
| | | &__wrapper { |
| | | flex: 1; |
| | | |
| | | &__item { |
| | | flex: 1; |
| | | |
| | | &__wrapper { |
| | | @include flex; |
| | | position: relative; |
| | | overflow: hidden; |
| | | transition: transform 0.3s; |
| | | flex: 1; |
| | | |
| | | &__image { |
| | | flex: 1; |
| | | } |
| | | |
| | | &__video { |
| | | flex: 1; |
| | | } |
| | | |
| | | &__title { |
| | | position: absolute; |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | font-size: 28rpx; |
| | | padding: 12rpx 24rpx; |
| | | color: #FFFFFF; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__indicator { |
| | | position: absolute; |
| | | bottom: 10px; |
| | | } |
| | | } |
| | | </style> |