【问题标题】:Creating graph with timeline in javascript在 javascript 中创建带有时间线的图形
【发布时间】:2017-01-29 06:03:22
【问题描述】:

我想在 javascript 中使用时间线创建动态变化的图形,看起来像 this。 编辑:我想自己决定哪个节点应该在哪个时间片中。

我想知道,是否有一个库可以用来执行此操作,或者我需要自己创建它(只需在画布上绘图)?我试图找到一个,但是似乎有很多时间线和图表的实现,但是很难找到这两者的组合。最合适的解决方案是使用gojs。但是我不能创建一个包含两个父节点的节点,因为它是作为树数据结构实现的。

【问题讨论】:

    标签: javascript graph visualization timeline gojs


    【解决方案1】:

    您可能需要玩数学,但我希望这将作为一个有用的起点:

    演示JSFiddle

    HTML

    <div id='board'>
     <div id='titles'></div>
    
    </div>
    

    CSS

    #board { 
      position: relative; 
      width: 500px;
      height: 600px;
      background-color:#f83213;
    }
    #titles {
      color: #ffffff;
      width: 100%;
      height: 18px;
      font-size: 12px;
    }
    #titles div {
      display:inline-block;
      margin: 10px;
    }
    .event{
        border: 0px;
        background-color: #3a2356;
        color: #ffffff;
        width: 18px;
        height: 18px;
        position: absolute;
        padding: 4px;
        font-size: 18px;
        z-index: 2;
    }
    .line{
        height: 1px;
        width: 60px;
        background-color: #3a2356;
        position: absolute;
        z-index: 1;
    }
    

    ** JavaScript**

    var margin = 20;
    var events = {
      "A": {
        day: 0,
        indexInDay: 0,
        lineTos: ["D"]
      },
      "B": {
        day: 0,
        indexInDay: 1,
        lineTos: ["D"]
      },
      "D": {
        day: 1,
        indexInDay: 0,
        lineTos: ["E","F"]
      },
      "E": {
        day: 2,
        indexInDay: 0,
        lineTos: null
      },
      "C": {
        day: 0,
        indexInDay: 2,
        lineTos: ["F"]
      },
      "F": {
        day: 2,
        indexInDay: 2,
        lineTos: null
      },
    };
    
    drawAll(events);
    
    function drawAll(events) {
      drawTitles(events);
      drawEvents(events);
      drawLines(events);
    }
    
    function drawTitles(events) {
      var titles = document.getElementById('titles');
      var max = 0;
      for (var name in events) {
        if (events[name].day > max)
          max = events[name].day;
      }
      for (var i = 0 ; i <= max ; i++)
        titles.innerHTML += '<div>' + 'Day' + i + '</div>';
    }
    
    function drawEvents(events) {
      var board = document.getElementById('board');
      for (var name in events) {
        var ev = events[name];
        var eventDiv = document.createElement('DIV');
        board.appendChild(eventDiv);
        eventDiv.className = 'event';
        setTopLeftEvent(ev, eventDiv);
        eventDiv.innerText = name;
    
      }
    }
    
    function drawLines(events) {
      var board = document.getElementById('board');
      for (var name in events) {
        var from = events[name];
        var tos = from.lineTos;
        if (!tos) continue;
        for (var j = 0 ; j < tos.length ; j++) {
          var to = events[tos[j]];
          var lineDiv = document.createElement('DIV');
          board.appendChild(lineDiv);
          lineDiv.className = 'line';
          setTopLeftLine(from, lineDiv);
          lineDiv.style.width = margin  + 1 * margin * distance(to.indexInDay,from.indexInDay,to.day, from.day) + 'px';
          var tan = (to.indexInDay - from.indexInDay) / (to.day - from.day);
          lineDiv.style.top = lineDiv.offsetTop + (tan * margin) +'px';
          var angle = Math.atan(tan) * 180/Math.PI;
          // Code for Safari
          lineDiv.style.WebkitTransform = "rotate(" + angle + "deg)"; 
          // Code for IE9
          lineDiv.style.msTransform = "rotate(" + angle + "deg)"; 
          // Standard syntax
          lineDiv.style.transform = "rotate(" + angle + "deg)"; 
        }
    
      }
    }
    
    function distance(x1, y1, x2, y2){
     var res = Math.sqrt((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1)); 
     return res;
    }
    
    function setTopLeftEvent(event, eventDiv) {
      eventDiv.style.left = (margin + event.day * (margin * 2)) + 'px';
        eventDiv.style.top = (margin * 2 + event.indexInDay * (margin * 2)) + 'px';
    }
    function setTopLeftLine(event, lineDiv) {
      lineDiv.style.left = (margin + event.day * (margin * 2)) + 'px';
      lineDiv.style.top = (margin * 2.5 + event.indexInDay * (margin * 2)) + 'px';
    }
    

    【讨论】:

      【解决方案2】:

      正如GoJS sample 在文中提到的那样,很容易将 TreeLayout 替换为 LayeredDigraphLayout 并将 TreeModel 替换为 GraphLinksModel。这是我刚刚修改示例所做的。

      go.TreeLayout替换为go.LayeredDigraphLayout,这样自定义布局就不再继承自TreeLayout。更改构造函数以不打扰设置 TreeLayout 特定属性。更改图表的布局以使用 LayeredDigraphLayout 特定属性:

                  layout: $(LayeredTreeLayout,  // custom layout is defined above
                            {
                              angle: HORIZONTAL ? 0 : 90,
                              columnSpacing: 5,
                              layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource
                            }),
      

      用包含您想要的数据的 GraphLinksModel 替换该示例的模型:

      // define the node data
      var nodearray = [
        { // this is the information needed for the headers of the bands
          key: "_BANDS",
          category: "Bands",
          itemArray: [
            { text: "Day 0" },
            { text: "Day 1" },
            { text: "Day 2" },
            { text: "Day 3" },
            { text: "Day 4" },
            { text: "Day 5" }
          ]
        }
      ];
      var linkarray = [
        { from: "A", to: "D" },
        { from: "B", to: "D" },
        { from: "D", to: "E" },
        { from: "D", to: "F" },
        { from: "C", to: "F" }
      ];
      
      myDiagram.model = $(go.GraphLinksModel,
          { // automatically create node data objects for each "from" or "to" reference
            // (set this property before setting the linkDataArray)
            archetypeNodeData: {},
            nodeDataArray: nodearray,
            linkDataArray: linkarray
          });
      

      在没有更改任何模板或样式的情况下,结果是:

      为了确保它有效,我还尝试设置HORIZONTAL = false

      【讨论】:

      • 谢谢,这对我很有帮助。但是,我有一个问题,我希望 this 也能正常工作。具体来说,如果我可以自己决定哪个节点应该在哪个时间片中,那就太好了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      • 2020-02-13
      相关资源
      最近更新 更多