小程式:無限自動滾動的Gallery

Harlan2016發表於2019-01-15

遇到一個需求,需要在小程式內實現自動輪播的畫廊效果,如果是網頁版的話有大量現成的庫可以用,但小程式找了一圈沒找到有類似的庫,只好自己想辦法了。

在踩了多個坑之後找到最簡單的方法,就是用CSS animation來實現,但缺點就是不能手動拖動。

先貼一下效果圖

gallery

第一步 html

因為要無限滾動,所以放完在最後一個圖之後需要切換回第一個圖。為了讓使用者感知不到這個切換過程,需要將最開始圖片複製後末尾,小程式裡把wx:for複製一遍就行了,注意要修改wx:key的值,避免重複。

為啥是複製全部圖片呢,主要是因為keyframes的值不能動態設定,複製全部後只需要將end進度值設定為-50%即可。

<view class="series">
    <view
        style="animation: {{duration}}ms scroll-animation linear infinite;width: {{seriesWidth*2}}rpx"
        class="images">
        <view class="row" wx:for="{{productSeries}}" wx:key="{{index}}">
            <image
                wx:for="{{item}}"
                wx:for-item="img"
                wx:for-index="imgIndex"
                wx:key="{{img + imgIndex}}"
                src="{{img}}"
            ></image>
            <image
                wx:for="{{item}}"
                wx:for-item="img"
                wx:for-index="imgIndex"
                wx:key="{{img + imgIndex}}-extra"
                src="{{img}}"
            ></image>
        </view>
    </view>
</view>
複製程式碼

第二步 css

CSS動畫很簡單,讓gallery轉動到-50%的時候跳回0%,並設定infinite。使用style而非class的原因是畫廊總長不確定,動畫的時長根據圖片數量來設定。width也是需要動態設定,自動計算的width會有問題。

.series {
    overflow: hidden;
    .images {
        min-width: 100%;
        .row {
            white-space: nowrap;
            line-height: 1;
            &:last-child {
                transform: translateX(-100rpx);
            }
        }
        image {
            width: 180rpx;
            height: 180rpx;
            margin: 0 10rpx 8rpx 0;
        }
    }
}
@keyframes scroll-animation {
        from {
            transform: translateX(0);
        }
        to {
            transform: translateX(-50%);
        }
    }
複製程式碼

第三步 js

我們還需要通過js計算動畫時長和view的長度,數字190是image width + margin-right的值。最後要再減一次margin-right的原因我也不確定,但不減這個值的話動畫最後會有一點卡頓的感覺,顯得不太流暢,希望有大佬解答一下原理。

data = {
    productSeries: [
        [
            '/images/house1.png',
            '/images/house2.png',
            '/images/house3.png',
            '/images/house2.png',
            '/images/house3.png',
            '/images/house4.png'
        ],
        [
            '/images/house1.png',
            '/images/house2.png',
            '/images/house3.png',
            '/images/house2.png',
            '/images/house3.png',
            '/images/house4.png'
        ]
    ],
    speed: 40,
    seriesWidth: 400,
    duration: 60000
}
onShow() {
    if (this.productSeries[0].length > 4) {
        this.seriesWidth = 190 * this.productSeries[0].length - 10
        this.duration = Math.floor(this.seriesWidth / this.speed * 1000)
    } else { // 當一行圖片太少時就沒必要加動畫了
        this.seriesWidth = null
        this.duration = 0
    }
}
複製程式碼

相關文章