最近在做大屏展示,其中一个需求是展示生产过程中投料情况,效果类似甘特图。
思路: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>