TS使用highcharts甘特图,滚动放大

<template>
  <div id="container1">
    <div ref="contais" id="containerEMS"></div>
  </div>
</template>

<script>
// 导入chart组件

import Highcharts from 'highcharts'
import gantt from 'highcharts/modules/gantt'
import moment from 'moment'
// import { showGanttData, projectShowAll } from '../../serviceAPIs/service'
import { deepClone } from '@src/utils'
gantt(Highcharts)
export default {
  props: {
    showGanttData: {
      type: Array,
      require: true
    },
    projectShowAllData: {
      type: Array,
      require: true
    }
  },
  watch: {
    allData(val) {},
    projectShowAllData(newVal) {
      if (newVal) {
        this.getGantterData(this.showGanttData, this.projectShowAllData)
      }
    },
    immediate: true,
    deep: true
  },

  data() {
    return {
      // 存放二级进度数组
      secondProgress: [],
      // 存放一级进度
      firstProgress: [],
      resultArr: [],
      trueTimeDataThree: [],
      // 处理第一层数据
      oneSeriesData: [],
      // 处理第二层数据
      twoSeriesData: [],
      // 处理第三层数据
      threeSeriesData: [],
      // 存放甘特图数据
      seriesData: [],
      allData: []
    }
  },
  methods: {
    async getGantterData(res, productData) {
      // console.log('甘特图刷新', res, productData)
      this.allData = productData

      // 再一级加入进度
      this.calculateProgress(res, productData)
      // 在一级钟加入三级最大实际结束时间
      this.computingTime(res, productData)
      // 渲染甘特图
      this.HighchartsData()
    },
    // 计算二级进度
    calculateProgress(res, productData) {
      // 计算二级进度
      productData.forEach((item) => {
        item.children.forEach((item2) => {
          let secondProgressTotal = 0
          let secondProgressTotal2 = 0
          let projectCompletionDegree = 0
          let plancompletion = 0
          let a = 0
          let b = 0
          // 计算工作计划的进度
          if (item2.planName == '工作计划') {
            item2.children.forEach((item3) => {
              // 工作计划所有进度加起来的总和secondProgressTotal
              secondProgressTotal += item3.completionDegree
            })
            // 工作计划进度,总和除以工作计划下的数组长度
            projectCompletionDegree = (secondProgressTotal / item2.children.length).toFixed(1)
            this.secondProgress.push({
              projectName: item2.projectName,
              id: item2.id,
              mainProjectName: item.projectName,
              secondProgressrate: projectCompletionDegree
            })
          }
          // 计算物料计划的进度
          if (item2.projectName == '物料计划') {
            item2.children.forEach((item4) => {
              // 入库量大于计划量
              if (item4.scheduledReceipt > item4.planQuantity) {
                item4.scheduledReceipt = item4.planQuantity
              }
              a += item4.scheduledReceipt
              b += item4.planQuantity
              // 给物料计划加进度
              this.$set(item4, 'completionDegree', Number(((item4.scheduledReceipt / item4.planQuantity) * 100).toFixed(1)))
            })

            this.planCompletionDegree = ((a / b) * 100).toFixed(1)
            this.secondProgress.push({
              projectName: item2.projectName,
              id: item2.id,
              mainProjectName: item.projectName,
              secondProgressrate: this.planCompletionDegree
            })
          }
        })
      })
      this.calculatingProgressOperations(res, productData)
    },
    // 计算一级完成了率
    calculatingProgressOperations(res, productData) {
      // 往三级数据塞二级进度
      productData.forEach((item) => {
        item.children.forEach((item2) => {
          this.secondProgress.forEach((second) => {
            if (second.id == item2.id) {
              this.$set(item2, 'twoAmount', Number(second.secondProgressrate))
            }
          })
        })
      })
      let oneProgressTotal = 0
      let firstProgressrate = 0
      // 计算一级完成率
      productData.forEach((item) => {
        oneProgressTotal = 0
        item.children.forEach((item2) => {
          if (item.id == item2.parentId) {
            // 二级进度不为NaN,相加
            if (Object.is(item2.twoAmount, NaN)) {
            } else {
              oneProgressTotal += item2.twoAmount
            }
            // 一级进度,工作计划,和物理计划相加/2得出
            firstProgressrate = (oneProgressTotal / 2).toFixed(1)
            this.firstProgress.push({
              projectName: item.projectName,
              firstProgressrate: firstProgressrate
            })
          }
          item2.children.forEach((item3) => {
            this.$set(item2, 'name', item3.planName)
          })
        })
      })
      // 塞入计算后的一级进度
      productData.forEach((item) => {
        this.firstProgress.forEach((first) => {
          if (first.projectName == item.projectName) {
            this.$set(item, 'oneAmount', Number(first.firstProgressrate))
          }
        })
      })
      // console.log('productData', productData)
    },
    // 计算完成时间
    computingTime(res, productData) {
      let EndTime = []
      let time1 = []
      let time2 = 0
      // 找出三级的最大实际完成时间
      productData.forEach((item) => {
        item.children.forEach((item2) => {
          time1 = []
          time2 = 0

          let threeId = ''
          let name = ''
          item2.children.forEach((item3) => {
            // 实际结束实际转为数字
            if (item3.actualEndTime == null) {
              item3.actualEndTime = 0
            } else {
              item3.actualEndTime = moment(item3.actualEndTime).valueOf()
            }
            time1.push(item3.actualEndTime)
            time2 = Math.max(...time1)
            threeId = item3.projectId
          })
          this.resultArr.push({
            projectName: item.projectName,
            planName: item2.projectName,
            actualEndTime: time2,
            planId: threeId
          })
        })
      })
      // 往二级塞三级最大实际结束时间
      productData.forEach((item) => {
        item.children.forEach((item2) => {
          this.resultArr.forEach((item3) => {
            if (item2.parentId == item3.planId) {
              this.$set(item2, 'threeEndTime', item3.actualEndTime)
            }
          })
        })
      })
      this.computingTimeOptions(res, productData)
    },
    // 往一级塞入三级最大实际结束时间
    computingTimeOptions(res, productData) {
      let oneData = []
      let oneData2 = 0
      let oneDataArr = []
      productData.forEach((item) => {
        item.children.forEach((item2) => {
          oneData = []
          oneData2 = 0
          let parent = ''
          item2.children.forEach((item3) => {
            if (item3.actualEndTime == null) {
              item3.actualEndTime = 0
            } else {
              item3.actualEndTime = moment(item3.actualEndTime).valueOf()
            }
            oneData.push(item3.actualEndTime)
            oneData2 = Math.max(...oneData)
            parent = item3.projectId
          })
          oneDataArr.push({
            endtime: oneData2,
            planName: item2.projectName,
            projectName: item.projectName,
            planId: parent
          })
        })
      })
      // 往一级塞入三级最大实际结束时间
      productData.forEach((item) => {
        item.children.forEach((item2) => {
          oneDataArr.forEach((item3) => {
            if (item2.parentId == item3.planId) {
              this.$set(item, 'trueactualEndTime', item3.endtime)
            }
          })
        })
      })

      this.processingData(res, productData)
      this.insertGanttData()
    },
    // 处理甘特图所需数据,存放在数组中
    processingData(res, productData) {
      this.oneSeriesData = []
      this.twoSeriesData = []
      this.threeSeriesData = []
      // 往甘特图的series塞需要的数据
      productData.forEach((item) => {
        this.oneSeriesData.push({
          trueactualEndTime: item.trueactualEndTime,
          oneAmount: Object.is(item.oneAmount, NaN) ? 0 : item.oneAmount,
          projectName: item.projectName,
          plannedStartTime: item.plannedStartTime,
          plannedEndTime: item.plannedEndTime,
          personResponsible: item.personResponsible,
          id: item.id
        })
        item.children.forEach((item2, index, array1) => {
          this.twoSeriesData.push({
            threeEndTime: item2.threeEndTime,
            twoAmount: item2.twoAmount,
            oneid: item.id,
            projectName: item2.projectName ? item2.projectName : item2.planName,
            plannedStartTime: item2.plannedStartTime,
            plannedEndTime: item2.plannedEndTime,
            // actualStartTime: item2.actualStartTime,
            // actualEndTime: item2.actualEndTime,
            personResponsible: item2.personResponsible,
            id: item2.id,
            dependency: array1.length - 1 > index ? array1[index + 1].id : ''
          })
          item2.children.forEach((item3, index2, array2) => {
            this.threeSeriesData.push({
              twoprojectName: item2.projectName,
              twoid: item2.id,
              planName: item3.planName,
              plannedStartTime: item3.plannedStartTime,
              plannedEndTime: item3.plannedEndTime,
              actualStartTime: item3.actualStartTime,
              actualEndTime: item3.actualEndTime,
              personResponsible: item3.personResponsible,
              state: item3.state,
              completionDegree: item3.completionDegree,
              id: item3.id,
              dependency: array2.length - 1 > index2 ? array2[index2 + 1].id : ''
            })
          })
          // 2end
        })
        // 3end
      })
    },
    // 往series塞数据
    insertGanttData() {
      this.seriesData = []
      // 第一次
      this.oneSeriesData.forEach((item) => {
        this.seriesData.push({
          name: item.projectName + '&' + item.id,
          id: item.id,
          start:
            moment(item.plannedStartTime)
              .startOf('days')
              .valueOf() + 30000000,
          end: moment(item.plannedEndTime)
            .endOf('day')
            .valueOf(),
          owner: item.personResponsible,
          color: 'rgba(128, 128, 128,0.3)',
          dataLabels: {
            align: 'center',
            style: {
              textOutline: 'none'
              // 去除描边效果
            },
            color: 'rgb(196, 245, 229)',
            formatter: function(e, options) {
              if (item.oneAmount > 0 && item.oneAmount <= 100) {
                return '项目总进度:' + item.oneAmount + '%'
              } else {
                return '未开始'
              }
            }
          },
          completed: {
            amount: item.oneAmount / 100,
            // fill: 'red'
            fill: this.getclolrOne2(moment(item.plannedEndTime).valueOf(), item.trueactualEndTime, item.oneAmount)
          }
        })
      })
      // 第二次
      this.twoSeriesData.forEach((item) => {
        // console.log(item
        this.seriesData.unshift({
          name: (item.projectName ? item.projectName : item.planName) + '&' + item.id,
          // name: item.id,
          id: item.id,
          dependency: item.oneid,
          parent: item.oneid,
          start:
            moment(item.plannedStartTime)
              .startOf('days')
              .valueOf() + 30000000,
          end: moment(item.plannedEndTime)
            .endOf('day')
            .valueOf(),
          owner: item.personResponsible,
          collapsed: true,
          color: 'rgba(128, 128, 128,0.3)',
          dataLabels: {
            align: 'center',
            style: {
              textOutline: 'none' // 去除描边效果
            },
            color: 'rgb(247, 242, 199)',
            formatter: function(e, options) {
              if (item.twoAmount > 0 && item.twoAmount <= 100) {
                return '分组进度:' + item.twoAmount + '%'
              } else if (item.twoAmount > 100) {
                return '分组进度:' + item.twoAmount + '% (超量)'
              } else {
                return '未开始'
              }
            }
          },
          completed: {
            amount: item.twoAmount / 100,
            // fill:'green'
            fill: this.getclolrTwo2(moment(item.plannedEndTime).valueOf(), item.threeEndTime, item.twoAmount)
          }
        })
      })
      // 第三次
      this.threeSeriesData.forEach((item) => {
        this.seriesData.unshift({
          name: (item.twoprojectName == '物料计划' ? item.planName : item.planName + '-' + item.personResponsible) + '&' + item.id,
          id: item.id,
          dependency: item.twoid,
          parent: item.twoid,
          start: moment(item.plannedStartTime).valueOf(),
          end: moment(item.plannedEndTime)
            .endOf('day')
            .valueOf(),
          owner: item.personResponsible,
          color: 'rgba(128, 128, 128,0.3)',
          dataLabels: {
            align: 'center',
            style: {
              textOutline: 'none' // 去除描边效果
            },
            formatter: function(e, options) {
              if (item.state === 0) {
                return '未开始'
              } else {
                return '进度:' + item.completionDegree + '%'
              }
            }
          },
          completed: {
            amount: item.completionDegree / 100,
            // fill:'yellow'
            fill: this.getclolrThree2(moment(item.plannedEndTime).valueOf(), item.actualEndTime ? moment(item.actualEndTime).valueOf() : moment(item.plannedEndTime).valueOf(), item.completionDegree)
          }
        })
      })
    },
    HighchartsData() {
      var today = new Date(),
        day = 1000 * 60 * 60 * 24,
        // Utility functions
        dateFormat = Highcharts.dateFormat,
        defined = Highcharts.defined,
        isObject = Highcharts.isObject,
        reduce = Highcharts.reduce
      // Set to 00:00:00:000 today
      today.setUTCHours(0)
      today.setUTCMinutes(0)
      today.setUTCSeconds(0)
      today.setUTCMilliseconds(0)
      today = today.getTime()

      // console.log('************************:', this.seriesData)

      // 获取图表容器
      var container = document.getElementById('containerEMS')
      var chart = Highcharts.ganttChart(container, {
        series: [
          {
            name: '项目',
            borderColor: 'none',
            data: this.seriesData,
            dataLabels: {
              color: '#fff',
              borderColor: 'red'
              //  borderWidth:10
            },
            events: {
              legendItemClick: function(event) {}
            }
          }
        ],
        mapNavigation: {
          enabled: true,
          enableButtons: false
        },
        tooltip: {
          style: {
            zIndex: '99999'
          },
          followPointer: true,
          pointFormatter: function() {
            var point = this,
              format = '%e. %b',
              options = point.options,
              completed = options.completed,
              amount = isObject(completed) ? completed.amount : completed,
              status = (amount || 0) * 100 + '%',
              lines
            lines = [
              {
                value: point.name.split('&')[0],
                style: 'font-weight: bold;'
              },
              {
                title: '开始日期',
                value: moment(point.options.start).format('YYYY-MM-DD')
              },
              {
                visible: !options.milestone,
                title: '结束日期',
                value: moment(point.options.end).format('YYYY-MM-DD')
              },
              {
                title: '进度',
                value: status
              }
              // {
              //   title: '负责人',
              //   value: options.owner || 'unassigned'
              // }
            ]
            return reduce(
              lines,
              function(str, line) {
                var s = '',
                  style = defined(line.style) ? line.style : 'font-size: 0.8em;'
                if (line.visible !== false) {
                  s = '<span style="' + style + '">' + (defined(line.title) ? line.title + ': ' : '') + (defined(line.value) ? line.value : '') + '</span><br/>'
                }
                return str + s
              },
              ''
            )
          }
        },

        credits: {
          enabled: false
        },
        accessibility: {
          enabled: false
        },
        chart: {
          events: {
            selection: function(event) {
              // 阻止默认选中行为  选中下方拖动然后右边滚动条也跟着动
              event.preventDefault()
            }
          },
          scrollablePlotArea: {
            minHeight: this.heightFnc(),
            //   opacity: 1,
            opacity: 1
            //   scrollPositionY: 0
          },
          // height: this.heightFnc(), // 16:9 ratio
          // height: 70 + '%', // 16:9 ratio
          alignThresholds: true,

          backgroundColor: {
            linearGradient: [0, 0, 1, 280],
            stops: [[0, 'rgba(33, 65, 166,1)'], [1, 'rgba(33, 65, 166,0)']]
          },
          //  backgroundColor: ' linear-gradient(to top, red, green)',
          // plotBackgroundColor: 'rgba(4, 181, 178,0.1)',
          panning: true,
          panKey: 'shift'
        },
        resetZoomButton: {
          position: {},
          relativeTo: 'plot',
          theme: {
            states: {
              // 选择时的框子色
              hover: {
                stroke: '#1e3a97',
                'stroke-width': 1
              }
            }
          }
        },
        yAxis: [
          {
            labels: {
              formatter: function(e) {
                return '<span>' + this.value.split('&')[0] + "<p style='color:transparent;width:0px;display:none'>" + this.value.split('&')[1] + '</p>' + '</span>' // 设置字体颜色
              },
              //  this.value.split('&')[0]
              style: {
                color: '#04b5b2'
              }
            },
            gridLineWidth: 0,
            tickColor: 'rgba(4, 181, 178, 0.3)',
            lineColor: 'rgba(4, 181, 178, 0.3)',
            min: 0,
            max: null,
            uniqueNames: true,
            events: {
              click: function(e) {
                // 判断点击的位置是否在y轴上
                if (e.axis.userOptions.className === 'highcharts-yaxis') {
                  // 获取点击的坐标值
                  var chart = this.chart,
                    y = Math.round(chart.yAxis[0].toValue(e.chartY))

                  // 根据点击的坐标值进行相应的处理
                  // 例如展开或收起子任务
                  // ...
                }
              }
            }
          }
        ],

        xAxis: [
          {
            minTickInterval: 1000 * 60 * 60 * 24,
            min: today - 90 * day,

            max: today + 30 * day,

            tickColor: 'rgba(4, 181, 178, 0.3)',
            lineColor: 'rgba(4, 181, 178, 0.3)',
            tickWidth: 3,
            lineWidth: 1,

            labels: {
              format: `{value:%d}`,
              indentation: 20,
              padding: 1,
              style: {
                userSelect: 'none',
                color: '#04b5b2',
                fontSize: '13px',
                fontFamily: '微软雅黑'
              }
            }
          },
          {
            tickInterval: 31 * (24 * 3600 * 1000),
            tickWidth: 3,
            tickColor: 'rgba(4, 181, 178, 0.3)',
            lineColor: 'rgba(4, 181, 178, 0.3)',
            lineWidth: 1,
            labels: {
              // format: '{value: %Y年1 %W周}'
              format: '{value: %Y-%m}',
              style: {
                userSelect: 'none',
                color: '#04b5b2',
                fontWeight: 'bold',
                fontSize: '18px',
                fontFamily: '微软雅黑'
              }
            }
          }
        ]
      })
      // 监听鼠标滚轮事件
      if (container.addEventListener) {
        container.addEventListener('wheel', function(e) {
          // e.preventDefault() // 阻止默认滚动行为
          // 返出属性
          if (Object.keys(chart).length === 0) return
          if (e.ctrlKey) {
            // Y放大125 Y缩小-125
            var delta = e.deltaY || e.detail || e.wheelDelta // 获取滚动方向

            // 放大125,缩小-125
            // 向下放大0.9,向上缩小1.1
            var scale = delta < 0 ? 1.1 : 0.9 // 向上滚动放大,向下滚动缩小
            var xAxis = chart.xAxis[0]
            var min = xAxis.min
            var max = xAxis.max

            var newMin = min + ((max - min) * (1 - scale)) / 2
            var newMax = max - ((max - min) * (1 - scale)) / 2
            if (min < moment('2023-05-01').valueOf()) {
              if (e.ctrlKey) {
                var delta = e.deltaY
                var scale = delta < 0 ? 1.1 : 0.9
                var xAxis = chart.xAxis[0]
                var min = xAxis.min
                var max = xAxis.max

                var newMin = min + ((max - min) * (1 - scale)) / 2
                var newMax = max - ((max - min) * (1 - scale)) / 2
                if (scale == 0.9) {
                  xAxis.setExtremes(newMin, newMax)
                }
              }
            } else {
              xAxis.setExtremes(newMin, newMax)
            }
          } else {
          }
        })
      }
    },

    heightFnc() {
      let alldataInfo = []
      let oneData = []
      let twoData = []
      let threeData = []
      this.allData.forEach((item) => {
        oneData.push(item)
        item.children.forEach((item2) => {
          twoData.push(item)
          item2.children.forEach((item3) => {
            threeData.push(item3)
          })
        })
      })
      alldataInfo = oneData.concat(twoData, threeData)
      // return alldataInfo.length * 65
      let leng = alldataInfo.length * 65
      if (leng > 600) {
        return alldataInfo.length * 65
      } else {
        return 1200
      }
    },
    getclolrOne2(plannedEndTime, actualEndTime, state) {
      if (state == 100) {
        // 执行完成
        if (plannedEndTime >= actualEndTime) {
          // 没超时绿色
          return 'rgba(1, 178, 121,1)'
        } else if (plannedEndTime < actualEndTime) {
          // 实际结束实际和预计结束实际对必,超时就是
          // 红色
          return 'red'
        }
      } else {
        // 执行中
        // 橙色
        // return '#f35e03'
        // #9ccdc4'
        return '#1b9ff1'
      }
    },

    getclolrTwo2(plannedEndTime, actualEndTime, state) {
      if (state == 100) {
        // 执行完成
        if (plannedEndTime >= actualEndTime) {
          // 没超时绿色
          return 'rgba(1, 178, 121,1)'
        } else if (plannedEndTime < actualEndTime) {
          // 实际结束实际和预计结束实际对必,超时就是
          // 红色
          return 'red'
        }
      } else {
        // 执行中
        // 橙色
        // return '#f35e03'
        return '#1b9ff1'
      }
    },

    getclolrThree2(plannedEndTime, actualEndTime, state) {
      if (state == 100) {
        // 执行完成
        if (plannedEndTime >= actualEndTime) {
          // 没超时绿色
          return '#01b279'
        } else if (Number(plannedEndTime) < Number(actualEndTime)) {
          // 实际结束实际和预计结束实际对必,超时就是
          // 红色
          return 'red'
        }
      } else {
        // 执行中
        // 橙色
        // return '#f35e03'
        return '#1b9ff1'
      }
    }
  }
}
</script>

