d3js甘特图,日期/时间刻度在顶部,当天是蓝线

问题描述 投票:0回答:1

我正在研究d3js甘特图-我想增强此图表代码,以便它可以在视图的顶部合并日期/时间刻度,并在视图上添加蓝线,以指示当前日期/时间(移动-实时?)。我认为车道高度也不正确-调整车道高度有点困难-如果将来的设计需要的话,增加排水沟。洗涤器区域中可能存在多余的网格线。

//当前设计enter image description here

//新概念enter image description here

//最新版本https://jsfiddle.net/2mvhjr7z/2/

// html

<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
  <title>Gantt chart with D3.js</title>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script type='text/javascript' src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>

      <div 
           class="timelinechart" 
           data-role="timelinechart" 
           data-width=500 
           data-height=300 
           data-data=""
           >
      </div>

</body>
</html>

// css

        body {
          background: #eeeeee;
        }

        #holder {
          overflow: hidden;
        }

/*
.chart {
    shape-rendering: crispEdges;
}
*/

.timelinechart{
    /*width:100%;
    border: 1px solid red;*/
}

.timelinechart svg{
    width:100%;
    /*border: 1px solid green;*/
}

.timelinechartg{

}

.mini text {
    font: 10px sans-serif;  
}

.main text {
    font: 12px sans-serif;  
}

.miniItem {
    /*fill: darksalmon;*/
    stroke-width: 6;    
}

.miniItem.future{
    fill: #448875;
}
text.future {
    fill: #f7b363;
}


.brush .extent {
    stroke: #b6b8b9;
    fill: #57585b;
    fill-opacity: .365;
    stroke-width: .2;
}

.laneImg{
    border-radius: 25px;
}

// js

