亲宝软件园·资讯

展开

手把手教你用VUE封装一个文本滚动组件

Sumu 人气:0

一、引言

项目有文本滚动展示的需求,一开始使用marquee标签来实现需求,但是看一下MDN对该标签的描述:

这个标签已经不再推荐使用了,那就自己封装一个类似的组件来用。

二、实现思路

1.如何让文本滚动起来?

通过动画我们设置过渡transform:translateX(a) => transfrom:translateX(b)来实现向左或向右的滚动效果。transform:translateY(c) => transfrom:translateY(d)来实现向下或向上的滚动效果。

2.组件需要哪些配置?

(1)滚动的方向:上右下左

(2)滚动的速度:这里我以px/s作为单位

三、实现过程

1.html

2.css

最外层的div为滚动的可视区,里面的div为文本滚动区可视区宽度高度均为100%使用时大小由外部容器决定,overflow设为hidden,防止文本滚动区滚动出可视区外仍可见。文本滚动区设置宽高都为fit-content使大小随内容自适应,内部设置插槽使用组件时插入滚动内容。

3.动画

动画应设置在文本滚动区

需要上右下左四个方向滚动的动画,我们只需要定义上左两个方向,另外两个方向直接反转即可。先来想想向上滚动的动画怎么写,向上滚动的话文本滚动区的起点应设置在可视区外正下方,所以动画的起点应为 transform: translateY(可视区的高度),终点应设置在可视区外正上方应为transform: translateY(-100%)。

向上向左动画即为:

--text-scroll-height、--text-scroll-width两个css变量的值是可视区的高度和宽度,由于可视区的宽高不确定,所以需要通过js获取并设置这两个css变量。

注意: 动画样式不能加上scoped,否则不生效!

4.js

(1)组件配置

通过props传入组件配置

(2)计算得到滚动动画

scrollLength为一次动画的实际滚动的长度,time为一次动画的持续时间。我们可以算出scrollLength应为:可视区的宽或高加上文本滚动区的宽或高(根据滚动的方向来判断是宽还是高)。time应为 scrollLegnth / 组件配置的滚动速度。

(3)生命周期

在mounted里调用上面的方法初始化组件。在updated里同样调用该方法,当组件宽高改变或插槽内容变动重新计算动画样式。

三、完整代码

<template>
  <!-- 文本滚动 -->
  <div class="text-scroll" ref="textScroll">
    <div class="content" ref="content" :style="scrollAnimation">
      <!-- 默认插槽,插入滚动内容 -->
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "TextScroll",
  props: {
    /* 滚动方向
     * value: up、down、left、right
     */
    direction: {
      default: "up",
      type: String,
    },
    //滚动速度 单位px/s
    speed: {
      default: 60,
      type: Number,
    },
  },
  data() {
    return {
      //滚动动画
      scrollAnimation: {},
    };
  },
  methods: {
    getScrollAnimation() {
      //获取文本滚动实际显示宽度高度,设为css变量,用于设置动画开始起始位置
      let height = this.$refs.textScroll.offsetHeight;
      let width = this.$refs.textScroll.offsetWidth;
      this.$refs.content.style.setProperty(
        "--text-scroll-height",
        `${height}px`
      );
      this.$refs.content.style.setProperty("--text-scroll-width", `${width}px`);
      //滚动长度、时间
      let scrollLength, time;
      //根据滚动方向来设置不同的滚动动画
      switch (this.direction) {
        case "up":
          scrollLength =
            this.$refs.content.offsetHeight +
            height;
          time = scrollLength / this.speed;
          this.scrollAnimation.animation = `up-scroll linear ${time}s infinite`;
          break;
        case "down":
          scrollLength =
            this.$refs.content.offsetHeight +
            height;
          time = scrollLength / this.speed;
          this.scrollAnimation.animation = `up-scroll linear ${time}s infinite reverse`;
          break;
        case "left":
          scrollLength =
            this.$refs.content.offsetWidth + width;
          time = scrollLength / this.speed;
          this.scrollAnimation.animation = `left-scroll linear ${time}s infinite`;
          break;
        case "right":
          scrollLength =
            this.$refs.content.offsetWidth + width;
          time = scrollLength / this.speed;
          this.scrollAnimation.animation = `left-scroll linear ${time}s infinite reverse`;
          break;
      }
    },
  },
  async mounted() {
    //设置文本滚动动画
    this.getScrollAnimation();
  },
  updated() {
    //当插槽内容更新重新计算滚动动画
    this.getScrollAnimation();
  },
};
</script>

<style scoped lang="scss">
.text-scroll {
  width: 100%;
  height: 100%;
  overflow: hidden;

  .content {
    height: fit-content;
    width: fit-content;
  }
}
</style>

<style lang="scss">
.text-scroll {
  .content {
    @keyframes up-scroll {
      0% {
        transform: translateY(var(--text-scroll-height));
      }

      100% {
        transform: translateY(-100%);
      }
    }

    @keyframes left-scroll {
      0% {
        transform: translateX(var(--text-scroll-width));
      }

      100% {
        transform: translateX(-100%);
      }
    }
  }
}
</style>

总结

加载全部内容

相关教程
猜你喜欢
用户评论