gojs实现工作任务甘蔗图图表效果代码

代码语言:html

所属分类:图表

代码描述:gojs实现工作任务甘蔗图图表效果代码

代码标签: gojs 工作 任务 甘蔗图 图表

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
</head>

<body>
    <script src="//repo.bfw.wiki/bfwrepo/js/go.js"></script>
  
  <div id="allSampleContent" class="p-4 w-full">
<div id="sample">
  <div style="width: 100%; display: flex; justify-content: space-between; border: solid 1px black">
    <div id="myTasksDiv" style="width: 150px; margin-right: 2px; border-right: 1px solid black; position: relative; -webkit-tap-highlight-color: rgba(255, 255, 255, 0);"><canvas tabindex="0" width="186" height="500" style="position: absolute; top: 0px; left: 0px; z-index: 2; user-select: none; touch-action: none; width: 149px; height: 400px;">This text is displayed if your browser does not support the Canvas HTML element.</canvas><div style="position: absolute; overflow: auto; width: 149px; height: 400px; z-index: 1;"><div style="position: absolute; width: 1px; height: 1px;"></div></div></div>
    <div id="myGanttDiv" style="flex-grow: 1; height: 400px; position: relative; -webkit-tap-highlight-color: rgba(255, 255, 255, 0);"><canvas tabindex="0" width="1106" height="478" style="position: absolute; top: 0px; left: 0px; z-index: 2; user-select: none; touch-action: none; width: 885px; height: 383px;">This text is displayed if your browser does not support the Canvas HTML element.</canvas><div style="position: absolute; overflow: auto; width: 902px; height: 400px; z-index: 1;"><div style="position: absolute; width: 1104px; height: 484px;"></div></div></div>
  </div>
  <div id="slider">
    <label>间距:</label>
    <input id="widthSlider" type="range" min="8" max="24" value="12" oninput="rescale()">
  </div>
  <p>
   此示例演示了一个简单的甘特图。甘特图用于说明项目进度表,表示项目终端和摘要元素的开始和结束日期。

您可以通过更改“间距”值来放大图表,该值使用节点宽度和位置的数据绑定函数来缩放图表。这代替了更改Diagram.scale。
  </p>

  <p>
    The current model in JSON format:
  </p>
  <textarea id="mySavedModel" style="width:100%;height:250px">{ "class": "GraphLinksModel",
  "modelData": {"origin":1531540800000},
  "nodeDataArray": [
{"key":0,"text":"Project X","start":0,"duration":85},
{"key":1,"text":"Task 1","color":"darkgreen","start":0,"duration":22},
{"key":11,"text":"Task 1.1","color":"green","duration":10,"start":0},
{"key":12,"text":"Task 1.2","color":"green","start":10,"duration":12},
{"key":121,"text":"Task 1.2.1","color":"lightgreen","duration":3,"start":10},
{"key":122,"text":"Task 1.2.2","color":"lightgreen","duration":5,"start":13},
{"key":123,"text":"Task 1.2.3","color":"lightgreen","duration":4,"start":18},
{"key":2,"text":"Task 2","color":"darkblue","start":10,"duration":40},
{"key":21,"text":"Task 2.1","color":"blue","duration":15,"start":10},
{"key":22,"text":"Task 2.2","color":"goldenrod","start":25,"duration":14},
{"key":221,"text":"Task 2.2.1","color":"yellow","duration":8,"start":25},
{"key":222,"text":"Task 2.2.2","color":"yellow","duration":6,"start":33},
{"key":23,"text":"Task 2.3","color":"darkorange","start":39,"duration":11},
{"key":231,"text":"Task 2.3.1","color":"orange","duration":11,"start":39},
{"key":3,"text":"Task 3","color":"maroon","start":50,"duration":35},
{"key":31,"text":"Task 3.1","color":"brown","duration":10,"start":50},
{"key":32,"text":"Task 3.2","color":"brown","start":60,"duration":25},
{"key":321,"text":"Task 3.2.1","color":"lightsalmon","duration":8,"start":60},
{"key":322,"text":"Task 3.2.2","color":"lightsalmon","duration":3,"start":68},
{"key":323,"text":"Task 3.2.3","color":"lightsalmon","duration":7,"start":71},
{"key":324,"text":"Task 3.2.4","color":"lightsalmon","duration":5,"start":71},
{"key":325,"text":"Task 3.2.5","color":"lightsalmon","duration":4,"start":76},
{"key":326,"text":"Task 3.2.6","color":"lightsalmon","duration":5,"start":80}
],
  "linkDataArray": [
{"from":0,"to":1},
{"from":1,"to":11},
{"from":1,"to":12},
{"from":12,"to":121},
{"from":12,"to":122},
{"from":12,"to":123},
{"from":0,"to":2},
{"from":2,"to":21},
{"from":2,"to":22},
{"from":22,"to":221},
{"from":22,"to":222},
{"from":2,"to":23},
{"from":23,"to":231},
{"from":0,"to":3},
{"from":3,"to":31},
{"from":3,"to":32},
{"from":32,"to":321},
{"from":32,"to":322},
{"from":32,"to":323},
{"from":32,"to":324},
{"from":32,"to":325},
{"from":32,"to":326},
{"from":11,"to":2,"category":"Dep"}
]}</textarea>
<p class="text-xs">GoJS version 2.2.10. Copyright 1998-2022 by Northwoods Software.</p></div>
<script id="code">

// Custom Layout for myGantt Diagram
class GanttLayout extends go.Layout {
  constructor() {
    super();
    this.cellHeight = GridCellHeight;
  }

