zoukankan      html  css  js  c++  java
  • Gantt/BTS 生产计划电子看板甘特图

    Gantt/BTS 生产计划电子看板甘特图

    前言

    参考:https://www.freecodecamp.org/news/create-gantt-chart-using-css-grid/

    “甘特图是一种用于说明项目进度的条形图。该图表在纵轴上列出了要执行的任务,在横轴上列出了时间间隔。图中水平条的宽度显示了每项活动的持续时间。” – 维基百科

    成品

    image

    计算思路

    首先生成 7:00 - 6:00 24小时时间表头

    generateTimeRange () {
          // let h1 = parseInt(start.substring(0, 2))
          let timeRange = []
          for (let i = 7; i < 24; i++) {
            timeRange.push((i < 10 ? '0' + i : i) + ':' + '00')
            this.timeRangeOrigin.push(i)
          }
          for (let i = 0; i < 7; i++) {
            timeRange.push((i < 10 ? '0' + i : i) + ':' + '00')
            this.timeRangeOrigin.push(i)
          }
          return timeRange
        },
    

    如第一条Item,30和0这两个条状图像,时间范围分别是 7:40 - 8:12 和 7:30 - 8:30

    如何让条状图形正好偏移到时间点呢?

    首先需要一个存储所以时间的数组,为了方便查找,里面的数据大概为: [7,8,9,10,11 .... 6]

    以第二条为例:

    180 这一条的起始时间为 2021-06-03 08:22:46 - 2021-06-03 11:49:15

    我们先来计算宽度,这个180该多长:

    let width = ((endIdx - startIdx) === 0 ? 1 : (endIdx - startIdx)) * this.itemWidth
    

    endIdx 和 startIdx 为结束时间的分钟在数组中的下标,itemWidth为每个单元格的宽度

    那么上面的时间区间就是 (4 - 1) * 150 大约三个单元格的宽度

    那么再进行时间偏移

    180 的起始时间是8点,也就是需要跳跃7这个单元格到8,分钟时22分,那么算出偏移量

    (单元格宽度 / 60) * 分钟数 = 偏移量

     getOffset (minute) {
          return (this.itemWidth / 60) * minute
        },
    

    那么最后还要处理一下宽度,这个时候的结束时间位置应该时不正确的。

          let style = '' + ((width - this.getOffset(parseInt(m1)) + this.getOffset(parseInt(m2))) - this.itemWidth) + 'px;'
    
    

    最终宽度为: ((宽度 - 左偏移量 ) + 右偏移量) - 一个单元格宽度

    完整计算如下:

     getBarStyleVersion2 (flag, startTime, endTime) {
          let s = this.getMinutes(this.getTimestamp(startTime))
          let h1 = parseInt(s.substring(0, 2))
          let m1 = s.substring(s.indexOf(':') + 1, s.indexOf(':') + 3)
          let m2
          let h2
          if (endTime !== null) {
            let e = this.getMinutes(this.getTimestamp(endTime))
            h2 = parseInt(e.substring(0, 2))
            m2 = e.substring(s.indexOf(':') + 1, e.indexOf(':') + 3)
          } else {
            h2 = h1
            m2 = m1
          }
          let temp
          if (h1 > h2) {
            temp = h1
            h1 = h2
            h2 = temp
          }
          let startIdx = this.getTimeIdx(h1)
    
          let endIdx = this.getTimeIdx(h2) + 1
          // 计算长度
          // // console.log(startIdx)
          // // console.log(endIdx)
          // // console.log('w:' + ((endIdx - startIdx) === 0 ? 1 : (endIdx - startIdx)) * this.itemWidth)
    
          let width = ((endIdx - startIdx) === 0 ? 1 : (endIdx - startIdx)) * this.itemWidth
          // console.log('offset:' + this.getOffset(parseInt(m1)))
          let marginLeft = 0
    
          if (startIdx > 0) {
            marginLeft = (this.itemWidth * startIdx) + this.getOffset(parseInt(m1))
          } else {
            marginLeft = this.getOffset(parseInt(m1))
          }
    
          let style = '' + ((width - this.getOffset(parseInt(m1)) + this.getOffset(parseInt(m2))) - this.itemWidth) + 'px;'
          // 计算margin
          style += 'margin-left:' + marginLeft + 'px;'
          // 计算偏移
    
          // console.log('m1: -> ' + m1)
          // console.log('w: -> ' + this.itemWidth)
          // // console.log('m2: -> ' + m2)
          // // console.log(s)
          if (flag === 0) {
            style += 'background-color:#4F97A3;'
          } else {
            style += 'background-color:#0E4D92;'
          }
          return style
        },
        getOffset (minute) {
          return (this.itemWidth / 60) * minute
        },
    

    时间轴

    就是图中的绿色竖线,代表当前时间。

    首先一个DIV

    然后生成样式:

        getNowLine () {
          let styles = 'border:1px dashed green;height: 900px; 1px; position: fixed;z-index:999;'
          let now = this.getMinutes(Date.parse(new Date()))
          let m1 = parseInt(now.substring(0, 2))
          let s1 = parseInt(now.substring(now.indexOf(':') + 1, now.indexOf(':') + 3))
          let idx = this.getTimeIdx(m1)
    
          styles += 'margin-left:' + ((this.itemWidth * (idx + 1)) + (150 - (60 - this.getOffset(s1)))) + 'px'
          // console.log(idx)
          return styles
        }
    

    偏移量计算为 (单元格长度 * (小时数下标 + 1)) + (左侧固定栏宽度 - (60分钟 - 分钟数下标偏移量))

  • 相关阅读:
    由后序遍历序列和中序遍历序列确定二叉树
    由先序遍历序列和中序遍历序列确定二叉树
    EBR-TLV数据格式
    埃利斯(A.Ellis)ABCDE情绪管理理论
    马斯洛需求层次理论
    【Linux命令】find命令
    Windows核心编程——动态库和静态库
    C++Socket编程—socket网络模型之事件选择模型模型
    C++Socket编程—socket网络模型之异步选择模型
    C++Socket编程—socket网络模型之select模型
  • 原文地址:https://www.cnblogs.com/yangchaojie/p/14846292.html
Copyright © 2011-2022 走看看