美文网首页
手写一个NoticeBar 通知栏组件

手写一个NoticeBar 通知栏组件

作者: 德日班勒 | 来源:发表于2019-12-02 10:06 被阅读0次

    我们无论是移动端还是PC端都会遇到像滚动新闻的展示方式


    演示.gif

    自己做了一个组件,方便以后调用
    下面是组件内部代码:

    <template>
      <transition name="fade">
        <!--主要内容-->
        <div class="noticebar" :style="{backgroundColor:data.backround}">
          <div style="margin-left:5px"></div>
          <img v-if="data.icon" :style="{height:data.iconSize?data.iconSize:'16px',width:data.iconSize?data.iconSize:'16px'}" :src=data.icon alt="">
          <div style="margin-right:5px"></div>
          <div ref="back" class="back">
            <span ref="text" :style="{fontSize:data.size?data.size:'16px',color:data.color?data.color:'#f60'}" class="text">{{ data.text?data.text:'通知内容' }}</span>
          </div>
        </div>
      </transition>
    </template>
    <script>
    export default {
        props: {
            options: {
                type: Object,
                default() {
                    return {
                        text: '默认'
                    };
                }
            }
        },
        data() {
            return {
                speed: this.options.speed, // 速度(单位px/s)
                backWidth: '', // 父级宽度
                backHeight: '', // 父级高度
                wordLength: '', // 文本长度
                state: 1,
                firstAnimationTime: '', // 状态一动画效果
                secondAnimationTime: '', // 状态二动画效果
                data: this.options
            };
        },
        methods: {
            // 获取数据
            getData() {
                let style = document.styleSheets[0];
                let text = this.$refs.text;
                let back = this.$refs.back;
                this.backWidth = back.offsetWidth;
                this.backHeight = back.offsetHeight;
                text.style.lineHeight = this.backHeight + 'px';
                this.wordLength = text.offsetWidth;
                this.ComputationTime(); // 计算时间
                style.insertRule(
                    `@keyframes firstAnimation {0%   {left:0px;}100%  {left:-${this.wordLength}px;}}`
                );
                style.insertRule(
                    `@keyframes secondAnimation {0%   {left:${this.backWidth}px;}100%  {left:-${this.wordLength}px;}}`
                );
                setTimeout(res => {
                    this.changeState();
                }, this.data.delay);
            },
            // 用速度计算时间(想要保持速度一样,2种状态时间不同需算出)
            ComputationTime() {
                this.firstAnimationTime = this.wordLength / this.speed;
                this.secondAnimationTime =
                    (this.wordLength + this.backWidth) / this.speed;
            },
            // 根据状态切换动画
            changeState() {
                let text = this.$refs.text;
                if (this.state == 1) {
                    text.style.animation = `firstAnimation ${this.firstAnimationTime}s linear`;
                    this.state = 2;
                } else {
                    text.style.animation = `secondAnimation ${this.secondAnimationTime}s linear infinite`;
                }
            },
            Listener() {
                let text = this.$refs.text;
                console.log(text);
                text.addEventListener(
                    'animationend',
                    res => {
                        this.changeState();
                    },
                    false
                );
            }
        },
        mounted() {
            this.Listener();
            setTimeout(res => {
                this.getData();
            }, 100);
        }
    };
    </script>
    <style lang="less" scoped>
    .noticebar {
        display: flex;
        align-items: center;
        height: 100%;
        width: 100%;
        background-color: #fff7cc;
        .icon {
            img {
                height: 100%;
                width: 100%;
            }
        }
        .back {
            overflow: hidden;
            white-space: nowrap;
            margin: 0 auto;
            height: 100%;
            width: 100%;
            position: relative;
            .text {
                position: absolute;
                display: inline-block;
                padding: 2px 0;
            }
        }
    }
    </style>
    

    父组件调用:

    <template>
      <transition name="fade">
        <div class="wrap">
          <div class="father">
            <noticebar :options=options></noticebar>
          </div>
        </div>
      </transition>
    </template>
    <script>
    import noticebar from './noticebar';
    export default {
        components: {
            noticebar
        },
        data() {
            return {
                // noticebar 组件的配置项
                options: {
                    text:'日本网友momopoi家的柯基,表情管理经常崩坏,可以说是喜怒形于色的典范', // 通知内容
                    icon:'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=236296424,1105446647&fm=26&gp=0.jpg', // 左侧图标(不需要icon不传)
                    iconSize: '16px', // icon大小(正方形默认16px)
                    size: '16px', // 通知内容文字大小(默认16px)
                    color: '#1989fa', // 通知内容文字颜色(默认#f60)
                    backround: '#fff7cc', //背景颜色(默认#fff7cc)
                    delay: '1000', // 动画延迟时间(默认一秒后开始滚动,单位毫秒)
                    speed: '50' // 滚动速率默认50 (px/s)
                }
            };
        }
    };
    </script>
    <style lang="less" scoped>
    .wrap {
        .father {
            margin: 150px auto;
            height: 60px;
            width: 100%;
            img {
                height: 100%;
                width: 20px;
            }
        }
    }
    </style>
    

    目前可供的配置项在option中,以后有什么好的建议请在评论留言,我会关注并且经常更新这个组件。

    相关文章

      网友评论

          本文标题:手写一个NoticeBar 通知栏组件

          本文链接:https://www.haomeiwen.com/subject/ejdxgctx.html