刷盘区不按预期工作

时间:2017-06-26 19:35:06

标签: d3.js

出于某种原因,我的图表并没有像我希望的那样得到满足。 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);
}

https://jsbin.com/layecehidu/edit?js,console,output

1 个答案:

答案 0 :(得分:1)

您的代码中的问题是,您使用的是select,而应该使用selectAll

selectselectAll之间的明显区别,正如方法的名称所暗示的那样,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>