2015-04-17 56 views
2

我有兩個重疊的svg.g組,其中具有不同的onclick事件。我使用opacity屬性定期將這些組混合到可視化中。目前,只有頂層渲染組的onclick事件被調用,但我想調用當前可見組的事件。或者,我總是可以調用這兩個事件,並在被調用的函數中使用條件語句,這取決於opacity屬性。通過重疊的svg元素傳播事件

下面是一個例子

<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 

</head> 
<body> 
    <div id="body"></div> 
    <script type="text/javascript"> 

    var canvas_w = 1280 - 80, 
     canvas_h = 800 - 180; 

    var svg = d3.select("#body").append("div") 
     .append("svg:svg") 
     .attr("width", canvas_w) 
     .attr("height", canvas_h) 

    var visible_group = svg.append("g") 
     .attr("opacity", 1) 
     .on("click", function(d){console.log("Click")}) 
     .append("rect") 
     .attr("x", 0) 
     .attr("y", 0) 
     .attr("width", 100) 
     .attr("height", 100) 
     .style("fill", "blue"); 

    var invisible_group = svg.append("g") 
     .attr("opacity", 0) 
     .on("click", function(d){console.log("Invisiclick")}) 
     .append("rect") 
     .attr("x", 0) 
     .attr("y", 0) 
     .attr("width", 100) 
     .attr("height", 100) 
     .style("fill", "red"); 


    </script> 
</body> 
</html> 

此代碼將呈現藍色矩形,可見基。帶有紅色矩形的組是隱藏的。如果您單擊藍色矩形,「Invisiclick」將被打印到控制檯,隱藏組的onclick事件。我想打印「點擊」到控制檯,或者「Invisiclick」和「Click」。

我該怎麼做?

+1

你也可以把'pointer-events:none'放在隱形組上。即使你想留下它們,它仍然會使它們從鼠標事件的角度來看是透明的。 –

回答

2

不透明確實使元素半透明,它不會使它們消失。就像您可以點擊一塊玻璃一樣,您可以用opacity:0單擊一個元素。

現在,有兩種選擇,根據兩個視圖中的形狀是否不同。如果他們不是(比如說,你正在繪製一張世界地圖,這些國家保持不變,只是顏色發生變化),聽最頂層,然後運行一個if語句可能是最簡單的,執行。像這樣

var state = "blue"; 
 

 

 
    var clickHandler = function() { 
 
     if(state === "blue") { 
 
      console.log("Blue clicked"); 
 
     } else { 
 
      console.log("Red clicked"); 
 
     } 
 
    } 
 

 

 
    var toggleState = function() { 
 
     state = (state === "blue") ? "red" : "blue"; 
 
    } 
 

 
    var updateDisplay = function() { 
 
     blueGroup 
 
      .transition() 
 
      .duration(400) 
 
      .attr("opacity", state === "blue" ? 1 : 0); 
 
     redGroup 
 
      .transition() 
 
      .duration(400) 
 
      .attr("opacity", state === "red" ? 1 : 0); 
 
    } 
 

 
    var canvas_w = 1280 - 80, 
 
     canvas_h = 120; 
 

 
    var svg = d3.select("#body").append("div") 
 
     .append("svg:svg") 
 
     .attr("width", canvas_w) 
 
     .attr("height", canvas_h) 
 

 
    var blueGroup = svg.append("g") 
 
     .append("rect") 
 
     .attr("opacity", 1) 
 
     .attr("x", 0) 
 
     .attr("y", 0) 
 
     .attr("width", 100) 
 
     .attr("height", 100) 
 
     .style("fill", "blue"); 
 

 
    var redGroup = svg.append("g") 
 
     .on("click", clickHandler) 
 
     .append("rect") 
 
     .attr("opacity", 0) 
 
     .attr("x", 0) 
 
     .attr("y", 0) 
 
     .attr("width", 100) 
 
     .attr("height", 100) 
 
     .style("fill", "red"); 
 

 

 

 
    d3.select("button").on("click", function() { 
 
     toggleState(); 
 
     updateDisplay(); 
 
    });
