2014-07-11 46 views
3

我的意思是通過點擊等同於mouseout,我想要一種方法來單擊某個元素以更改某個屬性,然後在單擊該元素之外的任何其他元素時將其更改回來。通過懸停來切換此屬性更改很容易,因爲您基於mouseover和mouseout來更改內容,但我不確定如何根據click事件執行相同操作。d3.js:單擊鼠標等效物

所以我所擁有的是一個帶有圓圈的svg元素,當它們被點擊時它會顯示一個紅色輪廓。我足夠了解每次只能選中一個圓圈,但當我點擊不是圓的svg部分時,我不知道如何取消選擇所有節點。如果這還不夠清楚,我可以創建一個jsfiddle來展示我到目前爲止的內容。

我對閱讀很多示例有選擇性的工作知識,但似乎無法弄清楚我應該採取什麼方法來實現這一目標。

+0

您可以爲突出顯示的元素指定一個特殊的類,並在點擊時先選擇該類的所有元素並刪除突出顯示。 –

回答

5

您可以使用d3.dispatch來設置一些自定義事件處理。有時將不同的行爲與其他佈局代碼分離開來有助於保持組織結構的有序性。

您可能需要一個函數來忽略所有可點擊的圓圈,而另一個函數可以使單個圓圈變換。然後當單擊svg時,可以根據是否單擊圓圈來決定是否取消全部亮點。

換句話說...

當圈被點擊,撥動它。

當svg文件被點擊,並且點擊不在一個圓圈上時,忽略所有圓圈。

然後,您可以爲這兩個過程設置單獨的調度事件。這很好,因爲這些都成爲可重複使用的行爲。例如,如果您稍後想要添加一個按鈕來忽略所有圓圈,或者想要在被遮蓋時突出顯示一個圓圈,則可以調用相同的調度函數。

var dispatch = d3.dispatch('unhighlightAll','toggleSingle') 
    // remove the `highlighted` class on all circles 
    .on('unhighlightAll', function() { 
    d3.selectAll('.clickable-circle').classed('highlighted', false); 
    }) 
    // toggle the `highlighted` class on element `el` 
    .on('toggleSingle', function(el) { 
    d3.select(el).classed('highlighted', function() { 
     return !d3.select(el).classed('highlighted'); 
    }); 
    }); 

最後,你從你的點擊處理器調用調度功能:

svg.on('click', function() { 
    // do nothing if a clickable circle is clicked 
    if (d3.select(d3.event.target).classed('clickable-circle')) { 
    return; 
    } else { 
    // otherwise unhighlight all circles 
    dispatch.unhighlightAll(); 
    } 
}); 

circles.on('click', function() { 
    dispatch.toggleSingle(this); 
}); 

然後,所有剩下的就是決定如何顯示highlighted類,並處理在你的CSS。

這裏有一個演示JSBin

- 編輯 -

我才意識到,既然你想模仿鼠標移開,你可能不希望多選。你只需要改變toggleSingle功能位:

dispatch.on('toggleSingle', function(el) { 
    // store state of current element 
    var highlighted = d3.select(el).classed('highlighted'); 
    // unhighlight all 
    dispatch.unhighlightAll(); 
    // set opposite of stored state 
    d3.select(el).classed('highlighted', !highlighted); 
    }); 

而這裏的更新JSBin

+0

我正在閱讀'dispatch'的API,並試圖遵循示例,但說實話,我認爲這一切都飛過了我的腦海。是否有必要使用'dispatch',或者它只是最有效的方法? –

+1

您的情況沒有必要使用派送。你可以通過爲每個函數使用常規函數而避開,並從點擊處理程序中調用它們。事實上,我在這個例子中做過的事情,就是他們正在使用的。我只是這麼做的,因爲我想將它們視爲在可視化中共享的事件。 – jshanley

+0

有沒有簡單的方法來添加「nothighlighted」到這個?所以當選擇一個圓圈時,其他的變成「不透明度:0.2」? – As3adTintin

0

在SVG上添加點擊處理程序。在該點擊處理程序中,首先取消選擇所有的圈子。然後,通過d3.event檢查事件目標;如果它是一個圓圈,請選擇它。僞代碼描述:

svg.on('click', function() { 
    circles.classed('selected', false); 
    var target = /* get event target */; 
    if (/* target is circle */) { 
    target.classed('selected', true); 
    } 
}); 
+0

謝謝,我會嘗試實施這種方法。然而,我想知道這種方法有多複雜,還需要考慮改變懸停的不透明度 –

+0

這些應該是正交變化 - 您仍然可以像以前一樣將mouseenter等事件處理程序附加到您的圈子中。 – candu

0

Jshanley的答案是偉大的,很可能是在大多數情況下更好,但我最終修改了一點:

svg.selectAll("dot").data(datasource).enter() //you probably have your own thing here 
    .on("mousedown", function(d) { 
     d3.selectAll("circle") //this selects all of the elements you want to deselect by html tag (here its "circle") 
     .style("fill", "black"); //default color of unselected elements, here its black 
     d3.select(this) //select the element that's just been clicked 
     .style("fill", "orange"); //orange is the color of currently selected element 
    }); 

這個工作,只要被應用在所有元素的默認樣式的風格之前選定的元素。