vue3

跑马灯效果

<template>
  <div>
    <Marquee :speed="100">
      <div>跑马灯内容1</div>
      <div>跑马灯内容2</div>
      <div>跑马灯内容3</div>
    </Marquee>
  </div>
</template>

<script>
import Marquee from './components/Marquee.vue'

export default {
  name: 'App',
  components: {
    Marquee
  }
}
</script>
<template>
  <div class="marquee-outer" ref="marqueeOuter">
    <div
      class="marquee-inner"
      :style="{ transform: `translateX(${translateX}px)` }"
    >
      <!-- <slot />
      <slot /> -->
      <div>跑马灯内容1</div>
      <div>跑马灯内容2</div>
      <div>跑马灯内容3</div>
    </div>
  </div>
</template>

<script>
import { ref, watch } from 'vue'

export default {
  name: 'Marquee',
  props: {
    speed: {
      type: Number,
      default: 50 // 默认速度为50px/s
    }
  },
  setup(props) {
    const marqueeOuter = ref(null)
    const marqueeWidth = ref(0)
    const translateX = ref(0)

    // 获取跑马灯容器的宽度
    function getMarqueeWidth() {
      if (marqueeOuter.value) {
        marqueeWidth.value = marqueeOuter.value.offsetWidth
      }
    }

    // 监听子节点变化,更新跑马灯容器的宽度
    watch(
      () => marqueeOuter.value.children,
      () => {
        getMarqueeWidth()
      }
    )

    // 滚动跑马灯
    function scrollMarquee() {
      if (translateX.value > -marqueeWidth.value) {
        translateX.value -= props.speed / 60 // 每秒滚动props.speed个像素
        requestAnimationFrame(scrollMarquee)
      } else {
        // 跑马灯滚动完成
        translateX.value = marqueeWidth.value
      }
    }

    return {
      marqueeOuter,
      marqueeWidth,
      translateX,
      getMarqueeWidth,
      scrollMarquee
    }
  },
  mounted() {
    this.getMarqueeWidth()
    this.scrollMarquee()
  }
}
</script>

<style>
.marquee-outer {
  position: relative;
  display: flex;
  overflow: hidden;
}

.marquee-inner {
  display: flex;
}

/* 子元素样式,可根据实际需求修改 */
.marquee-inner > * {
  margin-right: 20px;
}
</style>
上次更新: