如何在 d3 JavaScript 库中为拖动行为设置原点 (drag.origin)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15966256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 02:45:36  来源:igfitidea点击:

How to set the Origin (drag.origin) for drag behavior in d3 JavaScript library

javascriptd3.jsdrag

提问by karlitos

I am trying to implement drag behavior for group consisting from HTML-text and background-rectangle using the d3 framework. I was able to get it working, although when not setting the drag.origin I can see noticeable jump due to the mouse-position/element-coordinates offset. Exactly how described on the d3 wiki-pageAlthough the page described how to set the Origin for dragging, I do not properly understand how ti implement it in my example. I tried two different approaches : using the element for grouping the elements together and defining new element holding tose. In the first case I have to use the translate-function and I do not even know how to get the coordinates of the group.

我正在尝试使用 d3 框架为由 HTML 文本和背景矩形组成的组实现拖动行为。我能够让它工作,虽然当没有设置 drag.origin 时,由于鼠标位置/元素坐标偏移,我可以看到明显的跳跃。d3 wiki 页面上的确切描述 虽然该页面描述了如何设置拖动的原点,但我没有正确理解如何在我的示例中实现它。我尝试了两种不同的方法:使用元素将元素组合在一起并定义新元素保持不变。在第一种情况下,我必须使用翻译功能,我什至不知道如何获取组的坐标。

var svg = d3.select("body").append("svg")
  .attr("width", 960)
  .attr("height", 500);

var group = svg.append("svg:g")
  .attr("transform", "translate(10, 10)")
  .attr("id", "group");

var rect1 = group.append("svg:rect")
  .attr("rx", 6)
  .attr("ry", 6)
  .attr("x", 5/2)
  .attr("y", 5/2)
  .attr("id", "rect")
  .attr("width", 250)
  .attr("height", 125)
  .style("fill", 'white')
  .style("stroke", d3.scale.category20c())
  .style('stroke-width', 5);


var html1 = group.append("foreignObject")
  .attr("x", 50)
  .attr("y", 25)
  .attr("width", 200)
  .attr("height", 100)
  .attr("id", "fobject")
  .style("border-color", d3.scale.category20c())
  .append("xhtml:div")
  .style("font", "14px 'Helvetica Neue'")
  .html("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu enim quam.");

var innerSvg = svg.append("svg")
  .attr("x", 500)
  .attr("y", 10)
  .attr("id", "innerSvg");

var rect2 = innerSvg.append("svg:rect")
  .attr("rx", 6)
  .attr("ry", 6)
  .attr("x", 5/2)
  .attr("y", 5/2)
  .attr("id", "rect")
  .attr("width", 250)
  .attr("height", 125)
  .style("fill", 'white')
  .style("stroke", d3.scale.category20c())
  .style('stroke-width', 5);

var html2 = innerSvg.append("foreignObject")
  .attr("x", 50)
  .attr("y", 25)
  .attr("width", 200)
  .attr("height", 100)
  .attr("id", "fobject")
  .style("border-color", d3.scale.category20c())
  .append("xhtml:div")
  .style("font", "14px 'Helvetica Neue'")
  .html("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu enim quam.");

var drag1 = d3.behavior.drag()
    .on("drag", function(d,i) {
        d3.select(this).attr("transform", function(d,i){
            return "translate(" + [ d3.event.x,d3.event.y ] + ")"
        })
    });

var drag2 = d3.behavior.drag()
    .on("drag", function(d,i) {
        d3.select(this)
        .attr("x", d3.event.x)
        .attr("y", d3.event.y);
    });

group.call(drag1);
innerSvg.call(drag2);

I would very appreciate any explanation, naturally I prepared a working example here : http://jsfiddle.net/Y8y7V/

我非常感谢任何解释,自然我在这里准备了一个工作示例:http: //jsfiddle.net/Y8y7V/

回答by Lars Kotthoff

You simply need to set the origin()function accordingly. In the second case this is straightforward, in the first case somewhat more difficult because you are using coordinates as well as a transform. The basic pattern (for the second case) looks like this:

您只需要相应地设置origin()功能。在第二种情况下,这很简单,在第一种情况下有点困难,因为您使用坐标和变换。基本模式(对于第二种情况)如下所示:

 .origin(function() { 
        var t = d3.select(this);
        return {x: t.attr("x"), y: t.attr("y")};
    })

Updated jsfiddle here.

在这里更新了 jsfiddle 。

回答by Dimas51

group element has no x/y attributes - no problem! create ones:

group 元素没有 x/y 属性 - 没问题!创建:

var node = svg.append("g")
            .attr('x',x_1)
            .attr('y',y_1)
            .attr("class","node")
            .attr("name","Node_A")
            .attr("transform","translate(" + x_1 + ", " + y_1 +")")
            .call(drag);

when, the .origin function from Lars will work

什么时候,来自 Lars 的 .origin 函数会起作用

and dont forget to update x,y attributes, while dragging:

并且不要忘记在拖动时更新 x,y 属性:

function dragged() {

    d3.select(this).attr("transform","translate(" + d3.event.x + ", " + d3.event.y +")");
    d3.select(this).attr("x",d3.event.x);
    d3.select(this).attr("y",d3.event.y);
}