目录
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其他说明
原文参考了