动手吧,vue移动端消息滚动组件

news2024/12/27 16:42:36

先看效果图:

1、模板部分

<transition name="fade-sport">
        <div class="v-message-roll" v-show="visible">
            <svg class="v-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7405">
                <path
                    d="M594.917478 144.398738c0-43.803645-37.123502-79.478146-82.916455-79.478146-45.699832 0-82.918501 35.585473-82.918501 79.478146 0 4.472871 0.38681 8.860808 1.12973 13.133112-114.497731 38.254256-208.430076 155.73083-208.430076 294.718325l0 109.423155c0 0 0 157.590178-40.387849 158.963455-24.082488 0-42.528606 17.792225-42.528606 39.74112 0 22.098297 18.557658 39.737026 41.452087 39.737026l663.36643 0c23.004947 0 41.451064-17.791202 41.451064-39.737026 0-22.103414-18.557658-39.74112-41.451064-39.74112-41.46539 0-41.46539-157.854191-41.46539-157.854191L802.218848 452.263477c0-139.166573-87.828324-256.691243-208.408587-294.828842C594.538855 153.190985 594.917478 148.838863 594.917478 144.398738zM636.377752 839.789535c-0.12382 65.903989-55.286164 119.28885-124.377752 119.28885-68.616774 0-124.254955-53.163827-124.378775-119.28885L636.377752 839.789535z"
                    fill="#f9a60a"
                    p-id="7406"
                ></path>
            </svg>
            <div class="v-content">
                <ul class="v-content-list" ref="listRef" @touchstart="touchstart" @touchend="touchend">
                    <li class="v-content-item" ref="itemsRef" v-for="(item, index) in contentComputed" :key="index">
                        {{ item }}
                    </li>
                </ul>
            </div>
            <svg
                v-if="showCloseIcon"
                @click="close"
                class="v-icon"
                viewBox="0 0 1024 1024"
                version="1.1"
                xmlns="http://www.w3.org/2000/svg"
                p-id="8743"
            >
                <path
                    d="M576 512l277.333333 277.333333-64 64-277.333333-277.333333L234.666667 853.333333 170.666667 789.333333l277.333333-277.333333L170.666667 234.666667 234.666667 170.666667l277.333333 277.333333L789.333333 170.666667 853.333333 234.666667 576 512z"
                    fill="#f9a60a"
                    p-id="8744"
                ></path>
            </svg>
        </div>
    </transition>

2、css部分

.v-message-roll {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: opacity 0.2s;
    .v-icon {
        width: 20px;
        height: 20px;
        flex-shrink: 0;
        vertical-align: middle;
        fill: currentColor;
        overflow: hidden;
    }
    .v-content {
        flex: 1;
        width: 0;
        .v-content-list {
            width: 100%;
            overflow-x: auto;
            white-space: nowrap;
            &::-webkit-scrollbar {
                display: none;
            }
            .v-content-item {
                display: inline-block;
                color: #db8412;
            }
        }
    }
}

.fade-sport-enter,
.fade-sport-leave {
    opacity: 0;
}

3、js部分

const SPEED = {
    FAST: 0.6,
    MIDDLE: 0.4,
    SLOW: 0.3,
};
export default {
    data() {
        return {
            visible: true,
            animationFrameTimer: null,
            touchTimeout: null,
            refreshRateTimer: null,
        };
    },

    props: {
        content: [String, Array],
        touchStop: {
            type: Boolean,
            default: false,
        },
        touchStopDuration: {
            type: Number,
            default: 1500,
        },
        showCloseIcon: {
            type: Boolean,
            default: true,
        },
    },

    watch: {
        content: {
            handler() {
                this.reset();
                this.$nextTick(() => {
                    this.init();
                });
            },
            deep: true,
        },
    },

    computed: {
        contentComputed() {
            if (Object.prototype.toString.call(this.content) === "[object Array]") {
                return this.content;
            }
            return [this.content];
        },
    },

    mounted() {
        this.calcScreenRefreshRate().then((rate) => {
            this.screenRefreshRate = rate;
            this.init();
        });
    },

    methods: {
        init() {
            const itemsRef = this.$refs.itemsRef;
            const scrollW = this.$refs.listRef.scrollWidth;
            this.scrollW = scrollW;
            if (itemsRef.length) {
                this.itemsRef = this.$refs.itemsRef;
                this.setInterval();
            }
        },

        reset() {
            this.$refs.listRef.scrollLeft = 0;
            this.cancelAnimationFrame();
        },

        calcScreenRefreshRate() {
            return new Promise((resolve) => {
                let screenRefreshRate = 0;
                const animationFrameFunc = () => {
                    screenRefreshRate += 2;
                    this.refreshRateTimer = window.requestAnimationFrame(animationFrameFunc);
                };
                setTimeout(() => {
                    window.cancelAnimationFrame(animationFrameFunc);
                    resolve(screenRefreshRate);
                }, 500);
                animationFrameFunc();
            });
        },

        setInterval(num) {
            this.animationFrameTimer = window.requestAnimationFrame(() => this.roll(num));
        },

        roll(num = 0) {
            const step = this.calcStep();
            this.itemsRef.forEach((ele) => {
                ele.style.transform = `translateX(-${num}px)`;
            });
            this.animationFrameTimer = window.requestAnimationFrame(() =>
                this.roll(num < this.scrollW ? num + step : 0)
            );
        },

        calcStep() {
            const screenRefreshRate = this.screenRefreshRate;
            let step = 0;
            if (screenRefreshRate < 90) {
                step = SPEED["FAST"];
            } else if (screenRefreshRate < 120) {
                step = SPEED["MIDDLE"];
            } else {
                step = SPEED["SLOW"];
            }
            return step;
        },

        touchstart() {
            if (!this.touchStop) {
                this.$refs.listRef.style.overflow = "hidden";
            } else {
                this.itemsRef.forEach((ele) => {
                    ele.style.transform = `translateX(0)`;
                });
                this.cancelAnimationFrame();
                window.clearTimeout(this.touchTimeout);
            }
        },

        touchend() {
            if (this.touchStop) {
                const scrollLeft = this.$refs.listRef.scrollLeft;
                this.touchTimeout = setTimeout(() => {
                    this.$refs.listRef.scrollLeft = 0;
                    this.setInterval(scrollLeft);
                }, this.touchStopDuration);
            }
        },

        close() {
            this.visible = false;
            this.$emit("close");
            this.cancelAnimationFrame();
        },

        cancelAnimationFrame() {
            window.cancelAnimationFrame(this.animationFrameTimer);
            window.cancelAnimationFrame(this.refreshRateTimer);
        },
    },

    deactivated() {
        this.cancelAnimationFrame();
    },

    beforeDestroy() {
        this.cancelAnimationFrame();
    },
};

