直播聊天消息滚动效果实现

实现的效果如下


7f8742e08764771fb614f6bf3b03a33f.gif

直接上代码吧

<!DOCTYPE html>
<html lang="en">

<head>
    <title></title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="css/zhibo.css" rel="stylesheet">
</head>

<body>
    <div id="app">
        <!-- 留言输入框 -->
        <div class="liu-input" v-if="showLy">
            <div class="input-pre" @click="inpFocue" v-if="isShowXie">
                <img class="input-xie" src="./img/xie.png" alt="">
                <span class="input-tip">发表留言... ... </span>
            </div>
            <input type="text" v-model="txt" ref="inp" maxlength="40" @focus="inputFocue" @blur="inputBlur" class="input-txt">
            <div v-if="txt" class="send-act" @click="add(txt, true)"></div>
            <img src="./img/send_img.png" v-if="txt" class="input-send" alt="">
        </div>

        <!-- 留言板 -->
        <div class="out" v-if="showLy">
        </div>
        <div class="out-con" v-if="showLy">
            <div class="con-1">
                <div class="title">
                    <img src="./img/axly.png" class="title-left" alt="">
                    <div @click="hideLy" class="title-right">收起
                        <img class="right-jian" src="./img/jian_tou.png" alt="">
                    </div>
                </div>
                <div class="content-out">
                    <div class="content" ref="box" :class="{anim:animate==true}">
                        <div class="msg" v-for="(item, index) in arr" :key="index">
                            <div class="userInfo">
                                <div class="name" :style="{width:item.name.length*1.125 + 'rem'}">{{ item.name }}</div>
                                <div class="fd" v-if="item.fdName">{{ item.fdName ? item.fdName : '' }}</div>

                            </div>
                            <div class="li">
                                <span>{{ item.content }}</span>
                            </div>
                        </div>
                    </div>
                </div>

            </div>
        </div>

        <!-- 打开留言板按钮 -->
        <div class="jiao_biao" @click="showLyFun" v-if="!showLy">
            <img src="./img/ly_xin.png" alt="">
            <p>爱心留言</p>
        </div>
    </div>
    <script src="./js/data.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let data1 = data;
        console.log(data1);
        var app = new Vue({
            el: '#app',
            data() {
                return {
                    txt: '',
                    isShowXie: true,
                    arr: [],
                    scrollDistance: 0,
                    items: [],
                    list: [],
                    showLy: false,
                    i: 5,
                    guaqi: false,
                    animate: false
                }
            },
            watch: {
                // 监听展示的数组 根据数组变化 实现滚动
                arr: {
                    handler() {
                        console.log(this.arr.length);
                        let time;
                        if (!this.showLy) {
                            return;
                        }
                        if (this.isSend) {
                            time = 100;
                        } else {
                            time = 1500;
                        }
                        setTimeout(() => {
                            let node = document.querySelector(".content-out");
                            let node1 = document.querySelector(".content");
                            if (node) {
                                this.scrollDistance = node1.clientHeight - node.clientHeight;
                                if (this.scrollDistance > 0) {
                                    this.animate = true;
                                    node1.style.transform = 'translateY(-' + this.scrollDistance + 'px)';
                                }
                            }
                        }, time);
                    },
                },
            },
            created() {
                this.getNoteList();
            },
            mounted() {
                // 网页挂起和唤醒时的操作 挂起时暂停 唤起开始
                document.addEventListener("visibilitychange", () => {
                    if (document.hidden) { //网页被挂起
                        this.guaqi = true;
                    } else {
                        this.guaqi = false;
                        let xxx = window.setInterval(() => {
                            if (!this.showLy || this.guaqi) {
                                window.clearInterval(xxx);
                                if (this.arr.length > 10) {
                                    this.arr = this.arr.slice(this.arr.length - 5);
                                }
                                return;
                            }
                            if (this.i > this.items.length - 1) {
                                this.i = 0;
                            }
                            this.add(this.items[this.i]);
                            this.i++;
                        }, 1500);
                    }
                })
            },
            methods: {
                // 留言模块
                getSubName(name) {
                    let newName;
                    if (name) {
                        if (name.length > 3) {
                            newName = name.substring(0, 3) + '...';
                        } else {
                            newName = name;
                        }
                    } else {
                        newName = '';
                    }
                    return newName;
                },
                // 获取留言列表
                getNoteList() {
                    var _this = this;
                    let items = data1;
                    // 此处先展示五笔 与i相对应 为的是:一进留言板 留言板不空荡
                    for (let index = 0; index < 5; index++) {
                        const ele = items[index];
                        ele.name = _this.getSubName(ele.name);
                        _this.arr = [
                            ..._this.arr,
                            ele,
                        ];
                    }
                    _this.items = items;
                    setTimeout(() => {
                            _this.showLy = true;
                        }, 1000)
                        // 开始滚动
                    let xxx = window.setInterval(() => {
                        if (!_this.showLy || _this.guaqi) {
                            window.clearInterval(xxx);
                            if (_this.arr.length > 10) {
                                _this.arr = _this.arr.slice(_this.arr.length - 5);
                            }
                            return;
                        }
                        if (_this.i > _this.items.length - 1) {
                            _this.i = 0;
                        }
                        _this.add(_this.items[_this.i]);
                        _this.i++;
                    }, 1500);
                },
                // 点击输入框
                inpFocue() {
                    this.$refs.inp.focus();
                },
                // 聚焦时隐藏提示文字
                inputFocue() {
                    this.isShowXie = false;
                },
                // 失去焦点时展示提示文字
                inputBlur() {
                    if (!this.txt) {
                        this.isShowXie = true;
                    }
                },
                // 新增留言
                add(element, flag) {
                    if (!element) {
                        return;
                    }
                    this.isSend = flag;
                    if (flag) {
                        if (element.length > 40) {
                            this.showMegClickFa('内容过长哦~');
                            return;
                        }
                        this.userName = '懿小诺'
                        this.fdName = '滁州'
                        console.log(this.userName);
                        let temp = {
                            "content": element,
                            "fdName": this.fdName ? this.fdName : '',
                            "id": "",
                            "name": this.getSubName(this.userName)
                        };
                        console.log(temp);
                        this.arr = [
                            ...this.arr,
                            temp
                        ];
                        this.items = [
                            ...this.items, {
                                "content": element,
                                "fdName": this.fdName ? this.fdName : '',
                                "id": "",
                                "name": this.getSubName(this.userName)
                            },
                        ];
                        // 。。。调服务提交
                        var _this = this;
                        console.log('内容', _this.txt);
                        console.log('留言成功');
                        _this.txt = '';
                       _this.inputBlur();
                    } else {
                        this.arr = [
                            ...this.arr,
                            element
                        ];
                    }
                },
                // 收起留言板
                hideLy() {
                    this.txt = ''
                    this.showLy = false;
                },
                // 展开留言板
                showLyFun() {
                    this.showLy = true;
                    let xxx = window.setInterval(() => {
                        if (!this.showLy || this.guaqi) {
                            window.clearInterval(xxx);
                            if (this.arr.length > 10) {
                                this.arr = this.arr.slice(this.arr.length - 5);
                            }
                            return;
                        }
                        if (this.i > this.items.length - 1) {
                            this.i = 0;
                        }
                        this.add(this.items[this.i]);
                        this.i++;
                    }, 1500);
                }
            }
        })
    </script>
