As an overview of the

Daily requirements require an overview that shows the total time flow of the project set and how much time each segment takes up.

The selection

Based on the project development is ve2. X so tend to find the original gantt chart plug-in written by Vue. Vue Gantt is the top three on Github.

The plug-in gantt-schedule-timeline-calendar gantt-elastic vue-gantt-chart
advantages 1. The node interaction is sufficient to meet all operations. 2. Elegant style. 3. The form slot 1. An event is emitted from the node. 2 2. Support custom description and container block
disadvantages Ask for money, not open source Do not maintain the predecessor of the previous plug-in. Bar type fixed style fixed cannot be adjusted The overall style is weird. The left configuration needs to be rendered by the Component itself. There is no concept of parent-child data

Generally speaking, gantt-Elastic is suitable for Chart Row, which can be used by modifying it.

Critical code analysis

Plug-in key steps diagram

// Fold operation
makeTaskTree(task, tasks) {
  for (let i = 0, len = tasks.length; i < len; i++) {
    let current = tasks[i];
    if (current.parentId === task.id) {
      if (task.parents.length) {
        task.parents.forEach((parent) = > current.parents.push(parent));
      }
      if (!Object.prototype.propertyIsEnumerable.call(task, '__root')) {
        current.parents.push(task.id);
        current.parent = task.id;
      } else {
        current.parents = [];
        current.parent = null;
      }
      current = this.makeTaskTree(current, tasks); // recursively find the downstream parent of a point
      task.allChildren.push(current.id);
      task.children.push(current.id);
      current.allChildren.forEach((childId) = >task.allChildren.push(childId)); }}returntask; } Since the tree structure is formed, subsequent folding operations only need to modify the state key in tasks, and global monitoring tasks can complete filter redrawing.Copy the code
// Scroll synchronization,chart listens wheel event through refs to get each module modify scrollLeft, scrollTop properties.
    onWheelChart(ev) {
      // if (! ev.shiftKey && ev.deltaX === 0) {
      let top = this.state.options.scroll.top + ev.deltaY;
      const chartClientHeight = this.state.options.rowsHeight;
      const scrollHeight = this.state.refs.chartGraph.scrollHeight - chartClientHeight;
      if (top < 0) {
        top = 0;
      } else if (top > scrollHeight) {
        top = scrollHeight;
      }
      this.scrollTo(null, top);
      let left = this.state.options.scroll.left + ev.deltaX;
      const chartClientWidth = this.state.refs.chartScrollContainerHorizontal.clientWidth;
      const scrollWidth = this.state.refs.chartScrollContainerHorizontal.scrollWidth - chartClientWidth;
      if (left < 0) {
        left = 0;
      } else if (left > scrollWidth) {
        left = scrollWidth;
      }
      this.scrollTo(left);
    },
Copy the code
// Row Components Group submodules are rendered together
    foundChildrens() {
      const childrens = this.task.allChildren.map((id) = > {
        return this.root.getTask(id);
      });
      this.task.group = childrens;
    }
    
// Calculate the length of row to show whether the text case can be dropped.
   calText(task) {
      let marginLeft = this.root.style['chart-row-inline-text'] ['marginLeft'];
      let text = task.text;
      let textWidth = this.root.state.ctx.measureText(text).width + marginLeft;
      if (textWidth < task.width) {
        return text;
      } else {
        let ellipsisWidth = this.root.state.ctx.measureText('... ').width;
        const textArr = text.split(' ');
        let currentWidth = ellipsisWidth;
        const res = [];
        for (let text of textArr) {
          const textWidth = this.root.state.ctx.measureText(text).width;
          if (textWidth + currentWidth > task.width) {
            break;
          } else{ currentWidth += textWidth; res.push(text); }}return res.length ? res.join(' ') + '... ' : ' '; }}Copy the code

In the end, it turns out that the key to a successful drawing of a graph is the smallest granularity of row and column clarity, on which all calculations are based. Gantt-elastic records the width and height sharing of each block by providing its own instance.

Subsequent modification

  • Change it to Virtual Scroll to avoid rendering pressure. Just keep track of how far you roll. Math.floor(top/taskHeight) calculates the current startIdx. Then modify visibleTasks to redraw.

Give it a thumbs up if you find it helpful, or leave a comment in the comments section if you have a better idea. Thank you.

Refer to the link

  1. Gantt – elastic source code
  2. virtual scroll