当相邻元素存在时,d3 svg缩放不起作用

时间:2019-07-01 12:21:38

标签: javascript d3.js svg overlay

我正在使用包含其他div的div作为svg顶部(或下方)的覆盖层。这将使我能够将基于HTML的丰富功能放在svg之上,例如滚动表,这与Google Maps叠加层不同。我现在只是使这个概念起作用,而关键的困难是让div保持与它们相关的svg点。

除非删除或隐藏叠加层div,否则下面示例中的缩放代码将不起作用。

我尝试过: -将div移出“ outerdiv”-不起作用,因为div没有收到数据(enter函数似乎停止工作) -在svg和overlay div上设置z索引 -将svg移动到叠加层div之前或之后

无论我做什么,缩放事件都不会触发,但是如果您在CSS中使用display:nonevisibility: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内容移动,但是显然第一步是使其完全缩放。

谢谢

编辑:最终解决方案,包括叠加分割和平移

https://jsfiddle.net/paull3876/z6ef2uwg/

这可能是很常见的要求,因此对某人有用:)

1 个答案:

答案 0 :(得分:2)

您可以添加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>

但是您也需要将转换应用于叠加