Vue3滚动轮播组件实现超标信息自动滚动

创建滚动轮播组件实现超标信息自动滚动

为了实现超出父容器高度时的自动轮播滚动效果,我们可以创建一个通用的滚动组件,通过插槽来包裹内容。

1. 组件代码如下

vue:/Users/dylan/Documents/GitHub/Supervision-of-cooking-fume/src/components/ScrollList.vue 复制代码
<template>
  <div 
    ref="container" 
    class="scroll-container" 
    :style="{ height: height }"
    @mouseenter="pauseScroll" 
    @mouseleave="resumeScroll"
  >
    <div 
      ref="wrapper"
      class="scroll-wrapper"
      :class="{ 'scrolling': isScrolling }"
      :style="{ animationDuration: `${duration}s`, animationPlayState: isPaused ? 'paused' : 'running' }"
    >
      <slot></slot>
      <!-- 当内容超出时,复制一份内容用于无缝滚动 -->
      <div v-if="needScroll" class="scroll-duplicate">
        <slot></slot>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue';

const props = defineProps({
  // 容器高度
  height: {
    type: String,
    default: '100%'
  },
  // 滚动速度,单位秒
  duration: {
    type: Number,
    default: 20
  },
  // 是否自动开始滚动
  autoScroll: {
    type: Boolean,
    default: true
  },
  // 滚动延迟,单位毫秒
  delay: {
    type: Number,
    default: 500
  }
});

const container = ref(null);
const wrapper = ref(null);
const isScrolling = ref(false);
const isPaused = ref(!props.autoScroll);
const needScroll = ref(false);

// 检查是否需要滚动
const checkNeedScroll = async () => {
  await nextTick();
  if (!container.value || !wrapper.value) return;
  
  const containerHeight = container.value.clientHeight;
  const contentHeight = wrapper.value.scrollHeight / (needScroll.value ? 2 : 1);
  
  needScroll.value = contentHeight > containerHeight;
  
  if (needScroll.value && props.autoScroll) {
    startScroll();
  } else {
    stopScroll();
  }
};

// 开始滚动
const startScroll = () => {
  isScrolling.value = true;
  isPaused.value = false;
};

// 停止滚动
const stopScroll = () => {
  isScrolling.value = false;
};

// 暂停滚动
const pauseScroll = () => {
  isPaused.value = true;
};

// 恢复滚动
const resumeScroll = () => {
  if (needScroll.value) {
    isPaused.value = false;
  }
};

// 监听内容变化
const observer = ref(null);

onMounted(() => {
  // 初始检查
  setTimeout(checkNeedScroll, props.delay);
  
  // 监听内容变化
  if (window.MutationObserver) {
    observer.value = new MutationObserver(checkNeedScroll);
    if (wrapper.value) {
      observer.value.observe(wrapper.value, {
        childList: true,
        subtree: true,
        characterData: true
      });
    }
  }
  
  // 监听窗口大小变化
  window.addEventListener('resize', checkNeedScroll);
});

onUnmounted(() => {
  if (observer.value) {
    observer.value.disconnect();
  }
  window.removeEventListener('resize', checkNeedScroll);
});

// 监听props变化
watch(() => props.autoScroll, (newVal) => {
  isPaused.value = !newVal;
});

// 暴露方法给父组件
defineExpose({
  checkNeedScroll,
  startScroll,
  stopScroll,
  pauseScroll,
  resumeScroll
});
</script>

<style scoped>
.scroll-container {
  overflow: hidden;
  position: relative;
  width: 100%;
}

.scroll-wrapper {
  position: relative;
  width: 100%;
}

.scrolling {
  animation: scrollAnimation linear infinite;
}

@keyframes scrollAnimation {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-50%);
  }
}

.scroll-duplicate {
  /* 确保复制的内容样式与原内容一致 */
}
</style>

2. 使用示例

vue:/Users/dylan/Documents/GitHub/Supervision-of-cooking-fume/src/views/IndexView.vue 复制代码
<script setup>
import { ref, onMounted, onUnmounted, inject } from "vue";
// 导入依赖...
import ScrollList from "@/components/ScrollList.vue"; // 导入滚动组件

// 其他代码...
</script>

<template>
    <div>
        <ScrollList
            class="flex-1 w-full hide-scrollbar"
            :duration="30"
          >
            <div
              v-for="(item, index) in 100"
              :key="index"
            >
              {{item}}
            </div>
          </ScrollList>
    </div>
</template>

组件功能说明

  1. 自动检测:组件会自动检测内容是否超出容器高度,只有超出时才会启动滚动

  2. 无缝滚动:通过复制一份内容实现无缝循环滚动效果

  3. 交互控制:鼠标悬停时暂停滚动,移出时恢复滚动

  4. 可配置性

    • height:设置容器高度
    • duration:控制滚动速度
    • autoScroll:是否自动开始滚动
    • delay:初始检测延迟时间
  5. 响应式

    • 监听内容变化自动更新滚动状态
    • 监听窗口大小变化重新计算是否需要滚动

这个组件设计为通用组件,可以在项目中的其他需要滚动展示的地方复用,提高代码的可维护性和一致性。

相关推荐
文火冰糖的硅基工坊12 分钟前
[嵌入式系统-146]:五次工业革命对应的机器人形态的演进、主要功能的演进以及操作系统的演进
前端·网络·人工智能·嵌入式硬件·机器人
2401_8370885024 分钟前
ResponseEntity - Spring框架的“标准回复模板“
java·前端·spring
yaoganjili33 分钟前
用 Tinymce 打造智能写作
前端
angelQ40 分钟前
Vue 3 中 ref 获取 scrollHeight 属性为 undefined 问题定位
前端·javascript
Dontla1 小时前
(临时解决)Chrome调试避免跳入第三方源码(设置Blackbox Scripts、将目录添加到忽略列表、向忽略列表添加脚本)
前端·chrome
我的div丢了肿么办1 小时前
js函数声明和函数表达式的理解
前端·javascript·vue.js
云中雾丽1 小时前
React.forwardRef 实战代码示例
前端
朝歌青年说1 小时前
一个在多年的技术债项目中写出来的miniHMR热更新工具
前端
武天1 小时前
一个项目有多个后端地址,每个后端地址的请求拦截器和响应拦截器都不一样,该怎么封装
vue.js
Moonbit1 小时前
倒计时 2 天|Meetup 议题已公开,Copilot 月卡等你来拿!
前端·后端