vue中通过.style.animationDuration属性,根据数据长度动态设定元素的纵向滚动时长的demo

根据数据长度动态设定元素的animation

先看看效果,是一个纯原生div标签加上css实现的表格纵向滚动动画:
在这里插入图片描述

HTML

1、确认好需要滚动内容的外盒子,并设置overflow: hidden;
2、类名为marquee的盒子为需要滚动内容的元素,给一个ref值之后通过获取ref设置元素的动画时长ref=“marqueeOld”
3、里面类名为row的子盒子是每行的表格内容
以下为控制台查看元素效果:
在这里插入图片描述

在这里插入图片描述

js逻辑

1、判断是数据长度是否达到滚动要求

滚动盒子的类绑定为 :class="{ ‘marquee’: shouldAnimate },在类名marquee 里给动画效果。以下为样式代码:

.marquee {
  /* infinite永久调用动画 */
  animation: material 300s linear infinite;
}

为了在计算属性中监听tableData数据的变化,若shouldAnimate返回为true,则有滚动marquee类名,否则不可滚动

可选链操作符 ? :在 JavaScript 中,当我们尝试访问一个对象的属性时,如果该对象为 null 或 undefined,通常会导致错误。可选链操作符 ? 可解决这一问题
这种写法可以让我们在访问对象的属性时更加安全,避免了因为对象不存在而导致的错误。特别是在处理来自外部或异步源的数据时,使用可选链操作符可以提高代码的健壮性。

computed: {
    shouldAnimate () {
      console.log("tableData.length >= 6", this.tableData.length >= 6);//若数据大于等于6条,则返回true;反之为false
      return this.tableData?.length >= 6; //这个?号是可选链操作符
    }
},

2、根据数据长度设置滚动速度

通过 refs 访问 DOM 元素时,有时需要在 DOM 渲染完成后才能正确获取到相应的元素,所以需要将设置滚动速度的逻辑放到 this.$nextTick 中,以确保 DOM 渲染完成后再进行操作,若没有nextTick 方法会找不到DOM,输出元素为undefined。

setMarqueeSpeed () {
      if (this.shouldAnimate) {
        this.$nextTick(() => {
          // 根据数据长度设置滚动速度
          this.$refs.marqueeOld.style.animationDuration = this.tableData.length * 2 + "s";
          console.log("this.$refs.marqueeOld.style.animationDuration", this.$refs.marqueeOld.style.animationDuration);
        });
      }
}

.style.animationDuration 是一个 DOM 元素的属性,用于设置或获取元素应用的动画持续时间。在这里的情况下,想要根据数据长度动态地设置滚动速度,使用 .style.animationDuration 就可以实现这一目的。
当设置 .style.animationDuration 时,可以为其赋予一个字符串数值,表示动画的持续时间。例如
element.style.animationDuration = “2s” 表示将动画持续时间设置为 2 秒。

所以通过动态设置 .style.animationDuration,可以根据数据的长度来调整滚动速度,从而实现动态的滚动效果。控制台输出animationDuration如下:
在这里插入图片描述

Demo完整代码

import jsondata from ‘./test.json’;
其中jsondata 为自己配置的数据,若是从接口获取,在获取数据那里调用setMarqueeSpeed方法即可

<template>
  <div class="innercolumn panel oldmaterial">
    <div class="inner"
         style="height: 100%">
      <h3><i class="icon-table"></i> 表格标题</h3>
      <div class="content"
           style="display: block">
        <div class="head headv1">
          <span class="col text-center">ID</span>
          <span class="col text-center">内容1</span>
          <span class="col text-center">内容2</span>
          <span class="col text-center">内容3</span>
          <span class="col text-right">内容4</span>
        </div>
        <div class="marquee-view">
          <div :class="{ 'marquee': shouldAnimate }"
               ref="marqueeOld"
               v-if="tableData">
            <div class="row"
                 v-for="(item, index) in tableData"
                 :key="index">
              <span class="col text-center nowrap">{{ item.ID }} </span>
              <span class="col text-center nowrap">{{ item.name1 }} </span>
              <span class="col text-center nowrap">{{ item.name2 }} </span>
              <span class="col text-center nowrap">{{ item.name3 }} </span>
              <span class="col text-right nowrap">{{ item.name4 }} </span>
              <span class="icon-location"></span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import jsondata from './test.json';
export default {
  data () {
    return {
      tableData: jsondata
    };
  },
  created () { },
  computed: {
    shouldAnimate () {
      console.log("tableData.length >= 6", this.tableData.length >= 6);
      return this.tableData.length >= 6;
    }
  },
  mounted () {
    this.setMarqueeSpeed();
  },
  methods: {
    setMarqueeSpeed () {
      if (this.shouldAnimate) {
        this.$nextTick(() => {
          // 根据数据长度设置滚动速度
          this.$refs.marqueeOld.style.animationDuration = this.tableData.length * 2 + "s";
          console.log("this.$refs.marqueeOld.style.animationDuration", this.$refs.marqueeOld.style.animationDuration);
        });
      }
    }
  },
};
</script>

<style scoped>
.oldmaterial {
  height: 17rem;
  background: #080866;
  color: #fff;
  padding: 1rem;
  width: 25%;
}
.oldmaterial .inner {
  /* padding: 1rem 0; */
  display: flex;
  flex-direction: column;
}
.oldmaterial .tabs {
  padding: 0 1.5rem;
  margin-bottom: 0.75rem;
}
.oldmaterial .tabs a {
  color: #1950c4;
  font-size: 0.75rem;
  padding: 0 1.125rem;
}

.oldmaterial .tabs a:first-child {
  padding-left: 0;
}

.oldmaterial .tabs a.active {
  color: #fff;
}
.oldmaterial .content {
  flex: 1;
  display: none;
  position: relative;
}
.oldmaterial .head {
  background: rgba(255, 255, 255, 0.1);
  font-size: 13px;
  padding: 0.5rem 0.5rem;
  color: #68d8fe;
  display: flex;
  justify-content: space-between;
  line-height: 1.05;
}
.oldmaterial .col {
  width: 4rem;
}
.oldmaterial .row {
  line-height: 1.05;
  padding: 0.5rem 0.5rem;
  color: #5b9cef;
  font-size: 1rem;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.oldmaterial .icon-location {
  position: absolute;
  left: -0.1rem;
  opacity: 0;
}
.oldmaterial .marquee-view {
  position: absolute;
  top: 2.4rem;
  bottom: 0;
  width: 100%;
  overflow: hidden;
}
.oldmaterial .row:hover {
  color: #5b9cef;
  background: rgba(255, 255, 255, 0.1);
}
.oldmaterial .row:hover .icon-location {
  opacity: 1;
}
@keyframes material {
  0% {
  }
  100% {
    transform: translateY(-50%);
  }
}
/* 调用动画 */
.oldmaterial .marquee {
  /* infinite永久调用动画 */
  animation: material 300s linear infinite;
}
/* 鼠标划入 停止动画  */
.oldmaterial .marquee:hover {
  animation-play-state: paused;
}
</style> 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值