效果看图,刚写的“组件”,需要剥离的参数自己写进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);
}
}
}
}