我正在构建这个甘特图,我在块上找到了一个例子:
https://bl.ocks.org/arpitnarechania/4b4aa79b04d2e79f30765674b4c24ace
效果很好。我只想在“任务”之上添加一条垂直线,以指示在任务进行过程中发生的其他事件。我们的想法是在矩形上绘制一条垂直线:
我唯一不确定的是如何处理从时间戳数组中绘制多条线。我知道目前我正在使用d.synched[0]
因此只有一行,但我如何更改它以绘制与时间戳一样多的行。
这是我的JSBIN:https://jsbin.com/layecehidu/edit?js,console,output
任何,所有的帮助将不胜感激!
答案 0 :(得分:1)
最简单的解决方案,即在不更改代码的情况下,为data
中的每个对象创建一个组:
var lineGroup = svg.selectAll(null)
.data(data)
.enter()
.append("g");
然后根据这些群组的数据创建行:
var lines = lineGroup.selectAll(null)
.data(function(d) {
return d.synched
})
.enter()
.append("line")
.style("stroke", "red")
.attr("x1", function(d) {
console.log(d);
return x(parseDate(d));
})
.attr("y1", function(d) {
var parentDatum = d3.select(this.parentNode).datum();
return y(parentDatum.category) - 5;
})
.attr("x2", function(d) {
return x(parseDate(d));
})
.attr("y2", function(d) {
var parentDatum = d3.select(this.parentNode).datum();
return y(parentDatum.category) + y.rangeBand() + 5;
});
以下是更新后的代码:
var parseDate = d3.time.format("%d-%b-%y").parse;
var data = [{
"category": "Task 1",
"from": "1-Jan-17",
"to": "15-Jan-17",
"progress": 100,
"synched": ["5-Jan-17", "7-Jan-17"]
}, {
"category": "Task 2",
"from": "13-Jan-17",
"to": "1-Feb-17",
"progress": 60,
"synched": ["15-Jan-17"]
}, {
"category": "Task 1",
"from": "1-Feb-17",
"to": "11-Mar-17",
"progress": 90,
"synched": ["2-Feb-17", "4-Feb-17"]
}]
var types_of_statuses = ["Completed", "Remaining"];
var statuses_color = ["#2ecc71", "#e74c3c"];
data.forEach(function(d) {
d.from = parseDate(d.from);
d.to = parseDate(d.to);
});
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], 0.2);
var x = d3.time.scale().range([0, width]);
y.domain(data.map(function(d) {
return d.category;
}));
x.domain([d3.min(data, function(d) {
return d.from;
}), d3.max(data, function(d) {
return d.to;
})]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(15)
.tickFormat(d3.time.format("%d%b"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("y", function(d) {
return y(d.category);
})
.attr("height", y.rangeBand())
.attr("x", function(d) {
return x(d.from);
})
.attr("width", function(d) {
return x(d.to) - x(d.from);
});
var lineGroup = svg.selectAll(null)
.data(data)
.enter()
.append("g");
var lines = lineGroup.selectAll(null)
.data(function(d) {
return d.synched
})
.enter()
.append("line")
.style("stroke", "red")
.attr("x1", function(d) {
return x(parseDate(d));
})
.attr("y1", function(d) {
var parentDatum = d3.select(this.parentNode).datum();
return y(parentDatum.category) - 5;
})
.attr("x2", function(d) {
return x(parseDate(d));
})
.attr("y2", function(d) {
var parentDatum = d3.select(this.parentNode).datum();
return y(parentDatum.category) + y.rangeBand() + 5;
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width - margin.right)
.attr("dx", ".71em")
.attr("dy", "-0.2em")
.text("Date");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
.pending {
fill: #e74c3c;
}
.bar {
fill: #2ecc71;
}
/* .bar:hover, .pending:hover {
fill: #3498db;
} */
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font: 16px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
.axis,
.frame {
shape-rendering: crispEdges;
}
.axis path {
fill: none;
stroke: grey;
shape-rendering: crispEdges;
}
.axis text {
font-family: Arial;
font-size: 10px;
}
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
请注意,为了获取每一行的category
,我们必须访问行选择中的父数据(即组)。
如果需要,另一个选项是使用父级(组)数据填充行的数据,如下所示:
var lines = lineGroup.selectAll(null)
.data(function(d) {
return d.synched.map(function(e) {
return {
syn: e,
cat: d.category
};
})
})
.enter()
.append("line")
.style("stroke", "red")
.attr("x1", function(d) {
return x(parseDate(d.syn));
})
.attr("y1", function(d) {
return y(d.cat) - 5;
})
.attr("x2", function(d) {
return x(parseDate(d.syn));
})
.attr("y2", function(d) {
return y(d.cat) + y.rangeBand() + 5;
});