  doLayout(coll) {
    coll = this.collectParts(coll);
    const diagram = this.diagram;
    diagram.startTransaction("Gantt Layout");
    const bars = [];
    this.assignTimes(diagram, bars);
    this.arrangementOrigin = this.initialOrigin(this.arrangementOrigin);
    let y = this.arrangementOrigin.y;
    bars.forEach(node => {
      const tasknode = myTasks.findNodeForData(node.data);
      node.visible = tasknode.isVisible();
      node.position = new go.Point(convertStartToX(node.data.start), y);
      if (node.visible) y += this.cellHeight;
    });
    diagram.commitTransaction("Gantt Layout");
  }

  // Update node data, to make sure each node has a start and a duration
  assignTimes(diagram, bars) {
    const roots = diagram.findTreeRoots();
    roots.each(root => this.walkTree(root, 0, bars));
  }

  walkTree(node, start, bars) {
    bars.push(node);
    const model = node.diagram.model;
    if (node.isTreeLeaf) {
      let dur = node.data.duration;
      if (dur === undefined || isNaN(dur)) {
        dur = convertDaysToUnits(1);  // default task length?
        model.set(node.data, "duration", dur);
      }
      let st = node.data.start;
      if (st === undefined || isNaN(st)) {
        st = start;  // use given START
        model.set(node.data, "start", st);
      }
      return st + dur;
    } else {
      // first recurse to fill in any missing data
      node.findTreeChildrenNodes().each(n => {
        start = this.walkTree(n, start, bars);
      });
      // now can calculate this non-leaf node's data
      let min = Infinity;
      let max = -Infinity;
      const colors = new go.Set();
      node.findTreeChildrenNodes().each(n => {
        min = Math.min(min, n.data.start);
        max = Math.max(max, n.data.start + n.data.duration);
        if (n.data.color) colors.add(n.data.color);
      });
      model.set(node.data, "start", min);
      model.set(node.data, "duration", max - min);
      return max;
    }
  }
}
// end of GanttLayout


var GridCellHeight = 20; // document units
var GridCellWidth = 12;  // document units per day
var TimelineHeight = 24; // document units

const MsPerDay = 24 * 60 * 60 * 1000;

// By default the values for the data properties start and duration are in days,
// and the start value is relative to the StartDate.
// If you want the start and duration properties to be in a unit other than days,
// you only need to change the implementation of convertDaysToUnits and convertUnitsToDays.

function convertDaysToUnits(n) {
  return n;
}

function convertUnitsToDays(n) {
  return n;
}

function convertStartToX(start) {
  return convertUnitsToDays(start) * GridCellWidth;
}

function convertXToStart(x, node) {
  return convertDaysToUnits(x / GridCellWidth);
}

function convertDurationToW(duration) {
  return convertUnitsToDays(duration) * GridCellWidth;
}

function convertWToDuration(w) {
  return convertDaysToUnits(w / GridCellWidth);
}

function convertStartToPosition(start, node) {
  return new go.Point(convertStartToX(start), node.position.y || 0);
}

function convertPositionToStart(pos) {
  return convertXToStart(pos.x);
}

var StartDate = new Date();  // set from Model.modelData.origin

function valueToText(n) {  // N is in days since StartDate
  const startDate = StartDate;
  const startDateMs = startDate.getTime() + startDate.getTimezoneOffset() * 60000;
  const date = new Date(startDateMs + n * MsPerDay / GridCellWidth);
  return date.toLocaleDateString();
}

function dateToValue(d) {  // D is a Date
  const startDate = StartDate;
  const startDateMs = startDate.getTime() + startDate.getTimezoneOffset() * 60000;
  const dateInMs = d.getTime() + d.getTimezoneOffset() * 60000;
  const msSinceStart = dateInMs - startDateMs;
  return msSinceStart / MsPerDay * GridCellWidth;
}


// the custom figure used for task bars that have downward points at their ends
go.Shape.defineFigureGenerator("RangeBar", (shape, w, h) => {
  const b = Math.min(5, w);
  const d = Math.min(5, h);
  return new go.Geometry()
    .add(new go.PathFigure(0, 0, true)
      .add(new go.PathSegment(go.PathSegment.Line, w, 0))
      .add(new go.PathSegment(go.PathSegment.Line, w, h))
      .add(new go.PathSegment(go.PathSegment.Line, w-b, h-d))
      .add(new go.PathSegment(go.PathSegment.Line, b, h-d))
      .add(new go.PathSegment(go.PathSegment.Line, 0, h).close()));
});

const $ = go.GraphObject.make;

function standardContextMenus() {
  return {
      contextMenu: $("ContextMenu",
        $("ContextMenuButton",
          $(go.TextBlock, "Details..."),
          {
            click: (e, button) => {
              const task = button.part.adornedPart;
              console.log("show HTML panel with details about the task " + task.text);
            }
          }
        ),
        $("ContextMenuButton",
          $(go.TextBlock, "New Task"),
          {
            click: (e, button) => {
              const task = button.part.adornedPart;
              e.diagram.model.commit(m => {
                const newdata = { key: undefined, text: "New Task", color: task.data.color, duration: convertDaysToUnits(5) };
                m.addNodeData(newdata);
                m.addLinkData({ from: task.key, to: newdata.key });
                e.diagram.select(e.diagram.findNodeForData(newdata));
              });
            }
          }
        )
      )
  };
}

// the left side of the whole diagram
const myTasks =
  new go.Diagram("myTasksDiv",
    {
      initialContentAlignment: go.Spot.Right,
      padding: new go.Margin(TimelineHeight, 0, 0, 0),
      hasVerticalScrollbar: false,
      a.........完整代码请登录后点击上方下载按钮下载查看

网友评论0