想根据element-ui组件里的slider滑块实现时间轴,效果如下
目前已使用单独组建将次时间轴进行样式显示,现在的问题是,不知道el-slider 滑动时怎么让对应标签在正上方显示。以及怎么时间根据不同间隔(5分钟、6分钟、10分钟、30分钟、 1小时)提示标签对应拖动后增加目前我实现的vue组件内容如下
<template>
<div class="slider">
<div class="minipanel">
<div class="refresh"><el-checkbox v-model="checked">自动刷新</el-checkbox></div>
<div class="timeleap"><label for="">间隔:</label>
<select v-model="timeStep" class="timer-select">
<option v-for="(item,index) in timeOptions" :key="item.value"
:label="item.label"
:value="item.value"/>
</select>
</div>
<div class="datetime">
<el-date-picker
v-model="timeCur"
type="date"
placeholder="选择日期">``
</el-date-picker>
</div>
<div class="play">
<div class="panelgap" :class="{'noClick':checked}" title="刷新"></div>
<div class="leftbtn" :class="{'noClick':checked}" title="往前"></div>
<div v-show="playing" class="playbtn" :class="{'noClick':checked}" title="播放"></div>
<div v-show="!playing" class="pausebtn" :class="{'noClick':checked}" title="暂停"></div>
<div class="rightbtn" :class="{'noClick':checked}" title="往后"></div>
</div>
</div>
<div class="slider-timer">
<!-- <el-slider v-model="nowCur"></el-slider> -->
<div class="custom-tooltip" v-if="tooltipVisible" >
<span class="custom-tooltip-tip">{{ tooltipText }} </span>
</div>
<el-slider ref="slider" :show-tooltip="false" v-model="nowCur" :max="maxTime" @change="handleSliderChange" :step="5"></el-slider>
<div class="time-marks">
<span class="slider-pip" v-for="(item,index) in timeMarks">
<span class="slider-label">
<span class="slider-longline"></span>
<div class="_sider_time" style="position: inherit;margin-left:4px;position: inherit;top: 26px;width: 40px;font-weight: normal;">{{ item.hour.replace(/0(\d)/g, '$1') }}</div>
</span>
</span>
</div>
</div>
</div>
</template>
<script>
import * as moment from 'moment';
export default{
data(){
return{
checked:false,
timeOptions:[{value: '10',label: '10min'},{value: '30',label: '30min'},{value: '60',label: '1h'}],
timeStep:10,timeCur:null,nowCur:null,
playing:true,
minTime:0,//new Date(new Date().getTime() - 24 * 3600 * 1000 - 3600 * 1000).getTime(),
// 当前时间前1小时的过去24小时
maxTime:100,//new Date(new Date().getTime() + 10 * 3600 * 1000).getTime(),
// 当前时间未来10小时
timeMarks: [],
tooltipVisible: true,
tooltipText: '',
tooltipStyle: {},
}
},
prop:{},
mounted(){this.initTime()},
methods:{
initTime(){
// 获取当前时间
this.timeCur = moment().format('YYYY-MM-DD');
this.nowCur = moment().hour();
// this.minTime = moment(this.timeCur).subtract(25, 'hours').hour()
// this.maxTime = moment(this.timeCur).add(12, 'hours').hour()
// 时间轴时次
this.getTimeCur()
// 时间轴显示toolip
},
getTimeCur(){
const now = moment(this.timeCur);
const year = now.year();
const month = now.format('MM');
const time = now.valueOf();
const hourInMs = 60 * 60 * 1000;
const scaleCountPast = 25;
const scaleCountFuture = 0; // 36 48
const scaleWidth = 70;
const tipsMark = [];const Mark = []
for (let i = -scaleCountPast; i <= scaleCountFuture; i++) {
const scaleTime = moment(time + i * hourInMs);
const day = scaleTime.format('DD');
const hour = scaleTime.format('HH');
const minute = scaleTime.format('mm');
Mark.push({index:i,hour:hour})
}
this.timeMarks = Mark
},
formatTime(timeStamp) {
const date = new Date(timeStamp);
return `${date.getDate()}日${date.getHours().toString().padStart(2, '0')}时${date.getMinutes().toString().padStart(2, '0')}分`;
},
handleSliderChange(value) {
// 当 slider 值改变时,更新 tooltip
this.updateTooltip(value);
},
updateTooltip(value) {
this.tooltipText = '';
this.tooltipVisible = true;
const sliderRect = this.$refs.slider.$el.getBoundingClientRect();
const sliderMax = this.maxTime;
const percent = (value / sliderMax) * 100;
const left = `${(percent / 100) * 20 - 10}px`;
this.tooltipStyle = {
left: `${left}%`, // 假设 tooltip 宽度为 100px
};
},
},
computed:{
},
watch:{},
}
</script>
<style lang="scss" scoped>
$bg:#fff;
.slider{
margin-left: -350px;
left: 50%;
position: absolute;
z-index: 1;
width: 700px;
height: 56px;
bottom: 32px;
opacity: 0.8;
box-sizing: border-box;
.minipanel{
float: left;
margin-left: -35px;
margin-top: -42px;
color: #000;
.refresh{
margin-bottom: 2px;
width: 100%;
height: 22px;
display: flex;justify-content: center;
-webkit-box-align: center;align-items: center;
border-radius: 20px;
border:1px solid #06608a;
background: $bg;
}
.timeleap{
display: -webkit-box;display: -ms-flexbox;display: flex;
-webkit-box-pack: center;-ms-flex-pack: center;
justify-content: center;-webkit-box-align: center;-ms-flex-align: center;
align-items: center;
border-radius: 20px;
border: 1px solid #06608a;
background: #fff;
height: 22px;
line-height: 22px;
-webkit-box-sizing: border-box;box-sizing: border-box;
padding: 5px;
::v-deep .timer-select{
width: 60px;
border: none;
color: #06608a;
text-transform: none;
option{line-height: 20px;height: 20px;}
}
}
.datetime{display: inline-block;line-height: normal;
::v-deep .el-date-editor.el-input, .el-date-editor.el-input__inner {
margin-top: 2px;
border: 1px solid #06608a;
display: block;
background: #fff;
height: 22px;
width: 120px;
border-radius: 12px;
color: #06608a;
text-align: center;
line-height: 22px;
}
::v-deep .el-input__inner{
height: 22px;
line-height: 22px;
border-radius: 22px;
font-size: 12px;
color: #06608a;
padding-right: 10px;
}
::v-deep .el-input__prefix{top:-8px;}
}
.play{
display: flex;
justify-content: space-around;
.panelgap{width: 30px;
height: 30px;background: url(../assets/home/time_refresh.png);margin-top: 5px;}
.leftbtn{width: 30px;
height: 30px;background: url(../assets/home/move_btn.png) center no-repeat;transform: rotateZ(180deg);overflow: hidden;margin-top: 2px;}
.playbtn{width: 30px;
height: 30px;background: url(../assets/home/move_play.png) center no-repeat;overflow: hidden;margin-top: 5px;}
.pausebtn{width: 30px;
height: 30px;background: url(../assets/home/pause_btn.png) center no-repeat;overflow: hidden;margin-top: 5px;}
.rightbtn{width: 30px;
height: 30px;background: url(../assets/home/move_btn.png) center no-repeat;overflow: hidden;margin-top: 5px;}
//
.panelgap.noClick{background: url(../assets/home/time_refresh_stop.png);}
.leftbtn.noClick{background: url(../assets/home/stop_btn.png) center no-repeat;transform:rotateZ(0deg);cursor: no-drop;pointer-events: none;margin-top: 5px;}
.playbtn.noClick{background: url(../assets/home/stop_play.png) center no-repeat;cursor: no-drop;pointer-events: none;}
.rightbtn.noClick{background:url(../assets/home/stop_btn.png) center no-repeat ;transform: rotateZ(180deg);cursor: no-drop;pointer-events: none;margin-top: 1px;}
}
}
&-timer{
::v-deep .el-slider{
margin-left: 120px;
margin-top:-26px;
margin-right: 15px;
height: 8px;
.el-slider__runway{
height: 8px;border-radius: 5px;
border: 1px solid #007ca0!important;
background: rgba(75,92,108,0.5)!important; //background-color: #4b5c6c80;
}
.el-slider__bar{
height: 8px;
background-color: #3090f0;
}
.el-slider__button{
width: 10px;
height: 10px;
z-index: 2;
border: 3px solid #fff;
background: -moz-linear-gradient(top, #a7d8ff, #69b7f7);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#a7d8ff), to(#69b7f7));
background: #3090f0;
border-radius: 50%;
-webkit-transform: translate(36%, 0px);
transform: translate(36%, 0px);
}
}
}
.custom-tooltip{
position: absolute;
margin-left: 132px;
margin-top: 10px;
margin-right: 15px;
&-tip{
position: absolute;
visibility: hidden;
top: -40px;
display: block;
width: 34px;
margin-left: -18px;
left: 50%;
height: 20px;
line-height: 20px;
background: #fff;
border-radius: 3px;
border: 1px solid #888;
text-align: center;
font-size: 12px;
opacity: 0;
color: #333;
-webkit-transition-duration: .2s,.2s,0;
transition-duration: .2s,.2s,0;
-webkit-transition-property: opacity,top,visibility;
transition-property: opacity,top,visibility;
-webkit-transition-delay: 0,0,.2s;
transition-delay: 0,0,.2s;
visibility: visible;
opacity: 1;
top: -25px;
margin-left: -40px;
width: 80px;color: #000;background: #fff;
&::before {
content: " ";
width: 0;
height: 0;
border: 5px solid hsla(0,0%,100%,0);
border-top-color: #888;
position: absolute;
bottom: -11px;
left: 50%;
margin-left: -5px;
}
&::after {
content: " ";
width: 0;
height: 0;
border: 5px solid hsla(0,0%,100%,0);
border-top-color: #fff;
position: absolute;
bottom: -10px;
left: 50%;
margin-left: -5px;
}
}
}
.time-marks{
display: flex;
margin: auto;
margin-top: 30px;
margin-left: 120px;
display: none;
.slider-pip{
width: 2em;
height: 1em;
line-height: 1em;
position: absolute;
font-size: .8em;
color: #999;
overflow: visible;
text-align: center;
top: 20px;
left: 20px;
margin-left: -1em;
cursor: pointer;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
.slider-label{
}
}
}
}
</style>
1.拖动滑块时能在对应正上方标签显示当前x日x时x分(根据间隔进行分、时叠加) 2.滑块条为对应整下方为时次显示(左侧选中时间值的过去24小时逐小时内容) 3.点击播放若花开位置已在100%不执行,反之往前走动(每个1s请求)
手搓,只能且必须手搓一个Tool,这个组件只支持鼠标经过隐藏与显示,初始化常态显示压根就不支持。方法就是css伪类。赋值的时候要给content传字符串内容。
<template>
<div style="width: 800px; margin: 30px">
<el-slider
v-model="time"
:min="0"
:max="24"
:show-tooltip="false"
@change="handleTimeChange"
></el-slider>
</div>
</template>
<script>
import moment from "moment";
export default {
data() {
return {
time: 0, // 初始化时显示tooltip
};
},
mounted() {
let hours = moment().format("HH");
this.showTime(hours);
},
methods: {
showTime(v) {
const that = this;
that.time = Number(v); //赋值小时注意这里必须为Number型
//tool显示文本
let sliderBar = document.getElementsByClassName("el-slider__bar");
let sliderButton = document.getElementsByClassName(
"el-slider__button-wrapper"
);
let showTime = moment().format("YYYY-M-D");
sliderButton[0].setAttribute(
"data-attr",
showTime + "\n" + that.time + ":00"
);
// 值为0的时候滑块位于最右端
if (that.time == 0) {
sliderBar[0].style.width = "0%";
sliderButton[0].style.left = "0%";
}
},
handleTimeChange(newTime) {
console.log(" ~ handleTimeChange ~ newTime:", newTime)
this.showTime(newTime);
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-slider__button-wrapper::before {
content: attr(data-attr); // 给伪类添加内容,值为上述传递的值
position: absolute;
width: 110px;
height: 25px;
border-radius: 5px;
border: 1px solid #ddd;
top: -25px;
left: -40px;
background: #fff;
font-size: 12px;
line-height: 25px;
text-align: center;
color: #000;
}
</style>
简单的方案:最大最小值使用时间戳,下面的marks根据开始结束时间进行等量分割,然后格式化,上面拖拽时的内容使用format-tooltip格式化显示就好了,
本文向大家介绍Android实现列表时间轴,包括了Android实现列表时间轴的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android列表时间轴展示的具体代码,供大家参考,具体内容如下 实现的效果图如下: 实现的方式是利用recycleview的ItemDecoration这个抽象类,就是我们经常用来画分割线的的这个类, 具体如下 使用比较简单: 以上就是本文的全部内容,希望对
本文向大家介绍DevExpress之ChartControl实现时间轴实例,包括了DevExpress之ChartControl实现时间轴实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了DevExpress采用ChartControl实现时间轴的方法,分享给大家供大家参考。具体实现方法如下: 关键代码如下: 运行效果如下图所示: 希望本文所述对大家的C#程序设计有所帮助
本文向大家介绍Vue实现可移动水平时间轴,包括了Vue实现可移动水平时间轴的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Vue实现可移动水平时间轴的具体代码,供大家参考,具体内容如下 里程碑时间轴具体实现 效果图 编辑里程碑效果图 编辑里程碑 stonedetail.vue 关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。 以上就是本文的全部内容,希望对
本文向大家介绍Android自定义时间轴的实现过程,包括了Android自定义时间轴的实现过程的使用技巧和注意事项,需要的朋友参考一下 本文讲述Android自定义时间轴的实现过程,供大家参考,具体内容如下 相关视频链接: Android自定义控件系列 http://edu.csdn.net/course/detail/3719/65396 Android视频全系列 http://edu.csdn
本文向大家介绍Android实现快递物流时间轴效果,包括了Android实现快递物流时间轴效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android实现快递物流时间轴效果展示的具体代码,供大家参考,具体内容如下 首先,这篇参考了别人的代码。根据自己的项目需求简单改造了一下,效果图如下 xml:代码 接下来是Activity,准备数据就好了 Adapter: 每一个item的布
使用Chrome DevTools Timeline(时间轴)面板录制和分析应用程序运行时的所有活动。这是开始检查和感知应用程序性能问题的最佳位置。 TL;DR 进行时间轴录制来分析在网页加载或用户互动后发生的每个事件。 在Overview(概览)窗格中查看FPS,CPU和网络请求。 单击 Flame Chart (火焰)图表中的事件可查看其详细信息。 放大录制的一部分,使分析更容易。 Timel