2013-08-05 68 views
2

我想讓用戶使用brush來選擇一系列值。但是,在我的應用程序中只有離散值是有意義的,所以我想限制畫筆到這些離散值(整數,比方說)。將畫筆限制在離散範圍

這樣做的一種方法是使用Ordinal Brushing中描述的方法。在這個例子中,刷子本身可以取連續值,然後將其映射到序數標度的離散值。

我想得到一個畫筆,當用戶刷或拖動畫筆時,它會捕捉離散值。我想出了一些基本的工作原理:四捨五入target.extent,然後重新選擇圓角範圍(Fiddle):

function brush() { 
    var s = d3.event.target.extent(); 
    if (d3.event.mode === "move") { 
     var extentlength = Math.round(s[1] - s[0]) 
     d3.event.target.extent([Math.round(s[0] + 0.5) - 0.5, 
     Math.round(s[0] + 0.5) - 0.5 + extentlength]) 
    } else { 
     d3.event.target.extent([Math.round(s[0] + 0.5) - 0.5, 
     Math.round(s[1] + 0.5) - 0.5]) 
    } 
    d3.event.target(d3.select(this)) 
} 

但是,這感覺有點笨重,而且它會導致不良行爲當用戶拖動畫筆時,光標可以懸停在畫筆邊緣,將光標符號從「拖拽」狀態變爲「調整尺寸」 - 箭頭。

是否有一種更優雅和可靠的方式獲取只允許選擇離散範圍的筆刷?

+0

我認爲你是在正確的軌道上。我試着改變你的小提琴使用「brushend」事件,而不是「brush」,並且我覺得它有點笨重(平滑幻燈片和發佈時的快照),但這是有爭議的。 –

回答

3

這可能對D3用於渲染畫筆的svg節點的內部過分挖掘,但一種解決方案是選擇這些節點並更改它們的光標風格。在你的榜樣,對於刷的一下像這樣生成的節點(我修剪出來的一些屬性):

var brush = d3.svg.brush().x(x).extent([0.5, 1.5]) 
    .on("brushstart", brushstart) 
    .on("brush", brush) 
    .on("brushend", brushend); 

function brushstart() { 
    // disable the resizing cursor 
    var resizers = d3.select(this).selectAll('g.resize') 
    .style("cursor", "auto"); 
} 

function brushend() { 
    // re-enable the resizing cursor 
    var resizers = d3.select(this).selectAll('g.resize') 
    .style("cursor", "ew-resize"); 
} 

<g style="pointer-events: all;"> 
    <rect class="background" style="visibility: hidden; cursor: crosshair;"></rect> 
    <rect class="extent" style="cursor: move;"></rect> 
    <g class="resize e" style="cursor: ew-resize;"> 
    <rect style="visibility: hidden;"></rect> 
    </g> 
    <g class="resize w" style="cursor: ew-resize;"> 
    <rect style="visibility: hidden;"></rect> 
    </g> 
</g> 

因此,例如,你可以完全刷事件期間禁用調整大小光標

正如我所說的,這會讓你面臨D3更改未來版本中刷子的svg節點結構的危險,但它在概念和計算上都相當簡單。內部筆刷事件中的this表示刷子本身的外部節點,所以我們只需應用該級別下的選擇器來查找調整大小節點。

再往前走一步,您可以在您的brush函數本身內添加額外的邏輯來更改遊標,但這是在鼠標移動時評估的,因此會更加昂貴。