Vue2时间轴组件(TimeLine/分页、自动顺序播放、暂停、换肤功能、时间选择,鼠标快速滑动)

目录

1介绍背景

2实现原理

3组件介绍

4代码

5其他说明


1介绍背景

项目背景是  一天的时间轴  10分钟为一间隔 一天被划分成144个节点  一页面12个节点 代码介绍的很详细 可参考或者借鉴

2实现原理

对Element-plus滑块组件的二次封装
基于Vue2(2.6.14),对element-plus(2.15.13)中slider滑块组件的二次封装。其中,用到了element-plus中的部分icon图标。

组件主要是对时间节点进行分页、顺序播放、暂停、换肤功能、时间选择,点击事件,上一页下一页,父组件监听到当前时间的改变,从而触发相应的业务逻辑。

3组件介绍

light天亮模式

dark黑夜模式

4代码

<template><div class="TimeLineBox"><h3>时间轴 {{ timeYMD }} {{ timeSFM }} </h3><div class="TimeLineBox_content"><div class="block custom-block"><!-- <span class="demonstration">默认</span> --><el-date-picker v-model="dayDate" type="date" placeholder="选择日期" size="small" @change="handleDatePickerChange"style="width: 150px;" :editable="false"></el-date-picker></div><TimeLine  :second="1000" :timeYMD="timeYMD" :timeSet="timeSet"@handleNowValueChange="handleNowValueChange"></TimeLine></div></div>
</template>
<script>
//--start-#引入时间轴组件#-->
import TimeLine from "./../components/TimeLine.vue";
//--start-#引入第三方关于时间的文件#-->
import moment from 'moment';
export default {components: {TimeLine},data() {return {//--start-#用于时间轴显示的初始化时间时分秒#-->timeSFM: "00:10:00",//--start-#时间集合#-->timeSet: [],//--start-#用于时间轴显示的初始化时间年月日#-->timeYMD: "",// //--start-#拼接时间组合 具体就是年月日时分秒#-->// timeCombination: nulldayDate: '',}},mounted() {this.computerTimeSet();},computed: {},methods: {handleDatePickerChange() {//--start-#获取时间选择器的年月日#-->//console.log("@@", this.dayDate);if (this.dayDate) {//--start-#非空执行#-->this.handleTimeSetNode(moment(this.dayDate).format('YYYY-MM-DD'))}},//--start-#计算时间轴中需要的时间节点集合方法#-->computerTimeSet() {//--start-#获取当天的年月日0时0分0秒#-->let startOfDay = moment().startOf('day');//--start-#获取当天的前一天年月日0时0分0秒#-->let previousDate = startOfDay.subtract(1, 'days');this.handleTimeSetNode(previousDate)},handleTimeSetNode(timeNode) {//--start-#获取当天的前一天年月日用于计算时间节点#-->let oneTimeNode = new Date(timeNode);//--start-#获取当天的前一天年月日  用于时间轴标题显示#-->this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD HH:mm:ss');this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');//--start-#遍历计算获取当天10分钟一次的时间节点组合#-->for (let i = 0; i < 144; i++) {//--start-#获取时间 并设置分钟位加10,意思是加10分钟#-->oneTimeNode.setMinutes(oneTimeNode.getMinutes() + 10);//this.timeSet.push(moment(oneTimeNode).format('YYYY-MM-DD HH:mm:ss'));//--start-#获取时间节点并加入到时间节点集合中#-->this.timeSet.push(moment(oneTimeNode).format('HH:mm:ss'));}},//--start-#父子函数回调,接收时间值的改变并响应#-->handleNowValueChange(val, val2) {if (val === "nextDay") {let oneTimeNode = new Date(this.timeYMD);oneTimeNode.setDate(oneTimeNode.getDate() + 1);this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');this.timeSFM = val2;}else if (val === "preDay") {let oneTimeNode = new Date(this.timeYMD);oneTimeNode.setDate(oneTimeNode.getDate() - 1);this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');this.timeSFM = val2;}else if (val === "nextDayAndZero") {let oneTimeNode = new Date(this.timeYMD);oneTimeNode.setDate(oneTimeNode.getDate() + 1);this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');this.timeSFM = val2;}else if (val === "preDayAndZero") {let oneTimeNode = new Date(this.timeYMD);oneTimeNode.setDate(oneTimeNode.getDate() - 1);this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');this.timeSFM = val2;}else {this.timeYMD = val;this.timeSFM = val2;}console.log(val, val2);}},
// watch:{
//   light(newVal,oldVal){
//     console.log(newVal,oldVal);
//   }
// }
}
</script>
<style lang="less" scoped>
.TimeLineBox {width: 100%;height: 100%;//background-image: url("./../assets/images/播放.png");background-size: 100% 100%;background-color: aqua;position: relative;h3 {color: rgb(241, 19, 19);position: absolute;bottom: 150px;left: 50%;transform: translate(-50%, 0);}.TimeLineBox_content {position: absolute;bottom: 50px;left: 50%;transform: translate(-50%, 0);width: 1000px;// width: 80%;height: 90px;.custom-block {position: absolute;left: 20px;top: 5px;z-index: 10;//background-color: rgb(233, 11, 11);::v-deep .el-input__inner {background-color: rgba(255, 255, 255, 0.0);border: none;}}}
}
</style>
<template><div :class="bgcolor == 'light' ? 'TimeLine2-light' : 'TimeLine2-dark'"><div class="LeftBox"><el-slider v-model="value" :step="1" show-stops :show-tooltip="false" :min="minValue" :max="maxValue":marks="marks" @change="handleTimeLineChange" v-if="timeSet.length" /></div><div class="RightBox"><el-tooltip class="box-item" effect="light" content="上一页" placement="top"><el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" @click.native="handlePrePage"class="el-icon-d-arrow-left  icon-size"></el-icon></el-tooltip><el-tooltip class="box-item" effect="light" content="播放/暂停" placement="top"><el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" v-if="playSwitch"class="el-icon-video-pause icon-size" @click.native="handlePlay"></el-icon><el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" v-if="!playSwitch"class="el-icon-video-play icon-size" @click.native="handlePlay"></el-icon></el-tooltip><el-tooltip class="box-item" effect="light" content="下一页" placement="top"><el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" @click.native="handleNextPage"class="el-icon-d-arrow-right  icon-size"></el-icon></el-tooltip></div><div class="skin-control"><el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" @click.native="skinControlSwitch"class="el-icon-s-opportunity" :class="bgcolor == 'light' ? 'skin-control-light' : 'skin-control-dark'"></el-icon></div></div></template>
<script>export default {data() {return {//--start-#定义时间定时器指引#-->timer: null,//--start-#时间轴页面容量#-->pageSize: 12,//--start-#时间轴页面数#-->pageCode: 1,//--start-#时间轴初始化显示的位置(0-11)#-->value: 0,//--start-#时间轴最小值#-->minValue: 0,//--start-#时间轴最大值#-->maxValue: 0,//--start-#遮罩,element公司提供的技术接口#-->marks: {},//--start-#播放按键转换#-->playSwitch: false,//--start-#时间集合12节点为一组#-->time12ArrNode: [],zeroTimeNode: undefined,startZero: true,bgcolor: "light"}},props: {//--start-#父组件时间轴展示标题#-->timeYMD: {type: String,default: '',},//--start-#时间节点集合#-->timeSet: {type: Array,default: [],},//--start-#播放时的时间间隔#-->second: {type: Number,default: 1000,},},mounted() { },computed: {},methods: {//--start-#处理皮肤空间切换#-->skinControlSwitch() {if (this.bgcolor === "dark")this.bgcolor = "light"else if (this.bgcolor === "light")this.bgcolor = "dark"},//--start-#处理时间轴点击事件#-->handleTimeLineChange(val) {if (this.time12ArrNode[val] === "00:00:00") {this.zeroTimeNode = "00:00:00";this.$emit("handleNowValueChange", "nextDayAndZero", "00:00:00");}else {if (this.zeroTimeNode === "00:00:00") {this.zeroTimeNode = undefined;this.$emit("handleNowValueChange", "preDayAndZero", this.time12ArrNode[val]);}else {this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[val]);}}},//--start-#处理播放是与否#-->handlePlay() {this.playSwitch = !this.playSwitch;},computeTime12ArrNode() {this.time12ArrNode = Array.from(this.timeSet).slice((this.pageCode - 1) * this.pageSize,this.pageCode * this.pageSize);},//--start-#处理上一页#-->handlePrePage() {//console.log(this.zeroTimeNode);this.startZero = false;if (this.pageCode === 1) {this.pageCode = Math.ceil(this.timeSet.length / this.pageSize)this.value = 0;this.computeTime12ArrNode();this.$emit("handleNowValueChange", "preDay", "22:10:00");}else if (this.pageCode > 1 && !this.zeroTimeNode) {this.pageCode--;this.value = 0;this.computeTime12ArrNode();this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[0]);if (this.time12ArrNode[0] == "00:10:00") {this.startZero = true;}}else if (this.pageCode === Math.ceil(this.timeSet.length / this.pageSize) && this.zeroTimeNode === "00:00:00") {// this.zeroTimeNode = undefined;this.pageCode--;this.value = 0;this.computeTime12ArrNode();this.$emit("handleNowValueChange", "preDay", "20:10:00");}this.zeroTimeNode = undefined;// console.log("@@", this.zeroTimeNode);},//--start-#处理下一页#-->handleNextPage() {this.startZero = false;//console.log(this.zeroTimeNode);if (this.pageCode === Math.ceil(this.timeSet.length / this.pageSize) && this.zeroTimeNode === "00:00:00") {this.pageCode = 1;this.value = 0;this.computeTime12ArrNode();this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[0]);this.startZero = true;}else if (this.pageCode === Math.ceil(this.timeSet.length / this.pageSize)) {this.pageCode = 1;this.value = 0;this.computeTime12ArrNode();this.$emit("handleNowValueChange", "nextDay", "00:10:00");}else if (this.pageCode < Math.ceil(this.timeSet.length / this.pageSize)) {this.pageCode++;this.value = 0;this.computeTime12ArrNode();this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[0]);}this.zeroTimeNode === undefined;},handlePalyNextPage() {this.pageCode++;this.value = 0;this.computeTime12ArrNode();this.zeroTimeNode = undefined;}},//--start-#监视时间轴#-->watch: {timeYMD(newVal, oldVal) {if (this.playSwitch)this.playSwitch = !this.playSwitch;},timeSet(newVal, oldVal) {this.time12ArrNode = Array.from(newVal).slice((this.pageCode - 1) * this.pageSize,this.pageCode * this.pageSize);},time12ArrNode(newVal, oldVal) {let obj = {};this.time12ArrNode.forEach((item, index) => {obj[index * 1] = item;});this.marks = obj;this.maxValue = this.time12ArrNode.length - 1;},//--start-#深度监视#-->deep: true,playSwitch(newVal, oldVal) {if (newVal) {this.timer = setInterval(() => {if (this.value < this.maxValue) {//--start-#判断是不是一天的第一个节点,即00:10:00#-->if (this.value === 0 && this.startZero) {this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[Math.floor(this.value)]);this.startZero = false;}else {this.value++;//--start-#判断是不是一天的最后一个节点,即00:00:00#-->if (this.time12ArrNode[Math.floor(this.value)] === "00:00:00") {this.$emit("handleNowValueChange", "nextDayAndZero", "00:00:00");this.zeroTimeNode = "00:00:00";this.playSwitch = !this.playSwitch;}//--start-#正常范围内增长值#-->else {this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[Math.floor(this.value)]);}}}//--start-#判断是不是每页12个时间节点的最后一个执行完毕,调用下一页生成#-->else if (this.value === this.maxValue && this.pageCode < Math.ceil(this.timeSet.length / this.pageSize)) {this.handlePalyNextPage();this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[Math.floor(this.value)]);}//console.log("@2", this.value, this.maxValue, this.time12ArrNode[Math.floor(this.value)]);}, this.second);} else {if (this.timer) {clearInterval(this.timer);}}}}
}
</script><style lang="less" scoped>
.TimeLine2-light {user-select: none;width: 100%;height: 100%;border: 2px solid slateblue;border-radius: 10px;background-color: rgba(255, 255, 255, 0.5);backdrop-filter: blur(10px);display: flex;justify-content: space-between;align-items: center;.LeftBox {width: 80%;height: 100;padding: 0px 30px;::v-deep .el-slider__runway {background-color: #cccccc88;}::v-deep .el-slider__button {width: 10px;height: 10px;background-color: transparent;border: none;}::v-deep .el-slider__stop {width: 1px;height: 12px;background-color: #4a0987;z-index: 999;display: block;}::v-deep .el-slider__marks-text {color: #4a0987;}}.RightBox {width: 20%;height: 100;display: flex;justify-content: space-around;align-items: center;}}.skin-control {position: absolute;top: 5px;right: 5px;}.skin-control-light {color: rgba(248, 17, 17, 0.5);
}.skin-control-dark {color: rgba(12, 35, 241, 0.5);
}.icon-size {font-size: 20px;
}.TimeLine2-dark {user-select: none;width: 100%;height: 100%;border: 2px solid white;border-radius: 10px;background-color: rgba(41, 5, 75, .5);backdrop-filter: blur(10px);display: flex;justify-content: space-between;align-items: center;.LeftBox {width: 80%;height: 100;padding: 0px 30px;::v-deep .el-slider__runway {background-color: #fff3;}::v-deep .el-slider__button {width: 10px;height: 10px;background-color: transparent;border: none;}::v-deep .el-slider__stop {width: 1px;height: 12px;background-color: white;z-index: 999;display: block;}::v-deep .el-slider__marks-text {color: white;}}.RightBox {width: 20%;height: 100;display: flex;justify-content: space-around;align-items: center;}
}
</style>

5其他说明

原文参考了

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 : ref 与 reactive

目录 一.ref 二.reactive 三.ref与reactive的区别 四.总结 一.ref 在 Vue 3 中&#xff0c;ref 是一个用于创建可读写且支持数据跟踪的响应式引用对象。它主要用于在组件内部创建响应式数据&#xff0c;这些数据可以是基本类型&#xff08;如 number、string、boolean&…

深入理解全连接层:从线性代数到 PyTorch 中的 nn.Linear 和 nn.Parameter

文章目录 数学概念&#xff08;全连接层&#xff0c;线性层&#xff09;nn.Linear()nn.Parameter()Q1. 为什么 self.weight 的权重矩阵 shape 使用 ( out_features , in_features ) (\text{out\_features}, \text{in\_features}) (out_features,in_features)而不是 ( in_featur…

Vue的缓存组件 | 详解KeepAlive

引言 在Vue开发中&#xff0c;我们经常需要处理大量的组件渲染和销毁操作&#xff0c;这可能会影响应用的性能和用户体验。而Vue的KeepAlive组件提供了一种简便的方式来优化组件的渲染和销毁流程&#xff0c;通过缓存已经渲染的组件来提升应用的性能。 本文将详细介绍Vue的Ke…

即插即用篇 | YOLOv10 引入矩形自校准模块RCM | ECCV 2024

本改进已同步到YOLO-Magic框架! 语义分割是许多应用的重要任务,但要在有限的计算成本下实现先进性能仍然非常具有挑战性。在本文中,我们提出了CGRSeg,一个基于上下文引导的空间特征重建的高效且具有竞争力的分割框架。我们精心设计了一个矩形自校准模块,用于空间特征重建和…

经典RNA-seq分析流程1

RNA-seq分析有很多流程&#xff0c; 一般都是上游linux工具获取表达矩阵数据&#xff0c;然后就可以使用下游R包进行处理了&#xff0c;要么是差异DEG表达gene等分析&#xff1b; 因为下游分析其实R包是明确的&#xff0c;毕竟有很多生信分析教程&#xff0c;但是上游的linux…

无人机之处理器篇

无人机的处理器是无人机系统的核心部件之一&#xff0c;它负责控制无人机的飞行、数据处理、任务执行等多个关键功能。以下是对无人机处理器的详细解析&#xff1a; 一、处理器类型 无人机中使用的处理器主要包括以下几种类型&#xff1a; CPU处理器&#xff1a;CPU是无人机的…

神经网络多层感知器异或问题求解-学习篇

多层感知器可以解决单层感知器无法解决的异或问题 首先给了四个输入样本&#xff0c;输入样本和位置信息如下所示&#xff0c;现在要学习一个模型&#xff0c;在二维空间中把两个样本分开&#xff0c;输入数据是个矩阵&#xff0c;矩阵中有四个样本&#xff0c;样本的维度是三维…

Unity全面取消Runtime费用 安装游戏不再收版费

Unity宣布他们已经废除了争议性的Runtime费用&#xff0c;该费用于2023年9月引入&#xff0c;定于1月1日开始收取。Runtime费用起初是打算根据使用Unity引擎安装游戏的次数收取版权费。2023年9月晚些时候&#xff0c;该公司部分收回了计划&#xff0c;称Runtime费用只适用于订阅…

[数据集][目标检测]车窗状态检测车窗开关检测数据集VOC+YOLO格式299张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;299 标注数量(xml文件个数)&#xff1a;299 标注数量(txt文件个数)&#xff1a;299 标注类别…

应用程序已被 Java 安全阻止:Java 安全中的添加的例外站点如何对所有用户生效

如题&#xff1a;应用程序已被 Java 安全阻止&#xff0c;如下图所示&#xff1a; 在寻找全局配置的时候花了一个上午的时间&#xff0c;到处搜解决方法&#xff0c;都不可行。最后还是参考官方的文档配置好了。如果你碰到了同样的问题&#xff0c;这篇文章一定可以帮到你。 环…

论文阅读:AutoDIR Automatic All-in-One Image Restoration with Latent Diffusion

论文阅读&#xff1a;AutoDIR: Automatic All-in-One Image Restoration with Latent Diffusion 这是 ECCV 2024 的一篇文章&#xff0c;利用扩散模型实现图像恢复的任务。 Abstract 这篇文章提出了一个创新的 all-in-one 的图像恢复框架&#xff0c;融合了隐扩散技术&#x…

【重学 MySQL】二十八、SQL99语法新特性之自然连接和 using 连接

【重学 MySQL】二十八、SQL99语法新特性之自然连接和 using 连接 自然连接&#xff08;NATURAL JOIN&#xff09;USING连接总结 SQL99语法在SQL92的基础上引入了一些新特性&#xff0c;其中自然连接&#xff08;NATURAL JOIN&#xff09;和USING连接是较为显著的两个特性。 自…

《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》P84

更正卷积与相关微课中互相关运算动画中的索引。 1-D correlation rectwave 禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

性能测试【Locust】基本使用介绍

一.前言 Locust是一款易于使用的分布式负载测试工具&#xff0c;基于事件驱动&#xff0c;使用轻量级执行单元&#xff08;如协程&#xff09;来实现高并发。 二.基本使用 以下是Locust性能测试使用的一个基础Demo示例&#xff0c;该示例有安装Locust、编写测试脚本、启动测…

三方共建 | 网络安全运营中心正式揭牌成立

9月3日&#xff0c;广州迎来了一场网络安全领域的盛事。悦学科技、聚铭网络、微步在线联合打造的7x24小时网络安全运营中心&#xff08;以下简称“中心”&#xff09;正式成立&#xff0c;并在现场举行了庄重而热烈的揭牌仪式。众多行业专家、企业代表齐聚一堂&#xff0c;共同…

MPP数据库之SelectDB

SelectDB 是一个高性能、云原生的 MPP&#xff08;大规模并行处理&#xff09;数据库&#xff0c;旨在为分析型数据处理场景提供快速、弹性和高效的解决方案。它专为处理大规模结构化和半结构化数据设计&#xff0c;常用于企业级业务分析、实时分析和决策支持。 SelectDB 是在…

实习项目|苍穹外卖|day9

实战作业。 用户端新增功能 1. 查询历史订单 接口设计 返回的是orderorderdetails&#xff08;那我这里就先查order&#xff0c;再根据order_id查&#xff09; 分页 pageHelper的使用&#xff1a; //controller相关函数GetMapping("/historyOrders")ApiOperati…

【GBase 8c V5_3.0.0 分布式数据库常用几个SQL】

1.检查应用连接数 以管理员用户 gbase&#xff0c;登录数据库主节点。 接数据库&#xff0c;并执行如下 SQL 语句查看连接数。 SELECT count(*) FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;2.查看空闲连接 查看空闲(state 字段为”idle”)且长时间没有更…

AI问答-Vue实例属性/实例方法:$refs、$emit、$attrs、$props、$data...

一、本文简介 在Vue.js中&#xff0c;$ 符号通常用于表示Vue实例或组件上的内置属性和方法&#xff0c;这些被称为“实例属性”或“实例方法”。以下是一些常见的以$开头的Vue实例属性和方法 1.1、实例属性 序号实例属性解释1$dataVue实例的数据对象&#xff0c;用于存储组件…

Linux - 探秘/proc/sys/net/ipv4/ip_local_port_range

文章目录 Pre概述默认值及其意义评估需求如何调整临时修改永久修改测试和验证 修改的潜在影响 Pre Linux - 探秘 Linux 的 /proc/sys/vm 常见核心配置 计划&#xff1a; 简要解释 /proc/sys/net/ipv4/ip_local_port_range 文件的功能和作用。介绍该文件的默认值及其影响。说明…