出于某种原因,我的图表并没有像我希望的那样得到满足。 brush.extent()的域似乎正在工作,但条形图都飞离页面。谁能告诉我这里有什么问题?
function doBrush() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select("rect").attr("x", function(d) { return x(d.from); });
focus.select("rect").attr("width", function(d) {return x(d.to) - x(d.from);});
focus.select(".x.axis").call(xAxis);
}
答案 0 :(得分:1)
您的代码中的问题是,您使用的是select
,而应该使用selectAll
。
select
和selectAll
之间的明显区别,正如方法的名称所暗示的那样,select
......
选择与指定选择器字符串匹配的第一个后代元素。
...... selectAll
:
选择与指定选择器字符串匹配的所有元素。
但这不是唯一的区别。分组和数据传播是众所周知的差异。看看这张表:
+------------------+----------------------------------+----------------------------+
| Method | select() | selectAll() |
+------------------+----------------------------------+----------------------------+
| Selection | selects the first element | selects all elements that |
| | that matches the selector string | match the selector string |
+------------------+----------------------------------+----------------------------+
| Grouping | Does not affect grouping | Affect grouping |
+------------------+----------------------------------+----------------------------+
| Data propagation | Propagates data | Doesn't propagate data |
+------------------+----------------------------------+----------------------------+
话虽如此,您的代码应该是:
function doBrush() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.selectAll("rect").attr("x", function(d) {
return x(d.from);
})
focus.selectAll("rect").attr("width", function(d) {
return x(d.to) - x(d.from);
});
focus.select(".x.axis").call(xAxis);
}
以下是仅包含此更改的代码:
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"]}
]
data.forEach(function(d) {
d.from = parseDate(d.from);
d.to = parseDate(d.to);
});
var margin = {top: 10, right: 10, bottom: 100, left: 100},
margin2 = {top: 330, right: 10, bottom: 30, left: 100},
width = 900 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
height2 = 400 - margin2.top - margin2.bottom;
var x = d3.time.scale().range([0, width]);
var x2 = d3.time.scale().range([0, width]);
var y = d3.scale.ordinal().rangeRoundBands([0, height], 0.2);
var y2 = d3.scale.ordinal().rangeRoundBands([0, height2], 0.2);
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;})]);
x2.domain(x.domain());
y2.domain(y.domain());
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(15)
.tickFormat(d3.time.format("%d%b"));
var xAxis2 = d3.svg.axis()
.scale(x2)
.orient("bottom")
.ticks(15)
.tickFormat(d3.time.format("%d%b"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", doBrush);
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.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("fill", "red")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
var context = svg.append("g")
.attr("transform", "translate(0," + margin2.top + ")");
var focusRectangleGroups = focus.selectAll("g")
.data(data)
.enter()
.append("g");
focusRectangleGroups.append("rect")
.attr("class", "bar")
.attr("clip-path", "url(#clip)")
.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); });
focus.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");
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
var contextRectangleGroups = context.selectAll("g")
.data(data)
.enter()
.append("g");
contextRectangleGroups.append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y2(d.category); })
.attr("height", y2.rangeBand())
.attr("x", function(d) { return x2(d.from); })
.attr("width", function(d) { return x2(d.to) - x2(d.from); })
.attr("clip-path", "url(#clip)");
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
function doBrush() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.selectAll("rect").attr("x", function(d) { return x(d.from); })
focus.selectAll("rect").attr("width", function(d) { return x(d.to) - x(d.from); });
focus.select(".x.axis").call(xAxis);
}
.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;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>