当前位置: 首页 > news >正文

vue3 + css 列表无限循环滚动+鼠标移入停止滚动+移出继续滚动

1.动画文件.vue

<template>
    <div class="dashboard" @click="setFullScreen">
        <div class="warp-box">
            <el-scrollbar ref="scrollRef" height="100%" @scroll="handelScroll">
                <div class="animation-box" @mouseover="stopAnim" @mouseout="runAnim" v-if="arrList.length"
                    :style="{ animationDuration: animationDuration }" :class="{ stopPlay: animationStopPlay }">
                    <div class="line-item" v-for="(item, index) in arrList" :key="index">
                        <img class="item-bg" src="../../assets/images/dashboard/line-bg.png"/>
                        <div class="item-warp">
                            <div class="item-number">
                                <template v-if="index <= 2">
                                    <img :class="`icon-img img-${index}`" :src="imgArr[index]"/>
                                </template>
                                <template v-else><div class="text">{{ index }}</div></template>
                            </div>
                            <div class="item-avatar">
                                <avatarImg :avatar="item.avatar"/>
                            </div>
                            <div class="item-nickname">{{ item.nickname }}</div>
                            <div class="item-point">{{ item.point }}</div>
                        </div>
                    </div>
                    <!-- 重复一次 实现无逢滚动 -->
                    <div class="line-item" v-for="(item, index) in arrList" :key="index">
                        <img class="item-bg" src="../../assets/images/dashboard/line-bg.png"/>
                        <div class="item-warp">
                            <div class="item-number">
                                <template v-if="index <= 2">
                                    <img :class="`icon-img img-${index}`" :src="imgArr[index]"/>
                                </template>
                                <template v-else><div class="text">{{ index }}</div></template>
                            </div>
                            <div class="item-avatar">
                                <avatarImg :avatar="item.avatar"/>
                            </div>
                            <div class="item-nickname">{{ item.nickname }}</div>
                            <div class="item-point">{{ item.point }}</div>
                        </div>
                    </div>
                </div>
            </el-scrollbar>
        </div>
    </div>
</template>

<script setup>
import p0 from '../../assets/images/dashboard/icon_0.png?v=1'
import p1 from '../../assets/images/dashboard/icon_1.png?v=1'
import p2 from '../../assets/images/dashboard/icon_2.png?v=1'
import avatarImg from './avatarImg.vue'
import { nextTick, onMounted, ref, onUnmounted, reactive } from 'vue';
const animationDuration = ref(null);
const animationStopPlay = ref(false);

const imgArr = reactive([p0, p1, p2]);
const scrollRef = ref(null);
const isLoading = ref(false);
const arrList = ref([
    {
        nickname: '昵称昵称昵称昵称',
        avatar: "",
        point: 5000,
    }
]);

const search = reactive({
    page: 1, limit: 20
});
onMounted(() => {
    nextTick(() => {
        setTimeout(() => {
            setFullScreen(); //设置全屏
        }, 3000)
        //加载列表
        loadList();
    })
});

const handelScroll = (event) => {
    const wrapRef = scrollRef.value.wrapRef;
    let poor = wrapRef.scrollHeight - wrapRef.clientHeight;
    // 判断滚动到底部
    if (event.scrollTop + 20 >= poor) {
        loadList();
    }
}

const loadList = () => {
    console.log('加载更多数据...')
    if(isLoading.value) return;
    isLoading.value = true;
    for (let i = 0; i < 30; i++) {
        arrList.value.push({
            nickname: '昵称昵称昵称昵称',
            avatar: "https://pic.qqans.com/up/2024-6/17183287196520597.jpg",
            point: 5000,
        })
    }
    if (arrList.value.length <= 2) {
        animationStopPlay.value = true
        animationDuration.value = 2 + 's'//动画持续时间
    } else {
        animationStopPlay.value = false
        // 跑马灯动画
        animationDuration.value = arrList.value.length * 2 + 's'
    }
    isLoading.value = false;
}
//设置全屏
const setFullScreen = () => {
    const elem = document.getElementById('app');
    if (elem.requestFullscreen) {
        elem.requestFullscreen();
    } else if (elem.mozRequestFullScreen) { /* Firefox */
        elem.mozRequestFullScreen();
    } else if (elem.webkitRequestFullscreen) { /* Chrome, Safari & Opera */
        elem.webkitRequestFullscreen();
    } else if (elem.msRequestFullscreen) { /* IE/Edge */
        elem.msRequestFullscreen();
    }
}

