当前位置: 首页 > article >正文

vue使用html实现的一个项目进度图

vue使用html实现的一个项目进度图

比如一个项目,可能对应多个不同的时间阶段,需要单独显示。如下图。那么echart和一些其他进度组件,实现起来就比较麻烦,甚至echart无法实现这么好的效果。于是就自己写了一个。
需求是:一个项目需要显示多个阶段,并且每个阶段都要一样的渐变色,并且按照日期显示在准确的比例位置

效果图:

在这里插入图片描述
对比echart实现的效果
在这里插入图片描述

这个echart的原理是用坐标,将月份视为x坐标,那么比如mar有数据,jun有数据,那么就会出现这么一段,但是他无法实现精准的显示,比如我一个时间是3月5日,他不能按比例显示在正确的位置

再对比另一个echart效果
在这里插入图片描述

这个echart的原理是先显示带颜色的部分,然后在用一个和echart背景色相同的,长度为从0到这个带颜色部分的起点位置的bar盖住带颜色的bar就形成了这个效果,那么可见。渐变色达不到效果,圆角达不到效果,而且要实现多个,这个数据结构会很复杂。
综上
还是决定自己用html实现一个,设计一个算法,显示再正确的比例位置

再看一下效果图

在这里插入图片描述

html
<div class="chart-box">
                          <div class="chart-top">
                            <div class="chart-top-item" v-for="(item,index) in headerData" :style="{width:100/headerData.length+'%'}" :key="index">
                              <span class="chart-top-item-year">{{ item.year||'' }}</span>
                              <span class="chart-top-item-year2">{{ item.lable }}</span>
                            </div>
                          </div>
                          <div class="chart-bot">
                            <div class="chart-line" :style="{minWidth:headerData.length*80+'px',width:'100%'}" v-for="(item,index) in productData" :key="index">
                              <el-tooltip  effect="dark" placement="top" v-for="(ite,idx) in item.items" :key="idx">
                                <template #content>{{ite.name||'--'}}<br/>开始日期:{{ite.startDateStr}}<br/>结束日期:{{ite.endDateStr}}</template>
                                <div class="chart-line-item"  :style="{left:ite.st+(100/headerData.length/2)+'%',width:(ite.et-ite.st)?(ite.et-ite.st)+'%':'',minWidth:'20px'}"></div>
                              </el-tooltip>
                              <div class="chart-line-split" v-for="(it,ix) in headerData" :style="{left:(ix*(100/headerData.length)+100/headerData.length/2)+'%'}" :key="ix"></div>
                            </div>
                          </div>
                        </div>
scss
.chart-box{
    width: 100%;
    height: calc(100% - 0px);
    // border:1px solid #333;
    overflow-x: scroll;
    /* 设置滚动条的大小 */
    &::-webkit-scrollbar {
        width: 3px; 
        height: 5px; 
    }
    /* 设置滚动条可拖动滑块的样式 */
    &::-webkit-scrollbar-thumb {
        border-radius: 5px;
        background: rgba(226, 232, 240, 1);
    }
    /* 设置外层轨道的样式 */
    &::-webkit-scrollbar-track {
        border-radius: 0;
        background: #fff;
    }
    box-sizing: content-box;
    display: flex;
    flex-direction: column;
    // padding: 5px 0 0;
    .chart-top{
      width: 100%;
      display: flex;
      .chart-top-item{
        min-width: 80px !important;
        height: 50px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: rgb(76,73,72);
        position: relative;
        // border-top: 1px solid rgb(76,73,72);
        font-weight: bolder;
        &::before{
          content: '';
          display: block;
          width: 8px;
          height: 8px;
          border-radius: 50%;
          background-color: rgb(76,73,72);
          position: absolute;
          top: 52%;
          left: 50%;
          transform: translate(-52%,-50%);
        }
        &:after{
          content: '';
          display: block;
          width: 100%;
          height: 0px;
          border-top: 2px solid rgb(76,73,72);
          position: absolute;
          top: 52%;
          transform: translateY(-52%);
          left: 0;
        }

        .chart-top-item-year{
          display: block;
          position: absolute;
          top: 10%;
          left: 50%;
          transform: translateX(-50%);
        }
        .chart-top-item-year2{
          position: absolute;
          top: 55%;
          left: 50%;
          transform: translateX(-55%);
        }
      }
    }
    .chart-bot{
      width: 100%;
      display: flex;
      flex-direction: column;
      flex: 1;
      .chart-line{
        width: 100%;
        position: relative;
        display: flex;
        align-items: center;
        height: 40px;
        .chart-line-split{
          width: 0.1px;
          height: 100%;
          // border-right: 0.1px solid #ccc;
          background: #ccc;
          position: absolute;
          top: 0;
          transform: translateX(-50%);
          z-index: 1;
        }
        .chart-line-item{
          border-radius: 10px;
          height: 20px;
          position: absolute;
          top: 50%;
          transform: translateY(-50%);
          background: linear-gradient(to right, rgba(251,147,139,1), rgba(179,13,0,1));
          cursor: pointer;
          z-index: 2;
        }
      }
    }
  }
