uni-app 滚动通知组件的实现

一、实现思路

二、使用scroll-view 组件实现

<template>
  <view class="notice">
    <scroll-view
      class="notice-scroll"
      :scroll-y="true"
      :scroll-with-animation="true"
      :scroll-top="scrollTop"
    >
      <view :animation="animationData" class="notice-content">
        <view
          class="notice-item"
          v-for="(item, index) in noticeList"
          :key="index"
          @tap="handleClickNotice(item)"
        >
          <text>{
   
   { item.text }}</text>
        </view>
      </view>
    </scroll-view>
  </view>
</template>

<script>
  export default {
    name: "notice-bar",
    data() {
      return {
        noticeList: [], // 通知列表
        timer: null, // 定时器
        interval: 2000, // 滚动时间间隔
        scrollTop: 0, // 滚动距离
        currentIndex: 0, // 当前通知索引
      };
    },
    props: {
      notices: {
        // 外部传入的通知列表
        type: Array,
        default: [],
      },
    },
    mounted() {
      this.initNoticeList();
    },
    methods: {
      // 初始化通知列表
      initNoticeList() {
        const _this = this;
        _this.noticeList = _this.notices;
        if (_this.noticeList.length > 1) {
          _this.timer = setInterval(() => {
            _this.handleScrollNotice();
          }, _this.interval);
        }
      },
      // 点击通知时触发
      handleClickNotice(item) {
        this.$emit("click", item);
      },
      // 滚动通知
      handleScrollNotice() {
        const len = this.noticeList.length;
        if (this.currentIndex === len - 1) {
          this.currentIndex = 0;
        } else {
          this.currentIndex++;
        }
        this.animateScroll();
      },
      // 动画滚动
      animateScroll() {
        const _this = this;
        const noticeHeight = 30; // 通知高度,根据实际情况调整
        const scrollTop = _this.currentIndex * noticeHeight;
        _this.scrollTop = scrollTop;
      },
    },
    destroyed() {
      if (this.timer) {
        clearInterval(this.timer);
      }
    },
  };
</script>

<style scoped>
  .notice {
    /* 组件高度,根据实际情况调整 */
    height: 60rpx;
    overflow: hidden;
  }

  .notice-scroll {
    width: 100%;
    height: 100%;
  }

  .notice-content {
    display: flex;
    flex-direction: column;
  }

  .notice-item {
    /* 通知高度,根据实际情况调整 */
    height: 60rpx;
    /* 通知行高,根据实际情况调整 */
    line-height: 60rpx;
    padding-left: 20rpx;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
</style>

这个组件实现了一个纵向滚动的通知列表,可以根据传入的通知列表自动滚动显示。组件初始化时会根据通知列表长度判断是否需要滚动,并设置定时器自动滚动。当用户点击某个通知时,会触发组件的 click 事件,并将点击的通知对象作为参数传递给父组件。组件的动画效果使用了 uni-app 的动画系统,通过创建一个动画对象并设置 translateY 属性来实现纵向滚动效果。

三、使用uni.createAnimationAPI 实现

<template>
  <view class="notice">
    <view :animation="animationData" class="notice-content">
      <view
        class="notice-item"
        v-for="(item, index) in noticeList"
        :key="index"
        @tap="handleClickNotice(item)"
      >
        <text>{
   
   { item.text }}</text>
      </view>
    </view>
  </view>
</template>

<script>
  export default {
    name: "notice-bar",
    data() {
      return {
        noticeList: [], // 通知列表
        animation: null, // 动画对象
        animationData: {},
        timer: null, // 定时器
        interval: 2000, // 滚动时间间隔
        scrollTop: 0, // 滚动距离
        currentIndex: 0, // 当前通知索引
      };
    },
    props: {
      notices: {
        // 外部传入的通知列表
        type: Array,
        default: [],
      },
    },
    mounted() {
      this.initNoticeList();

      const _this = this;
      _this.animation = uni.createAnimation({
        duration: 500,
        timingFunction: "ease-out",
      });
    },
    methods: {
      // 初始化通知列表
      initNoticeList() {
        const _this = this;
        _this.noticeList = _this.notices;
        if (_this.noticeList.length > 1) {
          _this.timer = setInterval(() => {
            _this.handleScrollNotice();
          }, _this.interval);
        }
      },
      // 点击通知时触发
      handleClickNotice(item) {
        this.$emit("click", item);
      },
      // 滚动通知
      handleScrollNotice() {
        const len = this.noticeList.length;
        if (this.currentIndex === len - 1) {
          this.currentIndex = 0;
        } else {
          this.currentIndex++;
        }
        this.animateScroll();
      },
      // 动画滚动
      animateScroll() {
        const _this = this;
        const noticeHeight = 30; // 通知高度,根据实际情况调整
        const scrollTop = _this.currentIndex * noticeHeight;

        if (scrollTop === 0) {
          _this.animation.translateY(-scrollTop).step({
            duration: 0,
          });
        } else {
          _this.animation.translateY(-scrollTop).step();
        }
        _this.animationData = _this.animation.export();
      },
    },
    destroyed() {
      if (this.timer) {
        clearInterval(this.timer);
      }
      if (this.animation) {
        this.animation = null;
      }
    },
  };
</script>

<style scoped>
  .notice {
    /* 组件高度,根据实际情况调整 */
    height: 60rpx;
    overflow: hidden;
  }

  .notice-scroll {
    width: 100%;
    height: 100%;
  }

  .notice-content {
    display: flex;
    flex-direction: column;
  }

  .notice-item {
    /* 通知高度,根据实际情况调整 */
    height: 60rpx;
    /* 通知行高,根据实际情况调整 */
    line-height: 60rpx;
    padding-left: 20rpx;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
</style>

猜你喜欢

转载自blog.csdn.net/lwf3115841/article/details/130031930