$(document).ready(function() {


  var $this = $('.timelinechart');

  var w = $this.data("width");
  var h = $this.data("height");

  var data = [
    {
      "label": "Argentina",
      "times": [
        {"text": "", "starting_time": 1355752800000, "ending_time": 1355752840000}
      ]
    },
    {
      "label": "Bolivia",
      "times": [
        {"text": "", "starting_time": 1355752800000, "ending_time": 1355752900000}
      ]
    },
    {
      "label": "Brazil",
      "times": [
        {"text": "", "starting_time": 1355752900000, "ending_time": 1355752935000}
      ]
    },
    {
      "label": "Canada",
      "times": [
        {"text": "", "starting_time": 1355753000000, "ending_time": 1355753500000}
      ]
    },
    {
      "label": "Chile",
      "times": [
        {"text": "", "starting_time": 1355753700000, "ending_time": 1355754000000}
      ]
    }
  ];


  var lanes = [];
  var times = [];

  $.each(data, function(index, value) {
    lanes.push(value.label);
    $.each(value.times, function(i, v) {
      v["lane"] = index;
    });
    times.push(value.times);
  });

  var laneLength = lanes.length;
  var items = [].concat.apply([], times);

  $.each(items, function(i, v) {
    v["id"] = i;
  });

  var timeBegin = d3.min(items, function(d) { return d["starting_time"]; });
  var timeEnd = d3.max(items, function(d) { return d["ending_time"]; });

  var m = [25, 80, 15, 105], //top right bottom left
      w = w - m[1] - m[3],
      h = h - m[0] - m[2],
      miniHeight = 50,//laneLength * 12 + 50,
      mainHeight = h - miniHeight - 50;


  //scales
  var x =  d3.scaleTime()
  .range([0, w])
  .domain([timeBegin, timeEnd]);
  var x1 = d3.scaleLinear()
  .range([0, w]);
  var y1 = d3.scaleLinear()
  .range([0, mainHeight])
  .domain([0, laneLength]);
  var y2 = d3.scaleLinear()
  .range([0, miniHeight])
  .domain([0, laneLength]);

  var xAxis = d3.axisBottom(x)
  .ticks(d3.timeMonth)
  .tickFormat(d=>d3.timeFormat("%B %Y")(d));


  var scaleFactor = (1/(timeEnd - timeBegin)) * (w);

  var chartWidth = w + m[1] + m[3];
  var chartHeight = h + m[0] + m[2];

  var chart = d3.select($this[0])
  .append("svg")
  .attr("width", chartWidth)
  .attr("height", chartHeight)
  .attr("viewBox", "0 0 "+chartWidth+" "+chartHeight)
  .attr("preserveAspectRatio", "xMidYMid meet")
  .append("g")
  .attr("class", "timelinechartg");

  chart.append("defs").append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", w)
    .attr("height", mainHeight);

  var main = chart.append("g")
  .attr("transform", "translate(" + m[3] + "," + m[0] + ")")
  .attr("width", w)
  .attr("height", mainHeight)
  .attr("class", "main");

  var mini = chart.append("g")
  .attr("transform", "translate(" + m[3] + "," + (mainHeight + m[0]) + ")")
  .attr("width", w)
  .attr("height", miniHeight)
  .attr("class", "mini");


  var gX = chart.append("g")
  .attr("class", "axis")
  .attr("transform", "translate(" + m[3] + "," + (mainHeight + miniHeight) + ")")
  .call(xAxis);

  //background colors
  function colores_background(n) {
    var colores_g = ["#f8dd2f", "#e9168a", "#448875", "#2b2d39", "#c3bd75", "#1b91dc"];
    return colores_g[n % colores_g.length];
  }

  //foreground colors
  function colores_foreground(n) {
    var colores_g = ["#553814", "#311854", "#f7b363", "#c12f39", "#89191d", "#2b2d39"];
    return colores_g[n % colores_g.length];
  }

  //main lanes and texts
  main.append("g").selectAll(".laneLines")
    .data(items)
    .enter().append("line")
    .attr("x1", 0)
    .attr("y1", function(d) {return y1(d.lane);})
    .attr("x2", w)
    .attr("y2", function(d) {return y1(d.lane);})
    .attr("stroke", "lightgray")

  var defs = main.append('svg:defs');

  main.append("g").selectAll(".laneText")
    .data(lanes)
    .enter().append("text")
    .text(function(d) {return d;})
    .attr("x", (-m[1] + 10))
    .attr("y", function(d, i) {
    return y1(i + .5);
  })
    .attr("dy", ".5ex")
    .attr("text-anchor", "end")
    .attr("class", "laneText");

  //mini lanes and texts
  mini.append("g").selectAll(".laneLines")
    .data(items)
    .enter().append("line")
    .attr("x1", 0)
    .attr("y1", function(d) {
    return y2(d.lane);
  })
    .attr("x2", w)
    .attr("y2", function(d) {
    return y2(d.lane);
  })
    .attr("stroke", "lightgray");



  var itemRects = main.append("g")
  .attr("clip-path", "url(#clip)");


mini.append('rect')
  .attr("class", "miniBar")
  .attr("x", 0)
  .attr("y", 10)
  .attr("fill", "grey")
  .attr("width", w)
  .attr("height", 30);





  var brush = d3.brushX()
  .extent([[0, 0], [w, miniHeight]])
  .on("brush", brushed);

  mini.append("g")
    .attr("class", "x brush")
    .call(brush)
    .selectAll("rect")
    .attr("y", 1)
    .attr("height", miniHeight - 1);

  function brushed() {
    var selection = d3.event.selection;
    var timeSelection = selection.map(x.invert, x);
    //console.log("selection: " + selection);
    //console.log("start: " + timeSelection[0]);
    //console.log("end: " + timeSelection[1]);

    var rects;
    var labels;
    var minExtent = timeSelection[0];
    var maxExtent = timeSelection[1];  

    var visItems = items.filter(function(d) {return d.starting_time <  maxExtent && d.ending_time > minExtent;});

    //mini.select(".brush")
    //.call(brush.extent([minExtent, maxExtent]));        

    x1.domain([minExtent, maxExtent]);      

    //update main item rects
    rects = itemRects.selectAll("rect")
      .data(visItems, function(d) { return d.id; })
      .attr("x", function(d) {return x1(d.starting_time);})
      .attr("width", function(d) {return x1(d.ending_time) - x1(d.starting_time);});

    rects.enter().append("rect")
      .attr("class", function(d) {return "miniItem "+d.state;})
      .attr("x", function(d) {return x1(d.starting_time);})
      .attr("y", function(d) {return y1(d.lane) + .8;})
      .attr("fill", "blue")
      .attr("width", function(d) {return x1(d.ending_time) - x1(d.starting_time);})
      .attr("height", function(d) {return .8 * y1(1);});

    rects.exit().remove();

    //update the item labels
    labels = itemRects.selectAll("text")
      .data(visItems, function (d) { return d.id; })
      .attr("x", function(d) {return x1(Math.max(d.starting_time, minExtent) + 2);});

    labels.enter().append("text")
      .text(function(d) {return d.text;})
      .attr("class", function(d) {return d.state;})
      .attr("x", function(d) {return x1(Math.max(d.starting_time, minExtent));})
      .attr("y", function(d) {return y1(d.lane + .5);})
      .attr("fill", function(d, i) {
      return colores_foreground(d.lane);
    })
      .attr("text-anchor", "start");

    labels.exit().remove();
  }

});
d3.js timeline gantt-chart
1个回答
0
投票

我添加了装订线。您可以更改数字以更改装订线比例。

我添加了另一个绑定到x1比例尺的轴,

var xAxisTop = d3.axisBottom(xTop)
    .ticks(d3.timeMonth)
    .tickFormat(d=>d3.timeFormat("%b %Y")(d));

并且在brushed中将其称为如下。

gXTop.call(xAxisTop);

配置对象可以在顶部找到。

var config = {
   gutter: 0.1,
   squareColor: "red",
   currentLineStroke: "green",
   laneTextSize: "30px",
   TopAxisLabelSize: "18px",
   BottomAxisLabelSize: "9px"
}

如果我错过了什么,或者您想添加其他内容,请发表评论。

enter image description here

Fiddle

© www.soinside.com 2019 - 2024. All rights reserved.