//鼠标移入暂停动画
const stopAnim = () => {
    animationStopPlay.value = true
}
//鼠标移除继续动画
const runAnim = () => {
    if (arrList.value.length > 2) {
        animationStopPlay.value = false
    }
}
</script>

<style lang="scss" scoped>
.dashboard {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
    background-image: url("../../assets/images/dashboard/bg-2.png");
    background-size: cover;
}
.warp-box {
    width: 46%; height: 65%;
    margin: 9.5% 0 0 36.5%;
    padding: 10px 0 10px 10px;
}
.line-item{
    width:100%; position: relative; cursor: pointer;
    font-family: XiangCuiDaZiJi35;
    .item-bg{
        width: 100%; height: auto; display: block;
    }
    .item-warp{
        width: 100%; height:100%; box-sizing: border-box; position: absolute; top: 0; left: 0;
        display: flex; justify-content: flex-start; align-items: center;
    }
}
.item-number{
    text-align: center; width: 16%; height:100%;
    color: #96795c;
    .icon-img{
        margin: 16% 0 0 28%;
        width: 60px; height: auto; display: block;
    }
    .text{
        font-size: 36px;margin: 22% 0 0 0;
    }
}
.item-avatar{
    margin-left: 3%; width: 13%; height:80%;
}
.item-nickname{
    width: 44%;
    font-size: 40px; color: #b99871;
}
.item-point{
    width: 22%;
    font-size: 28px; color: #ffffff; text-align: center;
}

.animation-box{
    animation-name: carousel;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    animation-delay: 0s;
    animation-direction: normal;
    &.stopPlay{
        animation-play-state: paused;
    }
}
@keyframes carousel {
    0% {
        transform: translateY(0%)
    }
    100% {
        transform: translateY(-50%)
    }
}
</style>

2.组件avatarImg.vue(内容显示)与动画无关

<template>
    <div class="image-box">
        <img class="avatar-img" :src="!avatar ? avatarBg : avatar"/>
        <img class="avatar-border" src="../../assets/images/dashboard/avatar-border.png"/>
    </div>
</template>

<script setup>
import avatarBg from '../../assets/images/dashboard/avatar-bg.png?v=1'
import { defineProps } from 'vue';
defineProps({
    avatar: {
        typeof: String,
        default: () => {
            return avatarBg;
        }
    }
})
</script>

<style lang="scss" scoped>
.image-box{
    position: relative;
    .avatar-img{
        width: 80px; height: 80px; display: block;
        transform: rotate(-3deg);
        position: absolute; top: 4px; left: 3px;
    }
    .avatar-border{
        width: 90px; height: 90px; display: block;
        position: absolute; top: 0; left: 0;
    }
}
</style>

相关文章:

  • 开源:LMDB 操作工具:lmcmd
  • 【万字总结】构建现代Web应用的全方位性能优化体系学习指南(一)
  • 基于Hadoop的城市道路交通数据的可视化分析-Flask
  • SAP ABAP BDC 录屏开发
  • spring boot实现程序运行过程中数据源动态切换
  • STM32配套程序接线图
  • WPF程序使用AutoUpdate实现自动更新
  • 重学vue3(二):vue3生命周期(包含父与子)
  • 专家系统如何运用谓词逻辑进行更复杂的推理
  • 模版题目的集合
  • maven--依赖的搜索顺序
  • 游戏引擎学习第158天
  • MySQL(第四周)
  • 整本书测试与巩固_《C++并发编程实战》笔记
  • C# 使用Markdown2Pdf把md文件转换为pdf文件
  • Flutter网页交互增强插件pulse_core_web的使用
  • “全志V821:智能玩具的理想之选”——科技赋能,乐趣升级
  • JVM调优关注的核心指标?
  • 《CircleCI:CircleCI:解锁软件开发持续集成(CI)和持续部署(CD)高效密码》
  • c++学习系列----002.写文件
  • soho网站建设/百度网页版官网
  • 网站seo插件/个人博客网站怎么做
  • 上海网站公司建设/电商平台怎么搭建
  • dede被挂赌博网站木马/百度推广开户渠道
  • 网站开发项目实战/品牌广告语经典100条
  • 会网站开发如何自己赚/网络营销有哪些例子