vue开发marquee文字跑马灯效果组件

在这里插入图片描述组件调用时候的使用方式:

<template>
  <div>
    <div class="demo">
      <notice-bar :text="text"></notice-bar>
    </div>
  </div>
</template>

<script>
import NoticeBar from "./components/notice-bar"
export default {
  components: {
    NoticeBar,
  },
  data() {
    return {
      text: "在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。而开始一不舒服在大黄蜂很纠结的好哦尽量降低妇女 啊hi弗拉啊发来拉动房价弗里达解放军尽快。"
    }
  }
}
</script>

<style scoped>
.demo {
  width: 800px;
  margin: 0 auto;
}
</style>

滚动notice-bar组件的实现方式一:

通过开启定时器setInterval配合css3的 transfrom: translateX()实现。

<template>
  <div class="my-outbox" ref="wrap">
    <div class="my-inbox" ref="content">
      <div class="my-list">
        {{ text }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "NoticeBar",
  props: {
    text: {
      Type: String,
      default: ""
    }
  },
  data() {
    return {
      wrapWidth: 0,
      contentWidth: 0,
    };
  },
  activated() {
  // keep-alive 缓存的组件,在重新激活的时候,必须要重新触发滚动,不然会停止不动了。
  this.start();
  },
  created() {},
  mounted() {
    this.start();
  },
  methods: {
    start() {
      const { wrap, content } = this.$refs;
      this.wrapWidth = wrap.getBoundingClientRect().width;
      this.contentWidth = content.getBoundingClientRect().width;
      this.animateFn();
    },
    animateFn() {
      const { content } = this.$refs;
      let distance = this.wrapWidth;
      content.style.transform = "translateX(" + distance + "px)"; //初始值
      let that = this
      setInterval(function() {
        distance = distance - 1;
        if (-distance >= that.contentWidth) {
          distance = that.wrapWidth;
        }
        content.style.transform = "translateX(" + distance + "px)";
      }, 20); //控制速度
    }
  },
  // 更新的时候运动
  updated: function() {
    this.animateFn();
  }
};
</script>

<style lang="scss" scoped>
.my-outbox {
  color: #d7bc8d;
  overflow: hidden;
  height: 35px;
  background: #422b02;
  position: relative;
  .my-inbox {
    white-space: nowrap;
    position: absolute;
    font-size: 0;
    .my-list {
      margin-right: 25px;
      display: inline-block;
      font-size: 13px;
      height: 35px;
      line-height: 35px;
    }
  }
}
</style>

实现方式二:

通过window.requestAnimationFrame配合transform:translateX()实现,
当然了,该组件并未彻底完成,插槽,未添加。

<template>
  <div ref="wrap" class="bar-wrap" :style="barStyle" role="marquee">
    <div
      ref="content"
      class="content"
      :style="contentStyle"
      @transitionend="onTransitionEnd"
    >
      {{ text }}
    </div>
  </div>
</template>

