前些日子老闆大人又安排了新的任務——banner的開發,拿到設計妹子給的設計圖以後,個人第一感受就是——呵!看起來不難嘛!不就是用touchStart,touchmove,touchend組合+一些transition效果+一些位置計算就能實現了嗎???看我兩天內不用輪子直接手寫一個實現它!css
。
。
。
一天半後
。
。
。
在嘗試了wx.createAnimation()中的translateX/left+原生的css3的transition以後,我拿起了鏡子,摸了摸被本身打腫的臉,內心盡是委屈:這特喵的效果怎麼都不按照預想的來啊!是個人寫法不對仍是由於mpvue各類坑使???我開始深深滴懷疑本身。。。在基本肯定此路不通以後(後來瞭解到其實應該是mpvue數據更新機制的問題,每次修改一個data()裏面的值,都會刷新其餘的值,不信你能夠在mpvue中去試試用scroll-view組件的scroll-top屬性實現返回頂部試試。。。),我打開了技術羣,拋出了問題,而後有人指出其實用小程序的swiper應該也能夠實現的,這個想法我以前在某一瞬間曾經有過——swiper設置好基礎參數,而後額外加一些樣式,應該能夠實現。這位仁兄的思路和我不謀而合(咳咳咳,我先不要臉,大家隨意),我也重拾信心,下面呢,就是具體的實現方法以及效果了:html
動圖已放(LICEcap製做)!感謝評論裏的@wangx老哥!想看具體的效果的小夥伴們能夠去我github的項目:mpvue-banner上下載而且跑起來看一下,若是這個banner不是你想要的效果,您能夠選擇再也不往下看,或者能夠看看實現的思路~具體效果以下:vue
banner就在上圖中紅色框內,能夠看到此款banner並無像大多數banner同樣佔據整個屏幕的寬度,而是先後的banner圖都露出了一部分,並且展現的banner圖比先後的banner圖片大小上還放大了必定的倍數,這樣看下來是否是以爲總體設計上要比默認的banner效果好了很多呢?若是還有興趣的話,請繼續往下看具體的實現思路以及代碼mpvue的該組件也是基於小程序原生的swiper組件實現的,具體的屬性我就再也不挨個介紹了,畢竟官方文檔裏寫的很清楚了~這裏就主要說下咱們要實現上圖中的banner要依賴的最重要的兩個屬性previous-margin和next-margin,前者主要做用是「露出前一項的一小部分」,後者主要做用是「露出後一項的一小部分」,好了,咱們先把mpvue-swiper組件介紹中的代碼copy 過來:css3
<template> <div class="page"> <view class="page__hd"> <view class="page__title">Swiper</view> <view class="page__desc">滑塊視圖容器,這裏採用小程序原生 swiper 組件實現。</view> </view> <div class="page__bd page__bd_spacing"> <swiper :indicator-dots="indicatorDots" :autoplay="autoplay" :interval="interval" :duration="duration" :circular="circular" @change="swiperChange" @animationfinish="animationfinish"> <div v-for="item in imgUrls" :key="index"> <swiper-item> <image :src="item" class="slide-image" /> </swiper-item> </div> </swiper> </div> </div> </template> <script> export default { data() { return { indicatorDots: true, autoplay: true, interval: 5000, duration: 900, circular: true, imgUrls: [ 'http://img02.tooopen.com/images/20150928/tooopen_sy_143912755726.jpg', 'http://img06.tooopen.com/images/20160818/tooopen_sy_175866434296.jpg', 'http://img06.tooopen.com/images/20160818/tooopen_sy_175833047715.jpg' ] } }, methods: { swiperChange(e) { console.log('第' + e.mp.detail.current + '張輪播圖發生了滑動'); }, animationfinish(e) { console.log('第' + e.mp.detail.current + '張輪播圖滑動結束'); } } } </script> <style> .slide-image { width: 100%; height: 100%; } </style> 複製代碼
粘完這些代碼,你能實現一個很常規的banner了,而後咱們加上剛剛咱們提到的那兩個屬性:git
<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" :interval="interval" :duration="duration" :circular="circular" :previous-margin="'60rpx'" :next-margin="'60rpx'" @change="swiperChange" @animationfinish="animationfinish"> <div v-for="item in imgUrls" :key="index"> <swiper-item> <div class="img-wrapper"> <image :src="item" class="slide-image" /> </div> </swiper-item> </div> </swiper> 複製代碼
這時候你就實現了一個能將前一項和後一項各露出60rpx的banner了,只不過此時各項的圖片大小都是相同的,那怎麼實現主項的圖片大小的放大呢,固然是使用css的transform給圖片標籤加各放大的樣式,且往下看代碼:github
<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" :interval="interval" :duration="duration" :circular="circular" :previous-margin="'60rpx'" :next-margin="'60rpx'" @change="swiperChange" @animationfinish="animationfinish"> <div v-for="item in imgUrls" :key="index"> <swiper-item> <div class="img-wrapper" :style="{ boxSizing: 'border-box', width: '100%', height: '100%', display: 'flex', justifyContent: 動態值,須要根據設計圖以及banner圖片的個數以及位置進行計算得出, padding: 動態值,須要根據設計圖以及banner圖片的個數以及位置進行計算得出 }"> <image :src="item" class="slide-image" :style="{ transform: currentIndex===bannerIndex?'scale(' + scaleX + ',' + scaleY + ')':'scale(1,1)', transitionDuration: '.3s', transitionTimingFunction: 'ease' }"/> </div> </swiper-item> </div> </swiper> 複製代碼
其中幾個出現的參數:
currentIndex:即當前展示的banner項的索引
bannerIndex:即banner項在整個圖片列表中的索引
scaleX以及scaleY:即你但願的主項的放大的倍數,此項的值可能須要咱們根據屏幕寬度以及設計稿的展現來進行計算
這幾個樣式就是:將當前展現的圖片放大必定的倍數
到了這裏,咱們須要的結構以及style上的代碼基本上都有了,下面主要是script裏對一些關鍵的參數進行控制,這裏有個比較重要的函數@changenpm
<script> data () { return { autoplay: false, interval: 3000, duration: 300, circular: true, currentIndex: 0, scaleX: (634 / 550).toFixed(4), scaleY: (378 / 328).toFixed(4) } }, methods: { // 控制currentIndex以及動畫執行索引descIndex的值 swiperChange (e) { const that = this this.currentIndex = e.mp.detail.current this.scaleX = (634 / 550).toFixed(4) this.scaleY = (378 / 328).toFixed(4) } } </script> 複製代碼
至此呢,主圖中的banner的主要效果基本已經實現了,看下來其實並非很難,主要是一些細節須要特別注意:小程序
它們的值並非隨便寫的,須要你根據設計圖去進行細微的計算api
其中我沒有寫出具體值的兩項屬性:justifyContent與padding,他們的具體值一樣須要你去進行計算,此時的計算不止會涉及到設計稿,他們的值還會根據當前展現出來的三張圖片在整個imgList(至少三項)中的順序的不一樣而不一樣,在個人實現中我使用了超長的三目運算符來保證每一個圖片的具體的屬性值。。。bash
項目已經上傳至github:mpvue-banner,歡迎fork或者討論,因爲可定製性太強,就不寫成npm包了,你們須要的話本身去研究吧! 因爲mpvue的一些的坑的存在,致使咱們像本身實現一些輪子確實很困難,在這種狀況下,咱們就要學會如何利用現成的輪子去改造,進而去實現咱們本身所需的輪子。造不出輪子沒關係,但咱們要保持一顆研(mo)究(fang)進(gai)取(zao)的❤️! 這個介紹到這而就打住了,其實這期也沒什麼東西,我想對於不少人來講只要肯花時間和精力,實現這樣的效果就是小菜一碟! 「咱們不造輪子,咱們只作輪子的改造者與搬運工」