最近在做大屏展示,其中一个需求是展示生产过程中投料情况,效果类似甘特图。
思路:1.先得到整个过程的开始时间startTime和结束时间endTime。计算出整个过长经历的时长。
2.计算横向坐标的开始时间start和结束时间end,坐标的开始时间为生产开始时间-百分之十的生产时长,即start = startTime – 0.1h;坐标的结束时间为生产结束时间+百分之十的生产时长,即end = endTime + 0.1h.
3.确定横纵坐标值,先计算横计算坐标间隔,我固定了横坐标的打点数,直接用横坐标结束时间-坐标开始时间除以点数+1,即 (end-start) / (number +1)。得到间隔之后就可以计算出横坐标值。纵坐标值直接使用物料名称
4.显示每个料的投放情况显示出来。显示是用的div,每种物料的投料时长就是div的长度。
注意:计算宽度的时候需要依据自己的实际情况进行调整
效果
代码
<template> <div class="Gantt"> <div class="content" ref="scrollbar"> <!-- --> <div class="info" style="margin-top: 2px; overflow: scroll; overflow-x: hidden;height: calc(100vh * 220 / 1080);" > <div id="gui-content" class="gui-content"> <div class="gui-list clear room-gui-list" v-for="task in taskList" :key="task.materialId" > <div id="name" class="fasten ellipsis" :title="task.name"> {{ task.name }} </div> <div class="gui-tab"> <li v-for="(o, i) in config.xAxis" :key="i" :style="{ width: 100 / (number + 1) + '%', cursor: 'pointer', }" ></li> </div> <template v-if="task.materialId"> <div v-for="(item, index) in task.materialData" :key="index" class="meet-item-one" v-bind:class="[ !item.status ? 'meet-color-having' : 'meet-color-finished', ]" :style="{ left: getLeftTime(item.startTime) + '%', width: getWidth(item) + '%', backgroundColor: item.color, // opacity:0.8 }" v-show="getWidth(item) != 0" @click="edit(item)" > <el-popover placement="top-start" trigger="hover" :style="{fontSize:'10px',padding:'0px'}" > <p>{{'开始:'+item.startTime}}</p> <p>{{'结束:'+item.endTime}}</p> <div slot="reference" class="meet-item-one-content"> <p class="ellipsis" >{{ item.content }}</p> </div> </el-popover> </div> </template> </div> </div> </div> <!-- --> <div class="time-bar clear"> <div class="gui-table clear"> <li :style="{ width: 100 / (number + 1) +'%', }" v-for="(item, index) in config.xAxis" :key="index" > <div class="gui-cle"></div> <div class="gui-lit"></div> <div class="gui-title"><span class="">{{item.xAxis}}</span></div> </li> </div> </div> </div> </div> </template> <script> import {Popover,Scrollbar} from 'element-ui' export default { name: "GanttDemo", data() { return { date: "", number:6, xInterval:0.1, config: {xAxis:[]}, taskList: [ { materialId: "1", name: "物料一", startTime: "2022-11-16 08:00:00", endTime: "2022-11-16 20:00:00", materialData: [ { materialId: "1", id: "14444", status: 0, startTime: '2022-11-16 08:00:00', endTime: '2022-11-16 12:00:00', color:"#32c5e9", content:"800", }, { materialId: "1", id: "15555", status: 0, startTime: '2022-11-16 18:30:10', endTime: '2022-11-16 20:00:00', color:"#32c5e9", content:"600", }, ], }, { materialId: "2", name: "物料二", startTime: "2022-11-16 20:00:00", endTime: "2022-11-16 23:30:00", materialData:[{ materialId: "2", id: "223865", status: 0, startTime: '2022-11-16 20:00:00', endTime: '2022-11-16 23:30:00', color:"#eb865e", content:"800", }, ] },{ materialId: "3", name: "物料三", startTime: "2022-11-16 15:00:00", endTime: "2022-11-16 16:30:00", materialData:[{ materialId: "3", id: "31", status: 0, startTime: '2022-11-16 15:00:00', endTime: '2022-11-16 16:30:00', color:"#eb865e", content:"500", }, ] },{ materialId: "4", name: "物料四", startTime: "2022-11-16 12:00:00", endTime: "2022-11-16 16:30:00", materialData:[{ materialId: "4", id: "41", status: 0, startTime: '2022-11-16 12:00:00', endTime: '2022-11-16 16:30:00', color:"#eb865e", content:"450", }, ] },{ materialId: "5", name: "物料五", startTime: "2022-11-16 11:00:00", endTime: "2022-11-16 15:30:00", materialData:[{ materialId: "5", id: "51", status: 0, startTime: '2022-11-16 11:00:00', endTime: '2022-11-16 15:30:00', color:"#eb865e", content:"300", }, ] },{ materialId: "6", name: "物料六", startTime: "2022-11-16 11:00:00", endTime: "2022-11-16 12:30:00", materialData:[{ materialId: "6", id: "61", status: 0, startTime: '2022-11-16 11:00:00', endTime: '2022-11-16 12:30:00', color:"#eb865e", content:"200", }, ] },{ materialId: "7", name: "物料七", startTime: "2022-11-16 09:00:00", endTime: "2022-11-16 10:30:00", materialData:[{ materialId: "7", id: "71", status: 0, startTime: '2022-11-16 09:00:00', endTime: '2022-11-16 10:30:00', color:"#eb865e", content:"300", }, ] }, ] }; }, components:{ elPopover: Popover, elScrollbar:Scrollbar, }, props:{ }, watch:{ }, mounted(){ this.getConfig(); }, methods: { getLeftTime(cTime) { const dTime = new Date(cTime).getTime(); const leftTime = new Date(this.config.startTime).getTime(); const time = (dTime - leftTime) / (1000 * 60 * 60); // 小时数 const leftPercent = 0.88 * (time * 100) / (this.xInterval * (this.number+1)) ; return leftPercent + 12; }, getWidth(item) { const _left1 = this.getLeftTime(item.startTime); const _left2 = this.getLeftTime(item.endTime); return _left2 - _left1; }, edit(item) { console.log(item); }, getConfig(){ if(this.taskList.length>0){ let startTime = this.taskList[0].startTime; let endTime = this.taskList[0].endTime; console.log(endTime) for(let index in this.taskList){ let task = this.taskList[index]; let start1 = startTime?new Date(startTime):new Date(); let start2 = new Date(task.startTime); if(start1 > start2 && null != task.startTime){ startTime = task.startTime; } let end1 = new Date(endTime); let end2 = new Date(task.endTime?task.endTime:start2); if(end1 < end2){ endTime = task.endTime; } } let hour =((new Date(endTime)).getTime() - (new Date(startTime)).getTime()); this.config.start = startTime; this.config.end = endTime; this.config.startTime = this.getDateTime(new Date((new Date(startTime)).getTime()-0.1*hour)); this.config.endTime = this.getDateTime(new Date((new Date(endTime)).getTime()+0.1*hour)); hour = ((new Date(this.config.endTime)).getTime() - (new Date(this.config.startTime)).getTime()); this.config.hour = hour; if(hour){ this.xInterval = (hour / (this.number+1)) / (1000*60*60); } this.config.xAxis = [] let hh = (new Date(this.config.startTime)).getHours() < 10 ? '0' + (new Date(this.config.startTime)).getHours() : (new Date(this.config.startTime)).getHours(); let mm = (new Date(this.config.startTime)).getMinutes() < 10 ? '0' + (new Date(this.config.startTime)).getMinutes() : (new Date(this.config.startTime)).getMinutes(); let xOne = hh +":" +mm; this.config.xAxis.push({xAxis:xOne}); for(let i = 0;i < this.number;i++){ console.log(); let node = (new Date(this.config.startTime)).getTime()+(this.xInterval * 60 *60 * 1000 * ( i + 1 )); let nodeHh = (new Date(node)).getHours() < 10 ? '0' + (new Date(node)).getHours() : (new Date(node)).getHours(); let nodeMm = (new Date(node)).getMinutes() < 10 ? '0' + (new Date(node)).getMinutes() : (new Date(node)).getMinutes(); let nodeX = nodeHh + ":" + nodeMm; this.config.xAxis.push({xAxis:nodeX}); } } }, getDateTime(time){ let year = time.getFullYear(); //获取年 2021 let month = time.getMonth() + 1; // 获取月 5 let day = time.getDate(); // 获取天 11 let h = time.getHours() < 10 ? '0' + time.getHours() : time.getHours(); // 获取小时 18 let m = time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes(); // 获取分钟 42 let s = time.getSeconds() < 10 ? '0' + time.getSeconds() : time.getSeconds(); // 获取秒 51 let dataTime = year + '-' + month + '-' + day + ' ' + h + ':' + m + ':' + s; return dataTime; }, } }; </script> <style lang="scss" scoped > .Gantt { padding: calc(100vw * 20 / 1920 );; border-radius: 3px; /* border: 1px solid red; */ height: 100%; box-sizing: border-box; display: flex; flex-direction: column-reverse; position: relative; } .content { padding-top: calc(100vw * 20 / 1920 ); } .content /deep/ .el-scrollbar{ height: calc(100vh * 220 / 1080); .el-scrollbar__wrap { overflow-x: hidden; } } .content /deep/ .el-scrollbar__view { height: 100%; // display: flex; // flex-direction: column-reverse; } .Gantt .gui-table, .gui-tab { font-size: calc(100vw * 12 / 1920 ); color: #333; margin: 0; width: 88%; float: right; white-space: nowrap; height: calc(100vh * 48 / 1080 ); } .Gantt .gui-table li { position: relative; border-top: solid 1px #1ba5fa; z-index: 666; word-wrap: break-word; } .Gantt .gui-table li { cursor: default; } .Gantt .gui-table li{ float: left; text-align: left; width: 8.9%; height: calc(100vh * 48 / 1080 ); line-height: calc(100vh * 48 / 1080 ); /* cursor: pointer; */ white-space: pre-wrap; } .Gantt .gui-table .gui-title{ line-height: calc(100vh * 24 / 1080 ); position: relative; width: 100%; } .Gantt .gui-table .gui-title span{ line-height: calc(100vh * 24 / 1080 ); color: rgba(255,255,255,.7); position: absolute; left: -50%; text-align: center; width: 100%; } .gui-tab li { float: left; text-align: left; width: 8.9%; height: calc(100vh * 28 / 1080 ); line-height: calc(100vh * 28 / 1080 ); /* cursor: pointer; */ white-space: pre-wrap; } .Gantt .gui-cle { position: absolute; left: -5px; top: -5px; width: 6px; height: 6px; background: #fff; border-radius: 50%; border: solid 2px #1ba5fa; z-index: 666; } .Gantt .gui-lit { position: absolute; left: 0; top: -3px; width: 3px; height: 3px; background: #fff; border-radius: 50%; border: solid 1px #1ba5fa; margin-left: 50%; z-index: 666; } .clear { *zoom: 1; } .clear:after { content: "."; display: block; clear: both; visibility: hidden; line-height: 0; height: 0; font-size: 0; } .Gantt .fasten { width: 12%; float: left; height: calc(100vh * 28 / 1080 ); text-align: center; line-height: calc(100vh * 28 / 1080 ); font-size: calc(100vw * 12 / 1920 ); color: rgba(255, 255, 255, .7); border-right: solid 1px #1ba5fa; /* word-break: break-word; white-space: pre-line; */ } .Gantt .gui-table{ font-size: calc(100vw * 12 / 1920 ); color: #333; margin: 0; width: 88%; float: right; white-space: nowrap; height: calc(100vh * 48 / 1080 ); } .gui-tab { font-size: calc(100vw * 12 / 1920 ); color: #333; margin: 0; width: 88%; float: right; white-space: nowrap; height: calc(100vh * 28 / 1080 ); } /* .Gantt .gui-list:first-child { background: #fff; } */ .Gantt .gui-list { position: relative; display: flex; } .Gantt .meet-color-finished { background: #4dc394; } .Gantt .meet-color-having { background: #eb865e; } .Gantt .meet-item-one { color: #000; text-align: center; position: absolute; height: calc(100vh * 26 / 1080 ); left: 12%; top: 1px; color: #fafafa; font: 14px/60px microsoft yahei; /* padding: 0 5px; */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; overflow: hidden; cursor: pointer; width: 20%; line-height: calc(100vh * 26 / 1080 ); } li { list-style: none; } .Gantt .meet-item-one-content{ height: 100%; } .ellipsis { overflow: hidden; margin-top: 0; white-space: nowrap; text-overflow: ellipsis; line-height: calc(100vh * 28 / 1080 ); } .info,.gui-content{ display: flex; flex-direction: column-reverse; } .info::-webkit-scrollbar { width : 5px; height: 1px; } .info::-webkit-scrollbar-thumb { box-shadow: 0px 1px 3px rgba(144,147,153,.3) inset; /*滚动条的内阴影*/ border-radius: 10px; /*滚动条的圆角*/ background-color: rgba(144,147,153,.3); /*滚动条的背景颜色*/ } .info::-webkit-scrollbar-track { box-shadow: 0px 1px 3px #071e4a inset; /*滚动条的背景区域的内阴影*/ border-radius: 10px; /*滚动条的背景区域的圆角*/ background-color: #071e4a; /*滚动条的背景颜色*/ } /* .gui-yAxis{ position: absolute; height: 100%; border: solid 1px #1ba5fa; } */ </style>