当存在相邻元素时,d3 svg 缩放不起作用
d3 svg zoom does not work when neighbouring element exists
我正在使用包含其他 div 的 div 作为 svg 之上(或之下)的叠加层。这将允许我在 svg 之上放置丰富的基于 html 的功能,例如滚动表格,与 google 地图叠加层不同。我现在只是让这个概念起作用,关键的困难是让 divs 与它们绑定的 svg 点保持一致。
下面示例中的缩放代码不起作用,除非我删除或隐藏叠加层 div。
我试过:
- 将 div 移出 "outerdiv" - 不起作用,因为 div 没有接收到任何数据(输入功能似乎停止工作)
- 在 svg 和叠加层上设置 z 索引 div
- 在叠加之前或之后移动 svg div
无论我做什么,缩放事件都不会触发,但是如果你在 CSS 中用 display:none
或 visibility:hidden
隐藏 div,它工作正常
var
outerwidth = 1000,
outerheight = 500,
width = outerwidth,
height = outerheight,
rectwidth = 200,
rectheight = 50;
var div = d3.select(".outerdiv");
var overlay = div.select(".overlay");
var svg = div.select("svg")
.attr("preserveAspectRatio", "xMidYMid")
.attr("class", "svgnetwork");
var g = svg.append("g");
overlay.style("width", outerwidth + "px").style("height", outerheight + "px");
var data = [
["Test1", 15],
["Test2", 25],
["Test3", 10],
["Test4", 20]
];
var nodes = overlay.selectAll("div").data(data).enter().append("div").attr("class", "node")
.style("top", function(d, i) {
return i * 100 + "px";
})
.style("left", function(d, i) {
return 0 + "px";
})
.style("width", rectwidth + "px")
.style("height", rectheight + "px")
// inner text content of node
nodes
.append("div").text(function(d, i) {
return "Content : " + d[0] + " " + d[1];
});
// rects which should appear in the same places as divs
g.selectAll("rect").data(data).enter().append("rect")
.attr("class", "noderect")
.attr("width", rectwidth)
.attr("height", rectheight)
.attr("y", function(d, i) {
return i * 100;
})
.attr("x", 0);
// set svg viewbox
svg.attr("viewBox", "0 0 " + width + " " + height);
// uncomment the next line and zoom on svg works
// overlay.node().style.display = "none";
svg.call(d3.zoom()
.scaleExtent([1 / 2, 2])
.on("zoom", function() { // zoom fires on pan and zoom
svg.attr("transform", d3.event.transform);
return false;
})
);
svg {
background-color: #ffffee;
z-index: 2;
}
.outerdiv {
border: 1px solid black;
margin: 5px;
height: 500px;
width: 1000px;
position: relative;
background-color: transparent;
}
.overlay {
border: 1px solid blue;
position: absolute;
top: 0;
left: 0;
z-index: 0;
}
.node {
box-sizing: border-box;
border: 1px solid green;
height: 25px;
width: 150px;
position: absolute;
}
.noderect {
fill: none;
stroke: red;
stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.7/d3.min.js"></script>
<div class="outerdiv">
<div class="overlay"></div>
<svg></svg>
</div>
最终目标是让叠加层中的 div 在我们缩放和平移时随 svg 内容一起移动,但显然第一步是让它完全缩放。
谢谢
编辑:包括叠加 DIVS 缩放和平移的最终解决方案
https://jsfiddle.net/paull3876/z6ef2uwg/
认为这可能是一个很常见的要求,因此对某些人有用:)
您可以添加 pointer-events:none;
叠加 div
.overlay {
pointer-events:none;
}
然后底层svg
会收到鼠标事件
var
outerwidth = 1000,
outerheight = 500,
width = outerwidth,
height = outerheight,
rectwidth = 200,
rectheight = 50;
var div = d3.select(".outerdiv");
var overlay = div.select(".overlay");
var svg = div.select("svg")
.attr("preserveAspectRatio", "xMidYMid")
.attr("class", "svgnetwork");
var g = svg.append("g");
overlay.style("width", outerwidth + "px").style("height", outerheight + "px");
var data = [
["Test1", 15],
["Test2", 25],
["Test3", 10],
["Test4", 20]
];
var nodes = overlay.selectAll("div").data(data).enter().append("div").attr("class", "node")
.style("top", function(d, i) {
return i * 100 + "px";
})
.style("left", function(d, i) {
return 0 + "px";
})
.style("width", rectwidth + "px")
.style("height", rectheight + "px")
// inner text content of node
nodes
.append("div").text(function(d, i) {
return "Content : " + d[0] + " " + d[1];
});
// rects which should appear in the same places as divs
g.selectAll("rect").data(data).enter().append("rect")
.attr("class", "noderect")
.attr("width", rectwidth)
.attr("height", rectheight)
.attr("y", function(d, i) {
return i * 100;
})
.attr("x", 0);
// set svg viewbox
svg.attr("viewBox", "0 0 " + width + " " + height);
// uncomment the next line and zoom on svg works
// overlay.node().style.display = "none";
svg.call(d3.zoom()
.scaleExtent([1 / 2, 2])
.on("zoom", function() { // zoom fires on pan and zoom
svg.attr("transform", d3.event.transform);
overlay.raise()
return false;
})
);
svg {
background-color: #ffffee;
z-index: 2;
}
.outerdiv {
border: 1px solid black;
margin: 5px;
height: 500px;
width: 1000px;
position: relative;
background-color: transparent;
}
.overlay {
border: 1px solid blue;
position: absolute;
top: 0;
left: 0;
z-index: 0;
pointer-events:none;
}
.node {
box-sizing: border-box;
border: 1px solid green;
height: 25px;
width: 150px;
position: absolute;
}
.noderect {
fill: none;
stroke: red;
stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.7/d3.min.js"></script>
<div class="outerdiv">
<div class="overlay"></div>
<svg></svg>
</div>
但您也需要将转换应用于叠加层
我正在使用包含其他 div 的 div 作为 svg 之上(或之下)的叠加层。这将允许我在 svg 之上放置丰富的基于 html 的功能,例如滚动表格,与 google 地图叠加层不同。我现在只是让这个概念起作用,关键的困难是让 divs 与它们绑定的 svg 点保持一致。
下面示例中的缩放代码不起作用,除非我删除或隐藏叠加层 div。
我试过: - 将 div 移出 "outerdiv" - 不起作用,因为 div 没有接收到任何数据(输入功能似乎停止工作) - 在 svg 和叠加层上设置 z 索引 div - 在叠加之前或之后移动 svg div
无论我做什么,缩放事件都不会触发,但是如果你在 CSS 中用 display:none
或 visibility:hidden
隐藏 div,它工作正常
var
outerwidth = 1000,
outerheight = 500,
width = outerwidth,
height = outerheight,
rectwidth = 200,
rectheight = 50;
var div = d3.select(".outerdiv");
var overlay = div.select(".overlay");
var svg = div.select("svg")
.attr("preserveAspectRatio", "xMidYMid")
.attr("class", "svgnetwork");
var g = svg.append("g");
overlay.style("width", outerwidth + "px").style("height", outerheight + "px");
var data = [
["Test1", 15],
["Test2", 25],
["Test3", 10],
["Test4", 20]
];
var nodes = overlay.selectAll("div").data(data).enter().append("div").attr("class", "node")
.style("top", function(d, i) {
return i * 100 + "px";
})
.style("left", function(d, i) {
return 0 + "px";
})
.style("width", rectwidth + "px")
.style("height", rectheight + "px")
// inner text content of node
nodes
.append("div").text(function(d, i) {
return "Content : " + d[0] + " " + d[1];
});
// rects which should appear in the same places as divs
g.selectAll("rect").data(data).enter().append("rect")
.attr("class", "noderect")
.attr("width", rectwidth)
.attr("height", rectheight)
.attr("y", function(d, i) {
return i * 100;
})
.attr("x", 0);
// set svg viewbox
svg.attr("viewBox", "0 0 " + width + " " + height);
// uncomment the next line and zoom on svg works
// overlay.node().style.display = "none";
svg.call(d3.zoom()
.scaleExtent([1 / 2, 2])
.on("zoom", function() { // zoom fires on pan and zoom
svg.attr("transform", d3.event.transform);
return false;
})
);
svg {
background-color: #ffffee;
z-index: 2;
}
.outerdiv {
border: 1px solid black;
margin: 5px;
height: 500px;
width: 1000px;
position: relative;
background-color: transparent;
}
.overlay {
border: 1px solid blue;
position: absolute;
top: 0;
left: 0;
z-index: 0;
}
.node {
box-sizing: border-box;
border: 1px solid green;
height: 25px;
width: 150px;
position: absolute;
}
.noderect {
fill: none;
stroke: red;
stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.7/d3.min.js"></script>
<div class="outerdiv">
<div class="overlay"></div>
<svg></svg>
</div>
最终目标是让叠加层中的 div 在我们缩放和平移时随 svg 内容一起移动,但显然第一步是让它完全缩放。
谢谢
编辑:包括叠加 DIVS 缩放和平移的最终解决方案
https://jsfiddle.net/paull3876/z6ef2uwg/
认为这可能是一个很常见的要求,因此对某些人有用:)
您可以添加 pointer-events:none;
叠加 div
.overlay {
pointer-events:none;
}
然后底层svg
会收到鼠标事件
var
outerwidth = 1000,
outerheight = 500,
width = outerwidth,
height = outerheight,
rectwidth = 200,
rectheight = 50;
var div = d3.select(".outerdiv");
var overlay = div.select(".overlay");
var svg = div.select("svg")
.attr("preserveAspectRatio", "xMidYMid")
.attr("class", "svgnetwork");
var g = svg.append("g");
overlay.style("width", outerwidth + "px").style("height", outerheight + "px");
var data = [
["Test1", 15],
["Test2", 25],
["Test3", 10],
["Test4", 20]
];
var nodes = overlay.selectAll("div").data(data).enter().append("div").attr("class", "node")
.style("top", function(d, i) {
return i * 100 + "px";
})
.style("left", function(d, i) {
return 0 + "px";
})
.style("width", rectwidth + "px")
.style("height", rectheight + "px")
// inner text content of node
nodes
.append("div").text(function(d, i) {
return "Content : " + d[0] + " " + d[1];
});
// rects which should appear in the same places as divs
g.selectAll("rect").data(data).enter().append("rect")
.attr("class", "noderect")
.attr("width", rectwidth)
.attr("height", rectheight)
.attr("y", function(d, i) {
return i * 100;
})
.attr("x", 0);
// set svg viewbox
svg.attr("viewBox", "0 0 " + width + " " + height);
// uncomment the next line and zoom on svg works
// overlay.node().style.display = "none";
svg.call(d3.zoom()
.scaleExtent([1 / 2, 2])
.on("zoom", function() { // zoom fires on pan and zoom
svg.attr("transform", d3.event.transform);
overlay.raise()
return false;
})
);
svg {
background-color: #ffffee;
z-index: 2;
}
.outerdiv {
border: 1px solid black;
margin: 5px;
height: 500px;
width: 1000px;
position: relative;
background-color: transparent;
}
.overlay {
border: 1px solid blue;
position: absolute;
top: 0;
left: 0;
z-index: 0;
pointer-events:none;
}
.node {
box-sizing: border-box;
border: 1px solid green;
height: 25px;
width: 150px;
position: absolute;
}
.noderect {
fill: none;
stroke: red;
stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.7/d3.min.js"></script>
<div class="outerdiv">
<div class="overlay"></div>
<svg></svg>
</div>
但您也需要将转换应用于叠加层