使用d3.js拖动元素时滚动

时间:2013-10-26 03:14:16

标签: javascript d3.js

我在svg元素上使用d3的拖动行为,可能需要将其拖放到可见区域之外。我将它设置在两个div中,溢出设置为auto以启用滚动。我有这个只与一些浏览器合作但不是全部。

问题是在某些浏览器中,您可以在拖动时滚动,但在其他浏览器中,拖动时窗口不会滚动。到目前为止,我还没有办法让这项工作保持一致。

有关工作示例,请参阅小提琴:http://jsfiddle.net/glanotte/qd5Td/1/

这正如预期的那样:

chrome - mac / windows safari - mac

但不是

Firefox - mac / windows IE - windows

HTML:

<div id="outerFrame">
    <div id="innerFrame">
        <svg width="600" height="600">
        </svg>
    </div>
</div>

的CSS:

#outerFrame{
    width: 300px;
    height: 300px;
    border: 1px solid red;
    overflow: auto;
}

#innerFrame{
    width: 600px;
    height: 600px;
    background-color: lightgrey;
}

的javascript:

var drag = d3.behavior.drag()
    .on("dragstart", dragstart)
    .on("drag", dragmove)
    .on("dragend", dragend);

function dragstart() {
  d3.select(this).style("border", "1px solid red");
}

function dragmove(d) {
    var coordinates = d3.mouse(d3.select("svg").node());
    d3.select(this).attr({
        x: coordinates[0] - 50,
        y: coordinates[1] - 25
    })

}

function dragend() {
  d3.select(this).style("border", null);
}

d3.select("svg")
    .append("rect")
    .attr({x: 100, y: 100, width: 100, height: 50})
    .call(drag);

1 个答案:

答案 0 :(得分:3)

不幸的是,bug in Firefox noticed before by mbostock and marked as WONT-FIX已经发现了http://jsfiddle.net/62CYD/

根据错误报告中的建议,您可以使其工作,但只能通过手动滚动容器:like done in DOMUtilityService in ng-grid

实施非常简单,可以通过以下方式改进:

  1. 使用动画
  2. 考虑滚动条的宽度Taking current mouse position into account
  3. {{3}}以避免捕捉拖动的项目和更顺畅的滚动。
  4. 即使拖动停止,也使用setTimeout继续滚动
  5. function dragmove(d) {
        var svg = d3.select("svg").node(),
            $parent = $('#outerFrame'),
            w = $parent.width(), h = $parent.height(),
            sL = $parent.scrollLeft(), sT = $parent.scrollTop();
    
        var coordinates = d3.mouse(svg),
            x = coordinates[0],
            y = coordinates[1];
    
        if (x > w + sL) {
            $parent.scrollLeft(x - w);  
        } else if (x < sL) {
            $parent.scrollLeft(x);
        }
    
        if (y > h + sT) {
            $parent.scrollTop(y - h);
        } else if (y < sT) {
            $parent.scrollTop(y);
        }
    
        d3.select(this).attr({
            x: x - 50,
            y: y - 25
        })
    }