2016-09-07 86 views
0

我有D3圖表上的以下數據顯示:D3卡扣刷到日期上XAXIS

[{ 
    "Date": "2012", 
    "Total": 5340 
}, { 
    "Date": "2013", 
    "Total": 4120 
}, { 
    "Date": "2014", 
    "Total": 1259 
}, { 
    "Date": "2015", 
    "Total": 3617 
}, { 
    "Date": "2016", 
    "Total": 2005 
}] 

該圖表還具有在其上的刷子,以便用戶可以通過拖動刷集中於一個選擇的年。然而,畫筆允許用戶在第一年和最後一年之間拖動所有日期。

我想要做的就是在用戶刷牙的時候使其捕捉多年。

這裏是我刷的事件代碼:

var brush = d3.svg.brush() 
    .x(xScale2) 
    .on('brush', brushed); 

function brushed() { 
    var min = d3.min(data.map(function (d) { 
     return d.total; 
    })); 
    var max = d3.max(data.map(function (d) { 
     return d.total; 
    })); 
    var extent = brush.extent(); 
    if (!brush.empty()) { 

     // Snap to years 
      var newBrush = extent.map(d3.time.year.round); 
      if (newBrush[0] >= newBrush[1]) {// If empty when rounded, use floor & ceil instead. 
       newBrush[0] = d3.time.year.floor(extent[0]); 
       newBrush[1] = d3.time.year.ceil(extent[1]); 

      } 
      // update the extent 
      brush.extent([newBrush[0], newBrush[1]]); 
      extent = brush.extent(); 

      xScale.domain(brush.empty() ? xScale2.domain() : extent); 
      yScale.domain([ 
       d3.min(data.map(function (d) { 
        return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : max; 
       })), 
       d3.max(data.map(function (d) { 
        return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : min; 
       })) 
      ]); 

     xScale.domain(brush.empty() ? xScale2.domain() : extent); 
     yScale.domain([ 
      d3.min(data.map(function (d) { 
       return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : max; 
      })), 
      d3.max(data.map(function (d) { 
       return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : min; 
      })) 
     ]); 
    } 
    totalChart.attr('d', totalLine); // update line 
    focus.select('.x.axis').call(xAxis); // update xAxis 
    focus.select('.y.axis').call(yAxis); // update yAxis 
} 

這是基於:https://bl.ocks.org/mbostock/6232620

這樣的想法是,今年是第一四捨五入,然後程度正被應用之前修改到域,應該使刷簡單...但是它不會捕捉...相反,它使用戶鬥爭之間拖動它的年間。我希望它實際上在用戶開始拖動時捕捉到下一年。他們永遠不應該能夠在這些年間拖延。

+0

你只是希望它的年度工作或你希望它四捨五入到當前數據的日期? – Mehraban

+0

@SaeedAdelMehraban只需每年在這個例子中,然後一旦它正確捕捉,我可以適應它爲我的其他日期格式工作。所以一言以蔽之。 – Cameron

+0

我已經更新了我的答案,以使用d3 v3。 – Mehraban

回答

2

這裏是mbostock代碼與年份對齊。它只是有一點點的背景界限。

此代碼工作正常,除了背景/刷子元素同步中的一個小缺陷。

var margin = {top: 0, right: 40, bottom: 50, left: 40}, 
 
    width = 500 - margin.left - margin.right, 
 
    height = 100 - margin.top - margin.bottom; 
 
var x = d3.time.scale() 
 
    .domain([new Date(2012, 1, 1), new Date(2023, 1, 1)]) 
 
    .range([0, width]); 
 
var brush = d3.svg.brush() 
 
    .x(x) 
 
    .extent([new Date(2014, 1, 1), new Date(2015, 1, 1)]) 
 
    .on("brushend", brushended); 
 
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("rect") 
 
    .attr("class", "grid-background") 
 
    .attr("width", width) 
 
    .attr("height", height); 
 
svg.append("g") 
 
    .attr("class", "x grid") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.svg.axis() 
 
     .scale(x) 
 
     .orient("bottom") 
 
     .ticks(d3.time.months, 6) 
 
     .tickSize(-height) 
 
     .tickFormat("")) 
 
    .selectAll(".tick") 
 
    .classed("minor", function(d) { return d.getHours(); }); 
 
svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.svg.axis() 
 
     .scale(x) 
 
     .orient("bottom") 
 
     .ticks(d3.time.years) 
 
     .tickPadding(0)) 
 
    .selectAll("text") 
 
    .attr("x", 6) 
 
    .style("text-anchor", null); 
 
var gBrush = svg.append("g") 
 
    .attr("class", "brush") 
 
    .call(brush) 
 
    .call(brush.event); 
 
gBrush.selectAll("rect") 
 
    .attr("height", height); 
 
function brushended() { 
 
    if (!d3.event.sourceEvent) return; // only transition after input 
 
    var extent0 = brush.extent(), 
 
     extent1 = extent0.map(d3.time.year.round); 
 
    // if empty when rounded, use floor & ceil instead 
 
    if (extent1[0] >= extent1[1]) { 
 
    extent1[0] = d3.time.year.floor(extent0[0]); 
 
    extent1[1] = d3.time.year.ceil(extent0[1]); 
 
    } 
 
    d3.select(this).transition() 
 
     .call(brush.extent(extent1)) 
 
     .call(brush.event); 
 
}
.axis text { 
 
    font: 11px sans-serif; 
 
} 
 
.axis path { 
 
    display: none; 
 
} 
 
.axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
} 
 
.grid-background { 
 
    fill: #ddd; 
 
} 
 
.grid line, 
 
.grid path { 
 
    fill: none; 
 
    stroke: #fff; 
 
    shape-rendering: crispEdges; 
 
} 
 
.grid .minor.tick line { 
 
    stroke-opacity: .5; 
 
} 
 
.brush .extent { 
 
    stroke: #000; 
 
    fill-opacity: .125; 
 
    shape-rendering: crispEdges; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script> 
 

 
<body> 
 
</body>

+0

是brush.move 4.0中的一個新功能d3? – Cameron

+0

@Cameron正如你可以看到這個示例代碼中的d3版本是v4。你可以看到v3和v4刷子之間的區別[這裏](https://github.com/d3/d3-brush/blob/master/README.md) – Mehraban

+0

'brush.move'做了那個'brush.extent '不?正如你可以在我的例子中看到的,我更新'brush.extent'中的值來嘗試使其更快。因爲我使用的是沒有'brush.move'的d3.v3。謝謝。 – Cameron