我有两个重叠的 svg.g
组,它们具有不同的 onclick
事件。我定期使用 opacity
属性将组混合进或出可视化效果。目前,仅调用顶部呈现的组的 onclick
事件,但我想调用当前可见的组的事件。或者,我始终可以调用这两个事件,并在被调用函数内使用条件语句,该语句取决于 opacity
属性。
这是一个例子
<!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
事件。我想将“Click”打印到控制台,或者同时打印“Invisiclick”和“Click”。
我该怎么做?
最佳答案
不透明度确实使元素半透明,但不会使它们消失。正如您可以点击一 block 玻璃一样,您可以点击 opacity:0
的元素。
现在,有两个选项,具体取决于两个 View 中的形状是否不同。如果它们不是(例如,您正在绘制世界地图,国家/地区保持不变,只是颜色发生变化),那么最简单的方法可能是监听最顶层,然后运行 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>
请注意,在每次转换时,我们现在必须以正确的顺序处理不透明度
和显示
。另请注意,现在我们在 both rect
上都有监听器。
如果该示例可以与 .enter()
和 .exit()
选择一起使用,那么它会更简单,因为您可以取消 .on("end")
并在退出转换上使用 .remove()
。
更新:实际上与display:none
相同也是visibility:hidden
。
关于javascript - 通过重叠的 svg 元素传播事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29704936/