</body>

</html>

css文件

html {
    font-size: 16px;
}

body {
    width: 100%;
    height: 100vh;
    background-color: pink;
}

* {
    padding: 0;
    margin: 0;
}

.liu-input {
    position: fixed;
    height: 3.125rem;
    bottom: 0;
    left: 0;
    width: 100%;
    z-index: 90;
    padding: 0 1.125rem;
    box-sizing: border-box;
    align-items: center;
    display: flex;
    background-color: #fff;
}

.liuyan {
    position: relative;
    height: 3.125rem;
    padding: 0 1.125rem;
    width: 100%;
    box-sizing: border-box;
    align-items: center;
    display: flex;
    background-color: #fff;
}

.input-txt,
.input-txt-area {
    flex: 1;
    padding: 0.5625rem 0.9375rem;
    border: 0;
    background: #F2F3F4;
    border-radius: 0.9375rem;
    outline: none;
    color: #3F444D;
    font-size: 0.875rem;
}

.input-txt-area {
    resize: none;
    vertical-align: top;
    outline: none;
    line-height: 1.25rem;
}

.input-pre {
    position: absolute;
    left: 2.0625rem;
}

.input-xie {
    width: 0.75rem;
}

.input-tip {
    color: #A2A6A7;
    font-size: 0.8125rem;
}

.input-send {
    margin-left: -2.3rem;
    display: block;
    width: 1.5rem;
    height: 1.5rem;
}

.send-act {
    width: 3.125rem;
    height: 2.5rem;
}


/* 角标 */

@keyframes sca {
    0% {
        transform: scale(0.8);
    }
    100% {
        transform: scale(1.2);
    }
}

.jiao_biao {
    position: fixed;
    left: 1rem;
    bottom: 6rem;
    /* bottom: 1.625rem; */
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    background-color: #FFCC00;
    padding-top: 0.5rem;
    box-sizing: border-box;
    text-align: center;
    z-index: 80;
    animation: sca 1s ease infinite forwards;
}

.jiao_biao img {
    width: 1.4375rem;
}

.jiao_biao p {
    color: #fff;
    font-size: 0.75rem;
}


/* 留言板 */

.out {
    position: fixed;
    left: 1.125rem;
    width: 80%;
    height: 430px;
    background-color: #000;
    opacity: 0.6;
    bottom: 4.25rem;
    z-index: 80;
    border-radius: 0.625rem;
    overflow: hidden;
}

