weex封装滚动通知栏

114 阅读1分钟

<template>
  <div class="notice" @click="jump">
    <div class="notice_left">
      <image :src="icon" class="icon"></image>
      <!-- <text class="tag">活动</text> -->
    </div>

    <div class="marquee-container" ref="marqueeContainer">
      <text ref="marqueeText" :style="{ transform: `translateX(${scrollPosition}px)` }" class="marquee-text">{{ visibleText }}</text>
      <!-- <div class="notice_right"></div> -->
    </div>

    <image class="notice_right" :src="
                  'https://xxx.png'"></image>

  </div>
</template>  
  
<script>
const animation = weex.requireModule("animation") || {};
const dom = weex.requireModule("dom") || {};
const modal = weex.requireModule("modal");
const platform = weex.config.env.platform;
export default {
  props: {
    text: {
      type: String,
      default: "",
    },
    url: {
      type: String,
    },
    icon: {
      type: String,
    },
    type: {
      default: "",
    },
  },
  data() {
    return {
      // text: "这是一条滚动的公告消息",
      visibleText: "", // 当前显示的文本片段
      containerWidth: 0, // 容器宽度
      textWidth: 0, // 文本宽度
      scrollPosition: 0, // 滚动位置
      speed: 5, // 滚动速度
      timer: null, // 定时器
      timer2: null, // 定时器
      num: 1,
    };
  },
  created() {},
  mounted() {
    this.initMarquee();
  },
  beforeDestroy() {
    this.stopMarquee();
  },
  methods: {
    initMarquee() {
      // 设置初始显示的文本片段
      this.visibleText = this.text;
      // 开始滚动文本
      this.timer2 = setTimeout(() => {
        this.start();
      }, 1000);
    },
    // animation动画实现方式
    start() {
      let durationTime = 15000;
      if (this.text && this.text.length > 0) {
        durationTime = this.text.length * 400; //计算滚动时长 按400毫秒走1个字计算
      }
      // console.log({ durationTime });
      const el2 = this.$refs.marqueeContainer;
      // 获取文本宽度
      const el1 = this.$refs.marqueeText;
      dom.getComponentRect(el2, (ops) => {
        console.log("父盒子宽度:", ops.size.width);
        let containerWidth = ops.size.width;
        dom.getComponentRect(el1, (ops) => {
          this.textWidth = -ops.size.width;
          console.log(this.num);
          if (this.num > 1) {
            this.scrollPosition = -ops.size.width;
          }
          this.num = this.num + 1;
          console.log("文本宽度:", ops.size.width);
          animation.transition(
            el1,
            {
              styles: {
                transform: `translateX(${this.textWidth})`,
              },
              duration: durationTime, //ms
              timingFunction: "linear",
              needLayout: false,
              // delay: 1000, //ms
            },
            () => {
              this.scrollPosition = containerWidth;
              console.log(
                " this.$refs.marqueeText.style:",
                this.$refs.marqueeText.style
              );
              this.visibleText = this.text;
              //走完 将通知栏销毁
              this.$emit("getNoticeShowFlag", false);
              // setTimeout(() => {
              //如果想循环可以放开
              //   this.start();
              // }, 0);
            }
          );
        });
      });
    },
    // 定時器实现方案 不是很流畅
    startMarquee() {
      let num = 1;
      this.timer = setInterval(() => {
        num = num + 2;
        // console.log({ num });
        const el2 = this.$refs.marqueeContainer;
        dom.getComponentRect(el2, (ops) => {
          // console.log("父盒子宽度:", ops.size.width);
          let containerWidth = ops.size.width;
          this.scrollPosition -= this.speed;
          // 获取文本宽度
          const el1 = this.$refs.marqueeText;
          dom.getComponentRect(el1, (ops) => {
            this.textWidth = ops.size.width;
            // console.log("文本宽度:", ops.size.width);
            // console.log("滚动值:", this.scrollPosition);
            // 当文本完全滚出屏幕时,重置滚动位置并显示文本的剩余部分
            if (this.scrollPosition < -this.textWidth) {
              this.scrollPosition = containerWidth;
              if (num > parseFloat(1500 / this.speed)) {
                this.$emit("getNoticeShowFlag", false);
              }
              this.visibleText = this.text;
            }
          });
        });
      }, 100);
    },
    stopMarquee() {
      clearInterval(this.timer);
      this.timer = null;
      clearInterval(this.timer2);
      this.timer2 = null;
    },

    jump() {
      console.log(this.type, this.url);
      if (!this.url) return;
      
      }
    },
  },
};
</script>  
  
<style scoped>
.notice {
  flex-direction: row;
  align-items: center;
  overflow: hidden;
  position: relative;
  box-sizing: border-box;
  padding: 0 20px;
  background-color: #f7fff9;
  box-shadow: 0px 2px 4px 0px rgba(210, 213, 232, 0.5);
  border-radius: 8px;
}
.marquee-container {
  align-items: center;
  padding-left: 20px;
  padding-right: 20px;
  height: 72px;
  overflow: hidden;
  position: relative;
  flex-direction: row;
}

.notice_left {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  margin-right: 8px;
  /* width: 120px; */
  width: 72px;
}

.icon {
  width: 72px;
  height: 36px;
  margin-right: 16px;
}

.tag {
  border-width: 1px;
  border-style: solid;
  border-color: #ff8040;
  padding: 8px;
  border-radius: 4px;
  font-family: PingFang-SC, PingFang-SC;
  font-weight: 500;
  font-size: 18px;
  color: #ff8040;
}

.marquee-text {
  position: absolute;
  white-space: nowrap; /* 防止文本换行 */
  /* will-change: transform; 优化滚动性能 */
  /* background-color: yellow; */
  overflow: hidden;
  font-size: 24px;
  color: #5a5a5a;
  line-height: 34px;
  text-shadow: 0px 4px 4px rgba(137, 137, 137, 0.5);

  text-overflow: ellipsis;
  white-space: nowrap;

  /* 滚动优化 */
  /* transition-property: transform;
  transition-timing-function:linear; */
  /* transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1); */
}

.marquee-container {
  flex: 1;
  /* background-color: hotpink; */
  padding: 0;
  margin: 0;
  justify-content: start;
  text-align: left;
}

.notice_right {
  width: 24px;
  height: 24px;
  margin-left: 8px;
}
</style>
<template>
<home class="home">
    <!-- 通知栏 -->
    <div class="topNotice" v-if="false" :style="{
       top: '358px'   
    }">
      <Notice class="capsule-banner-wrapper2" v-if="NoticeShow&&noticeData.text" @getNoticeShowFlag="(val)=>this.NoticeShow=val" :icon="noticeData.icon" :jumpType="1" :NoticeShow="NoticeShow" :text="noticeData.text"
        :url="noticeData.url" />
    </div>
</home>
</template>
<script>
import { WxcLoading } from "weex-ui";
import {
  Notice,
} from "@/components";

export default {
  components: {
    WxcLoading,
    Notice,
  },
  data() {
    return {
      // 通知栏数据
      NoticeShow: true,
      noticeData: {
        icon: "https://dcdn.mynj.cn/cdnicon/appicon/register/tongzhi.png",
        text: "",
        url: "https://wwww.baidu.com",
        notice: "https://t8.baidu.com/it/u=1521416094,2001553822&fm=193",
      },
    };
  },
  methods: {
  }
};
</script>

<style>
.home{
position:relative;
height:100%;
overflow-x:hidden;
overflow-y:scroll;
}
.topNotice {
  position: absolute;
  top: 340px; 
}
</style>