<script src="https://samizdat.cz/tools/d3/3.5.3.min.js" charset="utf-8"></script> 
 
<div id="body"></div> 
 
<button>change!</button>

如果另一方面形狀改變,則需要先半透明的元素與opacity:0然後使他們消失display:none(否則,它們會立即閃光)。另一種方法是pointer-events,但前提是您不需要支持old browsers。然後 的轉變應該是這樣的:

var state = "blue"; 
 

 
var toggleState = function() { 
 
    state = (state === "blue") ? "red" : "blue"; 
 
} 
 

 
var updateDisplay = function() { 
 
    blueGroup 
 
     .style("display", state === "blue" ? "block" : "none") 
 
     .transition() 
 
     .duration(400) 
 
     .attr("opacity", state === "blue" ? 1 : 0) 
 
     .each("end", function() { 
 
      blueGroup.style("display", state === "blue" ? "block" : "none"); 
 
     }); 
 
     
 
    redGroup 
 
     .style("display", state === "red" ? "block" : "none") 
 
     .transition() 
 
     .duration(400) 
 
     .attr("opacity", state === "red" ? 1 : 0) 
 
     .each("end", function() { 
 
      redGroup.style("display", state === "red" ? "block" : "none"); 
 
     }); 
 
} 
 

 
var canvas_w = 1280 - 80, 
 
    canvas_h = 120; 
 

 
var svg = d3.select("#body").append("div") 
 
    .append("svg:svg") 
 
    .attr("width", canvas_w) 
 
    .attr("height", canvas_h) 
 

 
var blueGroup = svg.append("g") 
 
    .on("click", function() { 
 
     console.log("Blue clicked"); 
 
    }) 
 
    .append("rect") 
 
    .attr("opacity", 1) 
 
    .attr("x", 0) 
 
    .attr("y", 0) 
 
    .attr("width", 150) 
 
    .attr("height", 100) 
 
    .style("fill", "blue"); 
 

 
var redGroup = svg.append("g") 
 
    .on("click", function() { 
 
     console.log("Red clicked"); 
 
    }) 
 
    .append("rect") 
 
    .attr("opacity", 0) 
 
    .style("display", "none") 
 
    .attr("x", 0) 
 
    .attr("y", 0) 
 
    .attr("width", 100) 
 
    .attr("height", 120) 
 
    .style("fill", "red"); 
 

 

 

 
d3.select("button").on("click", function() { 
 
    toggleState(); 
 
    updateDisplay(); 
 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="body"></div> 
 
<button>change!</button>

注意,每個轉型,我們現在必須同時處理opacitydisplay,並以正確的順序。另請注意,現在我們有的收聽者,均爲rect s。

的例子是相當簡單一點,如果它能夠與.enter().exit()選擇使用,因爲你可以使廢除了.on("end"),而是在退出過渡使用.remove()

更新:實際上與display:none相同也是visibility: hidden

2

如果您使用的樣式visibility而不是屬性opacity設置組爲隱藏或可見,您還可以使用樣式pointer-events限制事件可見的元素。

var canvas_w = 1280 - 80, 
    canvas_h = 800 - 180; 

var svg = d3.select("#body").append("div") 
    .append("svg:svg") 
    .attr("width", canvas_w) 
    .attr("height", canvas_h) 

var visible_group = svg.append("g") 
    .style("visibility", "visible") 
    .style("pointer-events", "visible") 
    .on("click", function(d){console.log("Click")}) 
    .append("rect") 
    .attr("x", 0) 
    .attr("y", 0) 
    .attr("width", 100) 
    .attr("height", 100) 
    .style("fill", "blue"); 

var invisible_group = svg.append("g") 
    .style("visibility", "hidden") 
    .style("pointer-events", "visible") 
    .on("click", function(d){console.log("Invisiclick")}) 
    .append("rect") 
    .attr("x", 0) 
    .attr("y", 0) 
    .attr("width", 100) 
    .attr("height", 100) 
    .style("fill", "red"); 


</script> 

這個例子將打印 「單擊」 控制檯當您單擊藍色矩形。