.title {
    width: 100%;
    padding-left: 1.0625rem;
    padding-right: 1.0625rem;
    display: flex;
    height: 50px;
    font-size: 0.875rem;
    align-items: center;
}

.title-left {
    width: 4.8125rem;
}

.title-right {
    color: #fff;
    flex: 1;
    text-align: end;
}

.right-jian {
    width: 0.75rem;
    vertical-align: baseline;
}

.content {
    /* width: 96%; */
    width: 100%;
    /* height: 360px; */
    font-size: 0.875rem;
    transition: all 1s;
}

.content-out {
    width: 96%;
    height: 360px;
    padding-left: 0.9375rem;
    overflow: hidden;
}

.userInfo {
    display: flex;
    height: 30px;
    align-items: center;
    color: #ffffff;
}

.name {
    font-size: 1.125rem;
    max-width: 4.5rem;
}

.fd {
    max-width: calc(100% - 75px);
    margin-left: 0.25rem;
    padding: 0.0625rem 0.75rem;
    background-color: #9fa6ac;
    font-size: 0.75rem;
    border-radius: 0.875rem;
    margin-top: 0.125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.li {
    padding: 0.3125rem 0.625rem;
    margin-bottom: 0.75rem;
    background: #ffffff;
    border-radius: 0px 0.6875rem 0.6875rem 0.6875rem;
}

.out-con {
    position: fixed;
    left: 1.125rem;
    width: 80%;
    height: 430px;
    bottom: 4.25rem;
    z-index: 81;
}

.con-1 {
    position: relative;
    width: 90%;
    height: 430px;
}

.msg {
    position: relative;
    opacity: 0;
    animation: scro 0.5s 0.2s ease forwards;
}

@keyframes scro {
    100% {
        opacity: 1;
    }
}

.anim {
    position: relative;
    transition: all 0.5s;
}

自造的假数据

let data = [{
    "content": "1",
    "fdName": "霸都合肥友爱啊",
    "id": "395",
    "mrkMonth": "",
    "name": "尚云飞",
    "userId": ""
}, {
    "content": "2",
    "fdName": "南京啊",
    "id": "393",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "3",
    "fdName": "南京啊",
    "id": "392",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "4",
    "fdName": "南京啊",
    "id": "391",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "5",
    "fdName": "南京啊",
    "id": "390",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "6",
    "fdName": "南京啊",
    "id": "389",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "7",
    "fdName": "南京啊",
    "id": "388",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "😄😄😄",
    "fdName": "合肥啊",
    "id": "387",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "9",
    "fdName": "合肥啊",
    "id": "386",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "10",
    "fdName": "合肥啊",
    "id": "385",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "11",
    "fdName": "南京啊",
    "id": "384",
    "mrkMonth": "",
    "name": "梦梦子",
    "userId": ""
}, {
    "content": "12",
    "fdName": "南京啊",
    "id": "383",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "13",
    "fdName": "南京啊",
    "id": "382",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "14",
    "fdName": "南京啊",
    "id": "381",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "15",
    "fdName": "南京啊",
    "id": "380",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "合肥合肥好",
    "fdName": "南京啊",
    "id": "379",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "17",
    "fdName": "南京啊",
    "id": "378",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "18",
    "fdName": "南京啊",
    "id": "377",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "19",
    "fdName": "南京啊",
    "id": "376",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "继续进行",
    "fdName": "南京啊",
    "id": "375",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "21",
    "fdName": "南京啊",
    "id": "374",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "22",
    "fdName": "南京啊",
    "id": "373",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "23",
    "fdName": "南京啊",
    "id": "372",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "24",
    "fdName": "南京啊",
    "id": "371",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "25",
    "fdName": "南京啊",
    "id": "370",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "26",
    "fdName": "南京啊",
    "id": "369",
    "mrkMonth": "",
    "name": "小梦子",
    "userId": ""
}, {
    "content": "27",
    "fdName": "合肥啊",
    "id": "368",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "28",
    "fdName": "合肥啊",
    "id": "367",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "9",
    "fdName": "合肥啊",
    "id": "366",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "30",
    "fdName": "合肥啊",
    "id": "365",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "7",
    "fdName": "合肥啊",
    "id": "364",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "6",
    "fdName": "合肥啊",
    "id": "363",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "5",
    "fdName": "合肥啊",
    "id": "362",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "4",
    "fdName": "合肥啊",
    "id": "360",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "3",
    "fdName": "合肥啊",
    "id": "359",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "2",
    "fdName": "合肥啊",
    "id": "358",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}, {
    "content": "1",
    "fdName": "合肥啊",
    "id": "357",
    "mrkMonth": "",
    "name": "孟是琬",
    "userId": ""
}]

有不懂的可以问哦 一起学习~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容