js

在这里插入图片描述

数据由表头和内容构成,如图:
1、表头是需要过滤的,比如23-26年之间都没有数据,那么就这之间的数据就全部不显示,只显示有数据的部分。
2、但是为了避免头部和尾部显示不全,又在已有表头数据的基础上,分别增加了一个节点。
3、为了便于区分,给每个这一年第一次出现的月份增加了一个年份的标记

数据

headerData.value = [
{
“lable”: “Sep”,
“value”: “2023-09”,
“year”: 2023,
“color”: “rgba(255,154,146,1)”,
“isfirst”: true
},
{
“lable”: “Oct”,
“value”: “2023-10”
},
{
“lable”: “Jan”,
“value”: “2024-01”,
“year”: 2024,
“color”: “rgba(255,103,92,1)”,
“isfirst”: true
},
{
“lable”: “Aug”,
“value”: “2024-08”
},
{
“lable”: “Sep”,
“value”: “2024-09”
},
{
“lable”: “Feb”,
“value”: “2025-02”,
“year”: 2025,
“color”: “rgba(255,103,92,1)”,
“isfirst”: true
},
{
“lable”: “Mar”,
“value”: “2025-03”
},
{
“lable”: “Apr”,
“value”: “2025-04”
},
{
“lable”: “Jun”,
“value”: “2025-06”
},
{
“lable”: “Jul”,
“value”: “2025-07”
},
{
“lable”: “Sep”,
“value”: “2025-09”
},
{
“lable”: “Jan”,
“value”: “2026-01”,
“year”: 2026,
“color”: “rgba(255,103,92,1)”,
“isfirst”: true
},
{
“lable”: “Feb”,
“value”: “2026-02”
},
{
“lable”: “Mar”,
“value”: “2026-03”
}
]