4、参数和事件

可以的话,点个赞嘛

## 属性
 
content: 内容。参数类型:string|array
 
touchStop: 触摸是否停止滚动。参数类型:boolean, 默认 false

touchStopDuration: 触摸停止滚动持续时长(ms)。参数类型:number, 默认1500

showCloseIcon:是否显示关闭按钮。参数类型:boolean, 默认 true
 
## 事件
 
close:关闭事件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/851798.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows环境下通过 系统定时 执行脚本方式 压缩并备份文件夹 到其他数据盘

环境配置 压缩时需要使用7-zip进行调用&#xff0c;因此根据自己电脑进行安装 官网&#xff1a;https://www.7-zip.org/ 脚本文件 新建记事本文件&#xff0c;重命名为git_back_up.bat echo off rem 设置utf-8可以正常显示中文 chcp 65001 > nulrem 获取当前日期和时间&…

树和二叉树基础概念

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大家三连关注&…

Webpack 的 sass-loader 在生产模式下最小化 CSS 问题

学习webpack时候我发现一个问题&#xff1a; 将mode 改为production模式后&#xff0c;生成的css会被压缩了&#xff0c;但是我并没有引入CssMinimizerPlugin插件&#xff0c;然后我试着将optimization.minimize 设置为false&#xff0c;测试是否为webpack自带的压缩&#xff0…

微星笔记本:为京津冀、黑吉辽受灾用户提供一系列维修服务

面对近期集中在华北、东北等地出现的极端降水&#xff0c;引发洪涝和地质灾害。全国人民都众志成城、万众一心&#xff0c;在各个环节上贡献自己一份力量。台风无情、微星有爱&#xff0c;为保障您的电脑正常使用&#xff0c;京津冀、黑吉辽全区域微星线下服务中心及微星上门服…

day0808

1.单链表实现约瑟夫环 #include "joseph.h" LoopLink list_create(int m) {LoopLink L (LoopLink)malloc(sizeof(Node));if(NULLL){printf("内存创建失败\n");return 0;}LoopLink qL;for(int i1; i<m; i){LoopLink p (LoopLink)malloc(sizeof(Node));…

年轻代频繁GC ParNew导致http变慢

背景介绍 某日下午大约四点多&#xff0c;接到合作方消息&#xff0c;线上环境&#xff0c;我这边维护的某http服务突然大量超时&#xff08;对方超时时间设置为300ms&#xff09;&#xff0c;我迅速到鹰眼平台开启采样&#xff0c;发现该服务平均QPS到了120左右&#xff0c;平…

管理类联考——逻辑——论证逻辑——汇总篇——真题和典例——削弱

削弱 199-2014-10-41——割裂关系 卫计委的报告表明&#xff0c;这些年来医疗保健费的确是增加了。可见&#xff0c;我们每个人享受到的医疗条件大大改善了。 以下哪项对上述结论提出最严重的质疑? A.医疗保健费的绝大部分用在了对高危病人的高技术强化护理上。 B.在不增加费…

容器——4. Map 接口

