Javascript D3光标下没有SVG元素时的几何缩放

Javascript D3光标下没有SVG元素时的几何缩放,javascript,svg,d3.js,zooming,pan,Javascript,Svg,D3.js,Zooming,Pan,我正在实现几何缩放行为,如图所示 问题是,如果光标位于绿色覆盖矩形或任何其他SVG元素(直线、圆等)外的白点上,浏览器会截取鼠标滚轮事件并向下滚动页面 我希望能够自由缩放,不受我在可视化上的位置影响 下面是一个简单的重新创建问题的过程 var width = 300, height = 300; var randomX = d3.random.normal(width / 2, 80), randomY = d3.random.normal(height / 2, 80);

我正在实现几何缩放行为,如图所示

问题是,如果光标位于绿色覆盖矩形或任何其他SVG元素(直线、圆等)外的白点上,浏览器会截取鼠标滚轮事件并向下滚动页面

我希望能够自由缩放,不受我在可视化上的位置影响

下面是一个简单的重新创建问题的过程

var width = 300,
    height = 300;

var randomX = d3.random.normal(width / 2, 80),
    randomY = d3.random.normal(height / 2, 80);

var data = d3.range(2000).map(function() {
  return [
    randomX(),
    randomY()
  ];
});

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .call(d3.behavior.zoom().scaleExtent([-8, 8]).on("zoom", zoom))
  .append("g");

svg.append("rect")
    .attr("class", "overlay")
    .attr("width", width)
    .attr("height", height);

svg.selectAll("circle")
    .data(data)
  .enter().append("circle")
    .attr("r", 2.5)
    .attr("transform", function(d) { return "translate(" + d + ")"; });

function zoom() {
  svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

在所有对象前面粘贴一个透明的矩形,这样鼠标事件就可以锁定。在SVG中,事件只发送到诸如RECT之类的渲染元素,而不发送到一般的未渲染背景

svg.append("rect")
    .attr("fill", "none")
    .attr("pointer-events", "all")
    .attr("width", "100%")
    .attr("height", "100%");
为了使其正常工作,SVG必须覆盖整个区域,以便获得与原始小提琴相同的外观,您需要将其剪裁到原始区域,这可以通过设置clipPath或(正如我在小提琴中所做的)创建一个Inser
元素来剪裁

var svg = d3.select("body").append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .call(d3.behavior.zoom().scaleExtent([-8, 8]).on("zoom", zoom));

svg = svg.append("svg")
    .attr("width", width)
    .attr("height", height)

在所有东西前面粘贴一个透明的矩形框,这样鼠标事件就可以锁定。在SVG中,事件只发送到诸如RECT之类的渲染元素,而不发送到一般的未渲染背景

svg.append("rect")
    .attr("fill", "none")
    .attr("pointer-events", "all")
    .attr("width", "100%")
    .attr("height", "100%");
为了使其正常工作,SVG必须覆盖整个区域,以便获得与原始小提琴相同的外观,您需要将其剪裁到原始区域,这可以通过设置clipPath或(正如我在小提琴中所做的)创建一个Inser
元素来剪裁

var svg = d3.select("body").append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .call(d3.behavior.zoom().scaleExtent([-8, 8]).on("zoom", zoom));

svg = svg.append("svg")
    .attr("width", width)
    .attr("height", height)

希望这不会太晚,我第一次错过了这个问题

它不能在Chrome下工作的原因是Chrome还没有在html元素上实现标准的CSS转换——尽管理解起来很奇怪,嵌入在网页中的SVG元素上最外层的
标记被视为用于布局的html元素

您有两个选择:

  • 除了常规转换语法外,还使用Chrome的自定义转换语法
    -webkit transform

    有点神经质,因为您正在转换整个SVG并相应地重新调整页面布局。由于种种原因,我不明白CSS/webkit转换和SVG属性转换在应用于“innerSVG”元素时都不起作用

  • 将嵌套的SVG结构替换为SVG
    组元素,Chrome在转换该元素时没有问题:


  • 希望这不会太晚,我第一次错过了这个问题

    它不能在Chrome下工作的原因是Chrome还没有在html元素上实现标准的CSS转换——尽管理解起来很奇怪,嵌入在网页中的SVG元素上最外层的
    标记被视为用于布局的html元素

    您有两个选择:

  • 除了常规转换语法外,还使用Chrome的自定义转换语法
    -webkit transform

    有点神经质,因为您正在转换整个SVG并相应地重新调整页面布局。由于种种原因,我不明白CSS/webkit转换和SVG属性转换在应用于“innerSVG”元素时都不起作用

  • 将嵌套的SVG结构替换为SVG
    组元素,Chrome在转换该元素时没有问题:



  • 请使用fiddle..?在缩放处理程序中执行d3.event.preventDefault()中的代码
    d3.event.stopPropagation()
    @LarsKotthoff我尝试了你的建议,但问题似乎不是当我们在白色区域时缩放回调没有被调用;由于未调用缩放处理程序,因此代码无效。不过这是合乎逻辑的。@Manoj创建了一个简单的JSFIDLE,从本质上重新创建了这个问题(我的代码中有很多事情:))请将您尝试过的代码放在FIDLE中..?在缩放处理程序中执行
    d3.event.preventDefault()
    d3.event.stopPropagation()
    @LarsKotthoff我尝试了你的建议,但问题似乎不是当我们在白色区域时缩放回调没有被调用;由于未调用缩放处理程序,因此代码无效。不过这是合乎逻辑的。@Manoj创建了一个简单的jsFiddle,从本质上重新创建了这个问题(我的代码中有很多东西:)。它确实适合我。我正在使用Firefox。我刚刚在Firefox下检查过,它可以正常工作;但不适用于Chrome。除了使用这种剪裁方法,没有其他方法了吗?我在问题中发布的图像是我想要使用它的实际场景,这种方法意味着丢失clipPath或内部SVG元素之外的任何内容。难道没有其他方法来实现这一点吗?我不明白为什么当我们在SVG画布上时d3没有得到缩放回调。它不转换或缩放。它被正确剪裁,但我无法与它交互。(没有缩放,也没有拖动)我的新版本更好了吗?没有,在Chrome下仍然一动不动。它确实适合我。我正在使用Firefox。我刚刚在Firefox下检查过,它可以正常工作;但不适用于Chrome。除了使用这种剪裁方法,没有其他方法了吗?我在问题中发布的图像是我想要使用它的实际场景,这种方法意味着丢失clipPath或内部SVG元素之外的任何内容。难道没有其他方法来实现这一点吗?我不明白为什么当我们在SVG画布上时d3没有得到缩放回调。它不转换或缩放。它被正确剪裁,但我无法与它交互。(没有缩放,也没有拖动)我的新版本更好了吗?没有,在Chrome下仍然静止不动。谢谢你,你的解决方案似乎解决了问题,而不需要妥协。谢谢你,你的解决方案似乎解决了问题,而不需要妥协。