<style scoped>
#container1 {
  max-width: 100%;
  margin: 1em auto;
}
#containerEMS {
  max-width: 100%;
  height: 96%;
  margin: 0 auto;
}
.highcharts-axis-labels text:hover tspan {
  text-decoration: none !important;
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Highgantt 是用纯 JavaScript 编写的甘特图控件 主要优势(功能特点) browsers兼容性 Highstock 可以在所有的移动设备及电脑上的浏览器中使用,包括 iPhone,iPad 和 IE6 以上的版本。在 IOS 和 Android 系统中 Highstock 支持多点触摸功能,因而可以给您提供极致的用户体验。在现代的浏览器中使用 SVG 技术进行图形绘制,在低版本 IE 则使用 VML 进行图形绘制。 free非商业使用免费 在个人网站、学校网站及非盈利机构中使用 Highstock 完全不需要经过我们的许可,直接可以任意使用! 商业网站或网站,请查看我们的 使用协议及价格。 open开源 Highstock 最重要的特点之一就是:无论免费版还是付费版,你都可以下载源码并可以对其进行编辑。 基于开源社区我们可以第一时间获取用户的需求、Bug 修复及吸收社区贡献。 no-backend纯 JavaScript Highstock 完全基于 HTML5 技术,不需要再客户端安装任何插件,如 Flash 或 Java。此外你也不用配置任何服务端环境,不需要 PHP、Tomcat、ASP.NET 等,只需要两个 JS 文件即可运行。 chart-types图表种类丰富 Highstock 支持直线图、折线图、面积图、面积曲线图、柱形图、散点图、蜡烛图(OHLC)、K线图、标签图、面积范围图、柱形范围图等多种图表, 其中很多图表可以集成在同一个图形中形成混合图 config-syntax简单的配置语法 在 Highstock 中设置配置选项不需要任何高级的编程技术,所有的配置都是 JSON 对象,只包含用冒号连接的键值对、用逗号进行分割、用括号进行对象包裹。JSON 具有易于人阅读和编写,同时也易于机器解析和生成的特点。 动态交互性 Highstock 支持丰富交互性,在图表创建完毕后,可以用丰富的 API 进行添加、移除或修改数据列、数据点、坐标轴等操作。 结合 jQuery 的 ajax 功能,可以做到实时刷新数据、用户手动修改数据等功能,结合事件处理,可以做到各种交互功能。 范围选择器 在处理大数据集时,我们可能需要查看不同时间范围的数据。Highstock 提供了范围选择器,方便的用它来选择预设范围的时间,例如 1个月、一季度、1年等,你可以通过时间输入框来选择自己想要查看数据范围。 滚动条和导航器 通过滚动条和导航器可以更加直观的操作和查看特定范围的数据。 事件标记 通过添加标志数据列可以为数据相关的事件做标记和注释。 支持多坐标轴 多个数据进行对比这是非常常见的需求,Highstock 可以让你为每个类型的数据添加坐标轴,每个轴可以定义放置的位置,所有的设置都可以独立生效,包括旋转、样式设计和定位,当然也支持多个数据共用一个坐标轴。 tooltip数据提示框 当鼠标划过图形时,Highstock 可以将数据点或数据列的信息展示在提示框中,并且提示框会跟随用户的鼠标;我们做了大量工作,可以智能的显示离鼠标最近的点或被遮盖点的信息。 datetime时间轴 Highstock 对时间轴的处理非常智能,可以精确的计算出月、周、日、小时、分钟等时间刻度的位置。 data grouping数据分组与合并 如果数据集包含 10 万个,浏览器对每个点进行计算并渲染的话效率会非常低。Highstock 具有数据分类功能,可以以飞速的进行数据分组;放大至小范围的数据是会重新分组,因为你可以查看高度清晰的数据又不失效率和速度。 exporting导出和打印 Highstock 支持导出功能,用户可以一键导出 PNG、JPEG、PDF 或 SVG 文件,通过插件可以实现导出为 Excel 文件功能;另外,用户还可以从网页上直接打印图表。 zooming缩放和平移 除了通过滚动条或导航器控制放大和平移功能,你还可以通过鼠标和手指来进行这两个操作。 ajax方便加载外部数据 Highstock 的数据是 JavaScript 数组或对象,这些数据可以是本地的配置对象,独立的数据文件(JSON、CVS)甚至是不同的网站上定义。另外,这些数据可以用任何形式处理好并加载到 Highstock 中。
下面是一个使用 React 和 Highcharts甘特图的示例代码: ```jsx import React, { Component } from 'react'; import Highcharts from 'highcharts'; import HighchartsGantt from 'highcharts/modules/gantt'; import HighchartsMore from 'highcharts/highcharts-more'; import moment from 'moment'; // 初始化 Highcharts 模块 HighchartsGantt(Highcharts); HighchartsMore(Highcharts); class GanttChart extends Component { componentDidMount() { // 初始化 Highcharts Gantt 图表 this.chart = Highcharts.ganttChart(this.container, { title: { text: '甘特图' }, xAxis: { currentDateIndicator: true, min: moment().startOf('day').valueOf(), max: moment().add(2, 'weeks').startOf('day').valueOf() }, yAxis: { uniqueNames: true }, series: [{ name: '项目', data: [{ name: '任务1', start: Date.UTC(2021, 4, 1), end: Date.UTC(2021, 4, 7), completed: 0.25 }, { name: '任务2', start: Date.UTC(2021, 4, 8), end: Date.UTC(2021, 4, 14), completed: 0 }] }] }); } componentWillUnmount() { // 销毁 Highcharts 图表实例 this.chart.destroy(); } render() { return ( <div ref={el => this.container = el}></div> ); } } export default GanttChart; ``` 在这个示例中,我们首先导入了 React、Highcharts 和 moment 库,然后初始化了 Highcharts Gantt 图表实例,并且使用 `componentDidMount` 生命周期钩子函数将图表挂载到 DOM 上。在 `componentWillUnmount` 生命周期钩子函数中,我们将 Highcharts 图表实例销毁以释放资源。 最后,我们在 `render` 函数中返回一个 `div` 元素,用于渲染 Highcharts Gantt 图表的容器。您可以根据自己的需求更改配置和数据,以适配您的项目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值