文章目录 4.1. HashMap 和 Hashtable 的区别4.2. HashMap 和 HashSet 区别4.3. HashMap 和 TreeMap 区别4.4. HashSet 如何检查重复4.5. HashMap 的底层实现4.5.1. JDK1.8 之前4.5.2. JDK1.8 之后 4.6. HashMap 的长度为什么是 2 的幂次方4.7. HashMap 多线程操作导致死循环问题…

STL模型修复权威指南【3D打印】

设计师和工程师通常需要软件来调整、修复和最终确定 3D 打印的 3D 模型。 幸运的是&#xff0c;手动网格编程的时代早已一去不复返了。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 如今&#xff0c;有一系列专用工具可提供自动和手动 STL 修复功能。 自动向导足以满…

zju代码题:4-6

一 分段函数算水费 #include <stdio.h>int main() {/*** 定义两个* 定义浮点型变量* y:水费* x:用水的吨数* */double x, y;printf("Enter x(x>=0):\n"

侯捷 C++ part2 兼谈对象模型笔记——2-xxx-like-classes

2 xxx-like classes 2.1 pointer-like classes 2.1.1 智能指针 设计得像指针class&#xff0c;能有更多的功能&#xff0c;包着一个普通指针指针允许的动作&#xff0c;这个类也要有&#xff0c;其中 *&#xff0c;-> 一般都要重载 template <typename T> class s…

工作中学到三个CSS伪类,直接少些几百行CSS代码~

前言 用最通俗易懂的话讲最难的知识点是我的座右铭&#xff0c;基础是进阶的前提是我的初心。分享一篇好文~ :where 基本使用 :where() CSS 伪类函数接受选择器列表作为它的参数&#xff0c;将会选择所有能被该选择器列表中任何一条规则选中的元素。 以下代码&#xff0c;文…

基于java SpringBoot和Vue零食销售网站设计

随着时代的发展&#xff0c;传统的超市购物方式已经不能满足人们的需求&#xff0c;对于顾客来说&#xff0c;排队购物和支付购物费用的问题亟待解决。对于实体超市来说&#xff0c;他们面临着网上购物的竞争压力&#xff0c;作为超市经理&#xff0c;他们要降低成本&#xff0…

全栈测试平台推荐:RunnerGo

做软件测试的同学在工作时应该都碰到过这种情况&#xff1a;接口管理、接口测试用postman、Apipost等接口管理工具&#xff0c;性能测试用jmeter、loadrunner等性能测试工具&#xff0c;接口自动化则是jmeter脚本或者python脚本配合jenkins使用。这种情况极大的降低了研发效率&…

聚观早报|网信办就人脸识别征求意见;地平线前总监入职比亚迪

【聚观365】8月9日消息 网信办就人脸识别应用征求意见地平线前总监廖杰入职比亚迪理想汽车预计三季度车辆交付量星纪魅族回应终止自研芯片业务上汽集团7月销量同比下滑21% 网信办就人脸识别应用征求意见 据网信中国微信公众号消息&#xff0c;为规范人脸识别技术应用&#xf…

自定义类型——联合

联合 1.联合体的定义 联合也是一种特殊的自定义类型。 先来看一个结构体变量&#xff1a; #include<stdio.h> #include<stdlib.h> union Un {char c;int i; }; int main() {union Un un;printf("%p\n", &un);printf("%p\n", &un.c)…

ad+硬件每日学习十个知识点(26)23.8.6 (DCDC的降压电路、升压电路、降压-升压电路,同步整流,选型考虑同步、隔离)

文章目录 1.DCDC的降压原理2.DCDC的升压原理3.DCDC的升压和降压原理4.什么是肖特基二极管造成的死区电压&#xff1f;5.MOS管有死区电压么&#xff1f;6.DCDC的同步整流&#xff08;用MOS管取代整流二极管&#xff0c;避免死区电压的影响&#xff09;7.DCDC选型——同步与非同步…

怎样学习PMP呢?

大多数人会觉得自己是工作者如果花时间去学习PMP精力上和时间上不好安排&#xff0c;其实上班族也是能学号pmp项目管理的。 首先&#xff0c;我把总结和思维导图打印出来&#xff0c;贴在镜子上&#xff0c;每天早上起来刷牙时&#xff0c;就可以过一遍这些内容。上班路上&…

《golang设计模式》第二部分·结构型模式-01-适配器模式(Adapter)

文章目录 1. 概念1.1 角色1.2 应用场景1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 示例类图 1. 概念 定义一个适配器&#xff0c;帮助原本不能实现接口的类“实现”该接口 1.1 角色 目标&#xff08;Target&#xff09;&#xff1a;客户端调用的目标接口 被适配者&#xff08…

Vue3中v-model在原生元素和自定义组件上的使用

目录 前言 一、原生元素上的用法 1. 输入框(input) 2. 多行文本域(textarea) 3. 单选按钮(radio) 4. 多选框(checkbox) 5. 下拉选择框(select) 二、自定义组件上的用法 1. 定义一个名为 modelValue 的 props 属性和一个名为 update:modelValue 的事件 2.使用一个可…