vue单条横向时间线(css+js)
vue单条横向时间线(css+js)
我这段时间遇到一个新的需求,在首页做一个时间线的展示图,因为其他的图都是用Echarts写的,这条时间线我也准备用Echarts,找了半天,没找到相关图例,因此,我在这方面纠结了很久,最后没有办法,只能自己手写一个时间线的图,样式很丑,这个就不用在意了,主要的是功能。
先上图吧
这个是基础逻辑就是点击右侧的天蓝色按钮,然后左侧下方的时间线会根据日期的数量动态生成,然后点击下面时间线的中心小圆点,上方的内容会跟着日期的不同而显示对应的内容。首先默认显示的是右侧第一条的日期和左侧下方时间条的第一个日期内容。
图片上的数据都是假数据,这些内容应该无所谓了吧
代码如下:
html代码
<div class="chart-content">
<div id="indexChart3">
<div class="con-middle-left">
<div class="projectCon">
<ul class="projectCon-left">
<span class="pament">基础合同付款条件:</span>
<li
v-for="contractTermData in contractTermList"
:key="contractTermData.termDesc"
>
{{
contractTermData.termDesc
}} <span>{{
contractTermData.isDelivered ? "已交付" : "未交付"
}}</span>
</li>
</ul>
<div class="projectCon-right" >
<div class="pament-con">爱奇艺付款节点:</div>
<div >爱奇艺付款节点:{{contractPament.paymentTerm}} <span class="pament-btn">{{
contractPament.isPayment ? "已付款" : "未付款"
}}</span></div>
</div>
</div>
<!-- 线 -->
<div class="line-botton">
<div
class="line-botton-one"
v-for="progressTime in progressTimeList"
:key="progressTime.seq"
@click="proConClick(progressTime)"
>
<div class="line-left"></div>
<div class="line-middle"></div>
<div class="line-left"></div>
</div>
</div>
<!-- 线的数据 -->
<div class="data-botton">
<div
v-for="progressTime in progressTimeList"
:key="progressTime.noteDesc"
:title="progressTime.noteDesc"
>
{{ progressTime.finalDeliveryDa }}<br />{{
progressTime.noteDesc
}}
</div>
</div>
</div>
<!-- 右侧按钮 -->
<div class="con-middle-right">
<ul>
<li
v-for="projectNameData in projectDate"
:key="projectNameData.projectName"
@click="projectClick(projectNameData)"
>
<button :title="projectNameData.projectName" :class='btnclass'>
{{ projectNameData.projectName }}
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
css代码:
.content-left {
.item-flex {
display: flex;
justify-content: center;
align-items: center;
}
}
.btnclass{
background: rgba(248, 192, 66, 0.33);
}
.projectCon {
width: 500px;
height: 160px;
margin: 30px 10px 0 10px;
border: 1px solid #fff;
border-radius: 10px;
overflow-y: auto;
background:rgb(255, 236, 193);
color: rgb(68, 61, 61);
opacity: 1;
.projectCon-left {
min-height:100%;
padding: 20px 10px 10px 10px;
float: left;
width:70%;
border-right:1px solid #ccc;
.pament{
width: 48%;
position: absolute;
top: 31px;
padding: 10px 0 0 0;
background:rgb(255, 236, 193);
color: red;
}
li {
margin:20px 0 5px 0 ;
span {
color: red;
}
}
}
.projectCon-right{
padding: 35px 10px 10px 10px;
float: right;
width:30%;
height:100%;
.pament-con{
width: 20%;
position: absolute;
top: 31px;
padding: 10px 0 0 0;
background:rgb(255, 236, 193);
color: red;
}
.pament-btn {
color: red;
}
}
}
.line-botton {
width: 500px;
height: 20px;
margin: 0 10px 0 10px;
// background: #000;
display: flex;
justify-content: center;
align-items: center;
.line-botton-one {
width: 20%;
display: flex;
justify-content: center;
align-items: center;
.line-left {
width: 48%;
border-bottom: 2px solid rgb(46, 212, 96);
margin-top: 15px;
}
.line-middle {
cursor: pointer;
border: 1px solid rgb(46, 212, 96);
width: 10px;
height: 10px;
margin-top: 15px;
border-radius: 50%;
background: rgb(46, 212, 96);
}
}
}
.data-botton {
width: 500px;
height: 20px;
margin: 15px 20px 0 10px;
display: flex;
justify-content: center;
align-items: center;
div {
width: 110px;
height: 40px;
margin: 0 13px;
width: 12%;
text-align: center;
font-size: 12px;
overflow: hidden;
white-space: nowrap;
}
}
#indexChart3{
display: flex;
}
.con-middle-left {
margin-left: 20px;
width: 85%;
height: 250px;
}
.con-middle-right {
margin: 20px 0 0 0;
width: 15%;
height: 200px;
button {
width: 80px;
// height: 20px;
margin-top: 5px;
padding: 5px 3px 5px 3px ;
// border: rgb(154, 247, 242) 1px solid;
border:#fff;
border-radius: 5px;
background: #3f75d4;
font-size: 12px;
white-space: nowrap;
overflow: hidden;
color: #fff;
}
button:hover{
background:#fc544b;
}
}
js代码:
methods: {
loadStoreData() {
var self = this;
var projectDate = {}; //单个项目
var handleResult = function (res) {
var data = [];
var result = 0;
for (let j = 0; j < res.data.length; j++) {
projectDate = res.data[j];
let projectName = projectDate.projectName; //项目名称
self.exProjectDate.push(projectDate);
self.projectDate = self.exProjectDate.slice(-7);
}
self.progressTimeList = self.projectDate[0].progressList;
self.contractTermList = self.progressTimeList[0].contractTermList;
self.contractPament = self.progressTimeList[0]//第一次进页面给时间线的默认值
};
var params = {
object: {
projectCode: ***,//请求接口需要的参数
},
};
return new Promise((resolve, reject) => {
api
.***(params)//这是请求的接口
.then((response) => {
if (response.body.code == "0000") {
let result = response.body;
if (result) {
handleResult(result);
}
}
})
.catch((error) => {
reject(error);
});
});
},
// 获取展示框数据
proConClick(progressTimeList) {
return new Promise((resolve, reject) => {
this.contractPament = progressTimeList
this.contractTermList = progressTimeList.contractTermList;
});
},
// 获取时间线日期和内容数据
projectClick(project) {
return new Promise((resolve, reject) => {
this.progressTimeList = [];
var self = this;
for (let i = 0; i < project.progressList.length; i++) {
var progressTimeList = project.progressList[i];
self.progressTimeList.push(progressTimeList);
}
self.contractTermList = self.progressTimeList[0].contractTermList;
self.contractPament = self.progressTimeList[0]//点击右侧按钮后展示框显示的默认值
});
},
},
mounted() {
this.$nextTick(function () {
setTimeout(() => {
this.loadSendData();
}, 1000);
});//进入页面自动执行
},
因为这是用vue写的,所以这些代码是vue的代码,这些样式都不是难点,主要的是这个数据处理,我这个接口返回的数据嵌套了五层,我用的是传参的方式,将获取的数据处理后通过参数传给proConClick和projectClick这两个函数,我也是一个前端小白,如果有什么更好的方法,不管是样式还是数据处理,都非常欢迎大佬们批评指正。