productData.value=[
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 643109350596677,
“category”: “test”,
“name”: “activity1”,
“description”: “activity1activity1”,
“organizer”: “test”,
“enabled”: true,
“items”: [
{
“name”: “item1”,
“startDate”: “2024-01-01 00:00:00”,
“startDateStr”: “2024-01-01”,
“endDate”: “2024-01-03 00:00:00”,
“endDateStr”: “2024-01-03”,
“st”: 14.516129032258066,
“et”: 14.976958525345623
},
{
“name”: “items3”,
“startDate”: “2025-02-12 00:00:00”,
“startDateStr”: “2025-02-12”,
“endDate”: “2025-02-13 00:00:00”,
“endDateStr”: “2025-02-13”,
“st”: 38.47926267281106,
“et”: 38.70967741935484
},
{
“name”: “item4”,
“startDate”: “2024-08-02 00:00:00”,
“startDateStr”: “2024-08-02”,
“endDate”: “2024-09-30 00:00:00”,
“endDateStr”: “2024-09-30”,
“st”: 21.88940092165899,
“et”: 35.483870967741936
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 646198382841925,
“category”: “test”,
“name”: “activity2”,
“description”: “activity2”,
“organizer”: “activity2”,
“enabled”: true,
“items”: [
{
“name”: “子事项”,
“startDate”: “2025-06-13 00:00:00”,
“startDateStr”: “2025-06-13”,
“endDate”: “2025-07-23 00:00:00”,
“endDateStr”: “2025-07-23”,
“st”: 60.13824884792627,
“et”: 69.58525345622121
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 646273017249861,
“category”: “test”,
“name”: “activity3”,
“description”: “activity3”,
“organizer”: “activity3”,
“enabled”: true,
“items”: [
{
“name”: “子事项1”,
“startDate”: “2025-02-01 00:00:00”,
“startDateStr”: “2025-02-01”,
“endDate”: “2025-02-28 00:00:00”,
“endDateStr”: “2025-02-28”,
“st”: 35.944700460829495,
“et”: 42.16589861751152
},
{
“name”: “子事项2”,
“startDate”: “2025-03-01 00:00:00”,
“startDateStr”: “2025-03-01”,
“endDate”: “2025-03-31 00:00:00”,
“endDateStr”: “2025-03-31”,
“st”: 43.08755760368664,
“et”: 50
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 645519724691525,
“category”: “qqqqq”,
“name”: “qqqqq”,
“description”: “qqqqq”,
“organizer”: “qqqqq”,
“enabled”: true,
“items”: [
{
“name”: “123”,
“startDate”: “2023-10-03 00:00:00”,
“startDateStr”: “2023-10-03”,
“endDate”: “2025-09-25 00:00:00”,
“endDateStr”: “2025-09-25”,
“st”: 7.8341013824884795,
“et”: 77.1889400921659
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 646201372651589,
“category”: “qqqqq”,
“name”: “activity2”,
“description”: “activity2”,
“organizer”: “activity2”,
“enabled”: true,
“items”: [
{
“name”: “子事项1”,
“startDate”: “2025-04-17 00:00:00”,
“startDateStr”: “2025-04-17”,
“endDate”: “2025-04-30 00:00:00”,
“endDateStr”: “2025-04-30”,
“st”: 53.91705069124424,
“et”: 56.91244239631337
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 645964431528005,
“category”: “广泛大概”,
“name”: “广泛大概”,
“description”: “广泛大概”,
“organizer”: “广泛大概”,
“enabled”: true,
“items”: [
{
“name”: “子圣西昂”,
“startDate”: “2026-01-15 00:00:00”,
“startDateStr”: “2026-01-15”,
“endDate”: “2026-02-16 00:00:00”,
“endDateStr”: “2026-02-16”,
“st”: 82.02764976958525,
“et”: 89.40092165898618
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 646201454104645,
“category”: “所发生的d”,
“name”: “的法国队发给”,
“description”: “d风格豆腐干”,
“organizer”: “古典风格d”,
“enabled”: true,
“items”: [
{
“name”: “”,
“startDate”: “2025-02-19 00:00:00”,
“startDateStr”: “2025-02-19”,
“endDate”: “2025-03-21 00:00:00”,
“endDateStr”: “2025-03-21”,
“st”: 40.09216589861751,
“et”: 47.69585253456221
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 646274932224069,
“category”: “测试测试”,
“name”: “测试测试”,
“description”: “测试测试”,
“organizer”: “测试测试”,
“enabled”: true,
“items”: []
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 649139617321029,
“category”: “Test2月27”,
“name”: “Test”,
“description”: “Test”,
“organizer”: “Test”,
“enabled”: true,
“items”: [
{
“name”: “Test”,
“startDate”: “2025-02-01 00:00:00”,
“startDateStr”: “2025-02-01”,
“endDate”: “2025-03-31 00:00:00”,
“endDateStr”: “2025-03-31”,
“st”: 35.944700460829495,
“et”: 50
},
{
“name”: “Test2”,
“startDate”: “2025-02-02 00:00:00”,
“startDateStr”: “2025-02-02”,
“endDate”: “2025-04-01 00:00:00”,
“endDateStr”: “2025-04-01”,
“st”: 36.175115207373274,
“et”: 50.23041474654378
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 649410891395141,
“category”: “Test2.28”,
“name”: “test”,
“description”: “test”,
“organizer”: “test”,
“enabled”: true,
“items”: [
{
“name”: “test”,
“startDate”: “2025-02-28 00:00:00”,
“startDateStr”: “2025-02-28”,
“endDate”: “2025-03-01 00:00:00”,
“endDateStr”: “2025-03-01”,
“st”: 42.16589861751152,
“et”: 43.08755760368664
},
{
“name”: “test2”,
“startDate”: “2025-03-01 00:00:00”,
“startDateStr”: “2025-03-01”,
“endDate”: “2025-03-02 00:00:00”,
“endDateStr”: “2025-03-02”,
“st”: 43.08755760368664,
“et”: 43.31797235023042
},
{
“name”: “”,
“startDate”: “2025-02-19 00:00:00”,
“startDateStr”: “2025-02-19”,
“endDate”: “2025-02-20 00:00:00”,
“endDateStr”: “2025-02-20”,
“st”: 40.09216589861751,
“et”: 40.322580645161295
}
]
},
{
“isShowFolder”: true,
“activityFolders”: null,
“id”: 649451403628613,
“category”: “A1”,
“name”: “A2”,
“description”: “D1”,
“organizer”: “O1”,
“enabled”: true,
“items”: []
}
]


http://www.kler.cn/a/571389.html

相关文章:

  • C语言的那点事第十二篇:动态内存分配、内存泄漏与野指针的深度剖析。
  • ==和===在不同场景下的具体区别是什么?
  • 【每日八股】MySQL篇(九):优化
  • golang程序员如何3天完成python学习
  • 【区块链 + 智慧政务】科大讯飞:省级一体化区块链平台 | FISCO BCOS 应用案例
  • 软件试用 防破解 防软件调试(C# )
  • Excel的行高、列宽单位不统一?还是LaTeX靠谱
  • 用matplotlib构建BI看板:Superset插件开发实战
  • 高并发场景下的数据库优化
  • 机器学习的半监督学习,弱监督学习,自监督学习
  • Linux : 环境变量
  • 【C语言5】函数:库函数、自定义函数、形参和实参、return语句、数组做函数参数、嵌套调用和链式访问、声明和定义
  • 剑指 Offer II 040. 矩阵中最大的矩形
  • PPT 小黑第36套
  • 建筑兔零基础自学python记录37|编程练习3
  • HTML label 标签使用
  • HttpServletRequest、ServerHttpRequest 和 ServerWebRequest作用详解
  • 【随手笔记】利尔达NB模组
  • jenkins流程概述
  • 计算机中的架构