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

先看效果图:

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:关闭事件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

上传图片视频

分布式文件系统MinIo MinIO提供多个语言版本SDK的支持&#xff0c;下边找到java版本的文档&#xff1a; 地址&#xff1a;https://docs.min.io/docs/java-client-quickstart-guide.html MinIO测试&#xff08;上传、删除、下载&#xff09; public class MinioTest {MinioC…

【数据结构刷题】数组oj

前言:本文章是关于在力扣上面的数组相关面试题的讲解&#xff0c;包括:1.原地移除数组中所有的元素val&#xff0c;要求时间复杂度为O(N)&#xff0c;空间复杂度为O(1),2.删除排序数组中的重复项。3. 合并两个有序数组。一.原地移除数组中所有的元素val 题目: https://leetcod…

狂码三万字 | 三维场景点云理解与重建技术

目录 00 引言 01 点云特征提取与匹配 1.1 传统点云特征提取 1.2 点云深度学习 1.3 点云卷积 1.4 稀疏卷积 1.5 点云Transformer 1.6 点云旋转不变特征提取 1.7 点云匹配 02 场景点云语义分割 2.1 场景表征与数据集 2.1.1 室内场景表征与相关数据集 2.1.2 室外场…

电脑IP地址错误无法上网怎么办?

电脑出现IP地址错误后就将无法连接网络&#xff0c;从而无法正常访问互联网。那么当电脑出现IP地址错误时该怎么办呢&#xff1f; 确认是否禁用本地连接 你需要先确定是否禁用了本地网络连接&#xff0c;如果发现禁用&#xff0c;则将其启用即可。 启用方法&#xff1a;点击桌…

pytest-xdist分布式测试原理浅析

目录 pytest-xdist执行流程&#xff1a; pytest-xdist 模块结构&#xff1a; pytest-xdist分布式测试原理&#xff1a; pytest-xdist源码浅读&#xff1a; pytest-xdist执行流程&#xff1a; 解析命令行参数&#xff1a;pytest-xdist 会解析命令行参数&#xff0c;获取用户…

DROP USER c##xyt CASCADE > ORA-01940: 无法删除当前连接的用户

多创建了一个用户&#xff0c;想要给它删除掉 一 上执行过程&#xff0c;确实删除成功了 Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing optionsSQL> DR…

CVPR 2023 | Attention-Based Point Cloud Edge Sampling

注1:本文系“计算机视觉/三维重建论文速递”系列之一,致力于简洁清晰完整地介绍、解读计算机视觉,特别是三维重建领域最新的顶会/顶刊论文(包括但不限于 CVPR, ICCV, ECCV, NeurIPS等)。本次介绍的论文是: CVPR 2023 | Attention-Based Point Cloud Edge Sampling CVPR 2023 | …

【c语言】-- 结构体

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章来学习结构体。 让我们开启c语言学习之…

CTF流量题解http4.pcapng

流量分析 导出http 打开报错 验证文件头&#xff0c;发现是zip。 图常片见里文可件能的包16含进:压制缩头包部,word,pdf JPG FF D8 FF E0/FF D8 FF E1 PNG 89 50 4E 47 GIF 47 49 46 38 ZIP 50 4B 03 04 RAR 52 61 72 21 MP3 49 44 33 0 改后缀 使用工具爆破。 git clone git…

WordPress使用【前端投稿】功能时为用户怎么添加插入文章标签

在使用Wordpress做前端投稿功能的时候&#xff0c;可能需要用户填写文章标签&#xff0c;在插入文章的时候很多人不知道怎么把这些标签插入进去&#xff0c;下面这篇文章来为大家带来WordPress使用前端投稿功能时插入文章标签方法。 在Wordpress里 wp_insert_post 此函数的作…

docker菜谱大全

记录docker常用软件安装&#xff0c;感谢小马哥和杨师傅的投稿。&#x1f60e;&#x1f60e;&#x1f60e; 相关文档&#xff1a; DockerHub&#xff1a;https://hub.docker.com/Linux手册&#xff1a;https://linuxcool.com/Docker文档&#xff1a;https://docs.docker.com/Do…

探索Python异常世界:玩转异常、模块与包

文章目录 一 异常概念二 异常的捕获方法2.1 捕获异常的原因2.2 捕获常规异常2.3 捕获指定异常2.4 捕获多个异常2.5 捕获异常并输入异常信息2.6 捕获所有异常2.7 异常else2.8 异常finally 三 异常的传递四 python模块4.1 模块的导入方式4.2 自定义模块4.3 测试模块4.4 注意事项4…

金蝶云星空与旺店通WMS对接集成盘盈单查询连通商品同步接口(盘盈单=>其他入库单)

金蝶云星空与旺店通WMS对接集成盘盈单查询连通商品同步接口(盘盈单>其他入库单) 来源系统:金蝶云星空 金蝶K/3Cloud结合当今先进管理理论和数十万家国内客户最佳应用实践&#xff0c;面向事业部制、多地点、多工厂等运营协同与管控型企业及集团公司&#xff0c;提供一个通用…

python爬虫相关

目录 初识爬虫 爬虫分类 网络爬虫原理 爬虫基本工作流程 搜索引擎获取新网站的url robots.txt HTHP协议 Resquests模块 前言&#xff1a; 安装 普通请求 会话请求 response的常用方法 简单案例 aiohttp模块 使用前安装模块 具体案例 数据解析 re解析 bs4…

第2章:模型评估与选择

经验误差与泛化误差 过拟合是核心问题。 过拟合是无法避免的&#xff0c;只能尽量去缓解。 每个算法都要思考&#xff0c;是怎么缓解过拟合的&#xff1f;缓解方法什么情况下会失效&#xff1f; 模型选择 评估方法 留出法 为什么不能太小&#xff1f; 因为Mx要用来逼近M100的结…

深入理解PyTorch中的NoamOpt优化器

深入理解PyTorch中的NoamOpt优化器 作者&#xff1a;安静到无声 个人主页 今天&#xff0c;我们将深入探讨一个在自然语言处理领域广泛使用的优化器——NoamOpt。这个优化器是基于PyTorch实现的&#xff0c;并且在"Attention is All You Need"这篇论文中首次提出。…

JedisDataException DENIED Redis is running in protected mode...异常的解决办法

一. 异常现象 壹哥最近在带学生做项目的过程中&#xff0c;有学生在使用Redis的时候&#xff0c;产生了如下这样的异常信息&#xff1a; com.yyg.demo.Demo01Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: DENIED Redis is runni…

Vue项目npm run dev 启动报错TypeError: Cannot read property ‘upgrade‘ of undefined

vue项目启动报错 TypeError: Cannot read property upgrade of undefined 由于我的vue.config.js文件 里面的代理target为空导致的 修改&#xff1a; 结果就可以正常运行了 参考原文&#xff1a; vue项目运行时报Cannot read property ‘upgrade’ of undefined错误_cannot r…

Springboot中拦截GET请求获取请求参数验证合法性

目录 目的 核心方法 完整代码 创建拦截器 注册拦截器 测试效果 目的 在Springboot中创建拦截器拦截所有GET类型请求&#xff0c;获取请求参数验证内容合法性防止SQL注入&#xff08;该方法仅适用拦截GET类型请求&#xff0c;POST类型请求参数是在body中&#xff0c;所以下面…

git教程(第一次使用)

一、gitee和github区别 二、git使用 下载地址 windows&#xff1a;https://gitforwindows.org/ mac&#xff1a;http://sourceforge.net/projects/git-osx-installer/ 1.git初次运行前的配置 &#xff08;1&#xff09;配置用户信息 git config --global user.name "…