css 滚动抽奖动画

358 阅读1分钟
<view class="content">
    <view class="lottery-title">{{infos[datas.length].title}}</view>
    <image :style="{left:10===datas.length ?'41%' : '50%'}" class="down" src="下箭头" mode="widthFix">
    </image>
    <image style="left: 60%" class="down" src="下箭头" mode="widthFix" v-if="10===datas.length">
    </image>
    <view :style="{top:infos[datas.length].top}" class="lottery-datas">
        <view>
            <view v-for="(item,index) in images" :key="index">
                <view class="item" :animation="animationData">
                    <view class="img" :style="{width:imageHeight + 'px',height:imageHeight + 'px'}"
                        v-for="(data,index1) in item.lists" :key="index1">
                        <image :style="{width:imageHeight + 'px',height:imageHeight + 'px'}"
                            :src="data.thumbnail_image" mode="aspectFit"></image>
                    </view>
                </view>
            </view>
        </view>
    </view>
    <image :style="{left:10===datas.length ?'41%' : '50%'}" class="up" src="上箭头" mode="widthFix">
    </image>
    <image style="left: 60%" class="up" src="上箭头" mode="widthFix" v-if="10===datas.length">
    </image>
    <view class="btn color-base-text" @click="startScroll">点击开启
    </view>
    <view class="scroll-text color-base-text" v-if="0<=count">
        {{count}}s 停止滚动
    </view>
</view>

<script>
    export default {
        data() {
            return {
                count: 3,
                timer: null,
                infos: {
                    1: {
                        top: '40%',
                        size: 0.28,
                        title: '一次',
                        scrollX: 1
                    },
                    3: {
                        top: '25%',
                        size: 0.28,
                        title: '三次',
                        scrollX: 1
                    },
                    5: {
                        top: '24%',
                        size: 0.16,
                        title: '五次',
                        scrollX: 1.05
                    },
                    10: {
                        top: '24%',
                        size: 0.16,
                        title: '十次',
                        scrollX: 1.06
                    }
                },
                datas: [],
                stopIndex: '',
                imageHeight: '',
                images: [],
                goodses: [],
                animationData: {},
                scrollX: 0,
                windowWidth: 0,
                isPng: true
            }
        },
        mounted() {
            this.datas = uni.getStorageSync('datas')
            this.goodses = uni.getStorageSync('goodses')
            let info = uni.getSystemInfoSync();
            let windowWidth = info.windowWidth
            this.imageHeight = (windowWidth * this.infos[this.datas.length].size).toFixed(2);
            this.scrollX = parseInt(windowWidth * 8.5)
            this.init()
        },
        methods: {
            init() {
                // 停留的索引
                this.stopIndex = Math.floor(this.scrollX / (this.imageHeight * 2))
                while (this.goodses.length < 40) {
                    this.goodses = this.goodses.concat(this.goodses)
                }
                const arr1 = JSON.stringify(this.goodses)
                this.datas.forEach((item, index) => {
                    let lists = index % 2 === 0 ? JSON.parse(arr1) : this.$util.shuffleArray(JSON.parse(arr1))
                    if (this.datas.length <= 5) {
                        // 商品数小于5
                        lists[this.stopIndex] = item
                        this.images[index] = {
                            lists: lists
                        }
                    } else if (5 > index) {
                        // 商品数大于5
                        lists[this.stopIndex] = item
                        lists[this.stopIndex + 1] = this.datas[index + 5]
                        this.images[index] = {
                            lists: lists
                        }
                    }
                })
            },
            startScroll() {
                var animation = uni.createAnimation({
                    duration: 3000,
                    timingFunction: 'ease'
                })
                this.animation = animation
                // 根据页面大小适配停留位置
                const scale = 375 >= this.windowWidth ? this.infos[this.datas.length].scrollX : (400 >= this.windowWidth ? this.infos[this.datas.length].scrollX - 0.05 : this.infos[this.datas.length].scrollX - 0.1)
                const stopX = -parseInt(this.scrollX * scale) + 'rpx'
                animation.translateX(stopX)
                    .step() //调试这个值来决定停止位置
                this.animationData = animation.export()
                this.count = 3
                this.timer = setInterval(() => {
                    // 创建定时器
                    if (this.count === 1) {
                        // 抽奖完成
                        this.count = 0
                    } else {
                        this.count--
                    }
                }, 1000)
            }
        }
    }
</script>

<style lang="scss" scoped>
.lottery-title {
    position: absolute;
    top: 146rpx;
    left: 50%;
    transform: translateX(-50%);
    color: #fff;
    font-size: 50rpx;
    font-family: YouSheBiaoTiHei;
    animation: titleScale 1.6s linear infinite;

    @keyframes titleScale {
        0% {
            transform: translateX(-50%) scale(1);
        }

        50% {
            transform: translateX(-50%) scale(0.9);
        }

        100% {
            transform: translateX(-50%) scale(1);
        }
    }
}

.up,
.down {
    width: 66rpx;
    max-height: 50rpx !important;
    position: absolute;
    margin-left: -33rpx;
}

.up {
    top: 1090rpx;
}

.down {
    top: 345rpx;
}

&-datas {
    position: absolute;
    width: 100%;

    .item {
        display: flex;
        align-items: center;
        height: 100%;
        width: 100%;
        margin-top: 20rpx;

        .img {
            margin-right: 20rpx;
        }
    }
}

.scroll-text {
    position: absolute;
    top: 270rpx;
    left: 50%;
    transform: translateX(-50%);
    font-size: 36rpx;
    font-family: YouSheBiaoTiHei;
}

.btn {
    width: 316rpx;
    height: 87rpx;
    line-height: 87rpx;
    border-radius: 44rpx;
    text-align: center;
    position: absolute;
    top: 1180rpx;
    left: 50%;
    transform: translateX(-50%);
    border: 1px solid $base-color;
    animation: scale 1.6s linear infinite;

    @keyframes scale {
        0% {
            font-size: 30rpx;
        }

        50% {
            font-size: 28rpx;
        }

        100% {
            font-size: 30rpx;
        }
    }
}
</style>

效果图:

image.png

image.png

抽奖:ext.dcloud.net.cn/plugin?id=1…

js乱序:blog.csdn.net/weixin_5081…