<script>
var lastTimeStamp = new Date().getTime();
function fallback(fn) {
  let currTimeStamp = new Date().getTime();
  let delay = Math.max(0, 16 - (currTimeStamp - lastTimeStamp));
  let handle = setTimeout(function() {
    fn(currTimeStamp);
  }, delay);
  lastTimeStamp = currTimeStamp;
  return handle;
}
function doubleRaf(fn) {
  raf(() => {
    raf(fn);
  });
}
function raf(fn) {
  // 在requestAnimationFrame不可用的时候,使用自定义的fallback来模拟
  const iRaf = window.requestAnimationFrame || fallback;
  return iRaf.call(window, fn);
}
export default {
  name: "NoticeBar",
  props: {
    text: {
      type: String,
      default: ""
    },
    color: {
      type: String,
      default: "#000"
    },
    leftIcon: {
      type: String,
      default: ""
    },
    background: {
      type: String,
      default: ""
    },
    delay: {
      type: [Number, String],
      default: 1
    },
    speed: {
      type: [Number, String],
      default: 50
    }
  },
  data() {
    return {
      show: true,
      offset: 0,
      duration: 0,
      wrapWidth: 0,
      contentWidth: 0,
    };
  },
  computed: {
    barStyle() {
      return {
        color: this.color,
        background: this.background
      };
    },
    contentStyle() {
      return {
        transform: this.offset ? `translateX(${this.offset}px)` : "",
        transitionDuration: this.duration + "s",
        transitionTimingFunction: "linear"
      };
    }
  },
  watch: {
    scrollable: "start",
    text: {
      handler: "start",
      immediate: true
    }
  },
  activated() {
    // this.start();
  },
  created() {
    this.start();
  },
  mounted() {},
  methods: {
    onTransitionEnd() {
      this.offset = this.wrapWidth;
      this.duration = 0;

      // wait for Vue to render offset
      this.$nextTick(() => {
        // use double raf to ensure animation can start
        doubleRaf(() => {
          this.offset = -this.contentWidth;
          this.duration = (this.contentWidth + this.wrapWidth) / this.speed;
          this.$emit("replay");
        });
      });
    },
    reset() {
      this.offset = 0;
      this.duration = 0;
      this.wrapWidth = 0;
      this.contentWidth = 0;
    },
    start() {
      const delay = this.delay * 1000;

      this.reset();

      setTimeout(() => {
        const { wrap, content } = this.$refs;
        if (!wrap || !content) {
          return;
        }

        const wrapWidth = wrap.getBoundingClientRect().width;
        const contentWidth = content.getBoundingClientRect().width;

        if (contentWidth > wrapWidth) {
          doubleRaf(() => {
            this.offset = -contentWidth;
            this.duration = contentWidth / this.speed;
            this.wrapWidth = wrapWidth;
            this.contentWidth = contentWidth;
          });
        }
      }, delay);
    }
  }
};
</script>

<style lang="scss" scoped>
.bar-wrap {
  height: 35px;
  overflow: hidden;
  position: relative;
  background: #422b02;
  line-height: 35px;
}
.content {
  white-space: nowrap;
  position: absolute;
  color: #d7bc8d;
}
</style>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue跑马灯 (marquee) 组件是一种常见的UI组件,可以用于在页面上展示滚动的文字或图片。以下是一个简单的Vue跑马灯组件示例: ```vue <template> <div class="marquee"> <div class="marquee-content" :style="{transform: 'translateX(' + position + 'px)'}"> <slot></slot> </div> </div> </template> <script> export default { data() { return { position: 0, interval: null }; }, mounted() { this.interval = setInterval(() => { const content = this.$el.querySelector('.marquee-content'); const width = content.offsetWidth; const parentWidth = this.$el.offsetWidth; if (width > parentWidth) { this.position -= 1; if (Math.abs(this.position) >= width) { this.position = parentWidth; } } }, 20); }, beforeDestroy() { clearInterval(this.interval); } }; </script> <style> .marquee { overflow: hidden; } .marquee-content { display: inline-block; white-space: nowrap; } </style> ``` 在上面的示例中,我们定义了一个名为 `marquee` 的组件,它包含一个名为 `marquee-content` 的子组件,用于包裹滚动的内容。我们使用CSS的 `overflow` 属性设置父元素为 `hidden`,以隐藏超出父元素边界的内容。 在 `mounted` 钩子函数中,我们使用 `setInterval` 函数定时更新 `marquee-content` 的 `transform` 属性,以实现滚动效果。我们在 `beforeDestroy` 钩子函数中清除定时器,以避免内存泄漏。 在使用 `marquee` 组件时,我们可以将需要滚动的内容插入到组件中,例如: ```vue <marquee> <img src="image1.jpg" alt="Image 1"> <img src="image2.jpg" alt="Image 2"> <img src="image3.jpg" alt="Image 3"> </marquee> ``` 在上面的示例中,我们插入了三张图片到 `marquee` 组件中。这些图片将在组件中滚动,并且当它们的宽度超出父元素的宽度时,它们将自动滚动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值