效果看圖,剛寫的“組件”,需要剝離的參數自己寫進props就行,不完善的地方自己完善,有什麼不懂的地方可以進羣問,一般不會回答
拖拽的時候時間和比例自己會變,有需要自己拿源碼,非vue的參考下思路就行
<template>
<div class="zhTimeProcess">
<div class="processCtn"
:ref="'zhTimeProcess'+ id">
<div class="processLine"
v-for="(item,index) in renderData"
:key="'processLine' + index"
:style="{'width':item.width + 'px'}">{{item.percent * 100 + '%'}}({{item.name}})</div>
<div class="timeNode unEdit">
<span class="time">{{startTime}}</span>
<!-- <span class="name">下單日期</span> -->
</div>
<div class="timeNode"
@mousedown.left="startDrag($event,item)"
@mouseup.left="endDrag(item)"
@mousemove="dragging($event,item,index)"
@mouseout="endDrag(item)"
v-for="(item,index) in renderData"
:key="'timeNode' + index"
:class="{'unEdit':index===renderData.length-1}"
:style="{'left':item.left + 'px'}">
<span class="time">{{cmpDate(item.percent)}}</span>
<!-- <span class="name">{{item.name}}</span> -->
</div>
</div>
</div>
</template>
<script>
import './zhTimeProcess.less'
export default {
data () {
return {
id: 1, // 用於標記當前組件的id,一個頁面有多個該組件的時候可以用到
startTime: '2020-01-01',
endTime: '2020-03-01',
needTime: 0, // 所需時間
testData: [{
name: '物料計劃',
percent: 0.2
}, {
name: '物料入庫',
percent: 0.3
}, {
name: '半成品入庫',
percent: 0.4
}, {
name: '成品裝箱',
percent: 0.1
}],
domWidth: 0,
renderData: [],
mousePosition: 0 // 記錄鼠標位置
}
},
methods: {
cmpDate (percent) {
let startTime = new Date(this.startTime)
startTime.setDate(startTime.getDate() + Math.round(percent * this.needTime))
return startTime.getFullYear() + '-' + (startTime.getMonth() < 9 ? '0' + (startTime.getMonth() + 1) : (startTime.getMonth() + 1)) + '-' + (startTime.getDate() < 10 ? '0' + (startTime.getDate()) : startTime.getDate())
},
startDrag (ev, item) {
this.mousePosition = ev.clientX
item.draggble = true
},
endDrag (item) {
item.draggble = false
},
dragging (ev, item, index) {
if (item.draggble) {
let itemNext = this.renderData[index + 1]
let deltX = ev.clientX - this.mousePosition
item.left = item.left + deltX
item.width = item.width + deltX
item.percent = (item.width / this.domWidth).toFixed(2)
itemNext.width = itemNext.width - deltX
itemNext.percent = (itemNext.width / this.domWidth).toFixed(2)
this.mousePosition = ev.clientX
this.$forceUpdate()
}
// console.log(ev)
}
},
mounted () {
this.needTime = (new Date(this.endTime).getTime() - new Date(this.startTime).getTime()) / 1000 / 60 / 60 / 24
this.domWidth = this.$refs['zhTimeProcess' + this.id].offsetWidth
let left = 0
this.renderData = this.testData.map((item) => {
item.width = Math.round(this.domWidth * item.percent)
left = left + item.width
item.left = left
return item
})
}
}
</script>
.zhTimeProcess{
display: block;
height: 20px;
padding: 25px 0;
.processCtn{
height:100%;
background: #4989D3;
position: relative;
.processLine{
text-align: center;
display: inline-block;
height: 100%;
line-height: 20px;
font-size: 14px;
color: #fff;
overflow: hidden;
text-overflow: ellipsis;
}
.timeNode{
position: absolute;
width: 2px;
top: 0;
bottom: 0;
background: #fff;
cursor: pointer;
&.unEdit{
background:rgba(0,0,0,0);
&::after{
border:0;
}
&::before{
border:0;
}
}
&::after{
content: '';
position: absolute;
width: 0;
height: 0;
border:6px solid transparent;
border-top-color: #4989D3;
top: -9px;
left: -5px;
}
&::before{
content: '';
position: absolute;
width: 0;
height: 0;
border:6px solid transparent;
border-bottom-color: #4989D3;
bottom: -9px;
left: -5px;
}
.time{
position: absolute;
white-space: nowrap;
font-size: 12px;
left: 1px;
top: -28px;
transform: translate(-50%);
color: rgba(0,0,0,0.85);
}
.name{
position: absolute;
white-space: nowrap;
font-size: 12px;
left: 1px;
bottom: -28px;
transform: translate(-50%);
color: rgba(0,0,0,0.85);
}
}
}
}