2012-09-10 85 views
4

即使範圍較大,是否有限制刷子尺寸的方法?d3.js:刷子的極限尺寸

我把只有一個可以移動和調整大小的x-scale的畫筆放在一起。我希望能夠限制用戶調整大小的範圍(基本上只限於某個特定點)。

在以下示例中,畫筆函數在畫筆變得大於最大範圍的一半時停止更新。但是刷子本身仍然可以延伸。有沒有辦法來防止這種情況發生?或者有更好的方法來處理這個問題?

非常感謝!

在這裏看到這個代碼在行動:http://bl.ocks.org/3691274編輯:這個演示現在工作)

bar = function(range) { 

     var x_range = d3.scale.linear() 
      .domain([0, range.length]) 
      .range([0, width]); 

     svg.selectAll("rect.items").remove(); 

     svg.selectAll("rect.items") 
      .data(range) 
     .enter().append("svg:rect") 
      .attr("class", "items") 
      .attr("x", function(d, i) {return x_range(i);}) 
      .attr("y", 0) 
      .attr("width", width/range.length-2) 
      .attr("height", 100) 
      .attr("fill", function(d) {return d}) 
      .attr("title", function(d) {return d}); 
} 

var start = 21; 
bar(data.slice(0, start), true); 

var control_x_range = d3.scale.linear() 
    .domain([0, data.length]) 
    .range([0, width]); 

controlBar = svg.selectAll("rect.itemsControl") 
    .data(data) 
    .enter().append("svg:rect") 
    .attr("class", "itemsControl") 
    .attr("x", function(d, i) {return control_x_range(i);}) 
    .attr("y", 110) 
    .attr("width", width/data.length-2) 
    .attr("height", 20) 
    .attr("fill", function(d) {return d}); 

svg.append("g") 
    .attr("class", "brush") 
    .call(d3.svg.brush().x(d3.scale.linear().range([0, width])) 
    .extent([0,1*start/data.length]) 
    .on("brush", brush)) 
    .selectAll("rect") 
    .attr("y", 110) 
    .attr("height", 20); 

function brush() { 
    var s = d3.event.target.extent(); 

    if (s[1]-s[0] < 0.5) { 
     var start = Math.round((data.length-1)*s[0]); 
     var end = Math.round((data.length-1)*s[1]); 

     bar(data.slice(start,end)); 
    }; 

} 

回答

4

我最終被超過大小時重畫刷其最大允許大小解決了這個問題:

function brush() { 
    var s = d3.event.target.extent(); 
    if (s[1]-s[0] < 0.5) { 
     var start = Math.round((data.length-1)*s[0]); 
     var end = Math.round((data.length-1)*s[1]); 

     bar(data.slice(start,end)); 
    } 
    else {d3.event.target.extent([s[0],s[0]+0.5]); d3.event.target(d3.select(this));} 
} 

演示:http://bl.ocks.org/3691274

我仍然有興趣閱讀更好的解決方案。

0

不錯的一段代碼,但我發現了一個小錯誤。 它會鎖定你的畫筆,只要s[1]-s[0] < 0.5,但如果你保持按下調整大小,並使所有的畫筆反方向,它開始「移動」畫筆沒有任何動作(即它不像它應該那樣)。

我很確定我能想出一個合理的解決方案。如果是這樣,我會在這裏重新發布它。

(遺憾的是,在這裏作爲回答發佈,但由於您已經回答過一次,我不能作爲評論發佈)。

0

這裏的另一種策略,利用d3.v4和ES6的辯論,因爲這就是我現在使用...

brush.on('end',() => { if (d3.event.selection[1] - d3.event.selection[0] > maxSelectionSize) { // selection is too large; animate back down to a more reasonable size let brushCenter = d3.event.selection[0] + 0.5 * (d3.event.selection[1] - d3.event.selection[0]); brushSel.transition() .duration(400) .call(brush.move, [ brushCenter - 0.49 * maxSelectionSize, brushCenter + 0.49 * maxSelectionSize ]); } else { // valid selection, do stuff } });

如果刷的選擇大小時,使用者放開過大它將動畫降回到指定的最大尺寸(maxSelectionSize)。此時,'end'事件將再次觸發,並具有可接受的選擇大小。

0.49標 - 這是爲了防止浮點/舍入誤差,可能導致無限循環,如果刷move() d的大小是仍然太大。