D3js:使用其中一个孩子拖动一个组 [英] D3js: Dragging a group by using one of it's children

查看:83
本文介绍了D3js:使用其中一个孩子拖动一个组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Jsfiddle: http://jsfiddle.net/6NBy2/

Jsfiddle: http://jsfiddle.net/6NBy2/

代码:

var in_editor_drag = d3.behavior.drag()
             .origin(function() {
                var g = this.parentNode;
                return {x: d3.transform(g.getAttribute("transform")).translate[0],
                        y: d3.transform(g.getAttribute("transform")).translate[1]};
            })
            .on("drag", function(d,i) {

                g = this.parentNode;
                translate = d3.transform(g.getAttribute("transform")).translate;
                x = d3.event.dx + translate[0],
                y = d3.event.dy + translate[1];
                d3.select(g).attr("transform", "translate(" + x + "," + y + ")");
                d3.event.sourceEvent.stopPropagation();
            });

svg = d3.select("svg");
d = {x: 20, y: 20 };
groups = svg
        .append("g")
        .attr("transform", "translate(20, 20)");

groups
    .append("rect")
        .attr("x", 0)
        .attr("y", 0)
        .attr("width", 100)
        .attr("height", 100)
        .style("fill", "green")
        .call(in_editor_drag)
        .style("opacity", 0.4);

我正在尝试使用其中一个子项作为句柄来拖动组。简单地说,我想要做的是,当拖动一个群组孩子时:

I'm trying to drag a group by using one of it's children as a handle. Simply, what i'm trying to do is, when a groups child is dragged:


  • 获取群组的翻译转换

  • 从d3.event.dx获取拖动距离,d3.event.dy

  • 将差异应用于组的转换属性

当孩子被拖动时,组不会按预期移动。它移动的距离小于拖动的距离,它开始在这里和那里跳跃。

When child dragged, group does not move as expected. It moves less than the dragged distance, and it begins to jump here and there.

我在这里做错了什么?

修改:

更新了jsfiddle: http://jsfiddle.net/6NBy2/2/

Updated jsfiddle: http://jsfiddle.net/6NBy2/2/

我试图通过使用一个或多个来拖动整个组它的子项是拖动句柄。

I'm trying to drag the whole group by using one or more of it's children as dragging handles.

推荐答案

这是一个老问题,但没有真正回答。我有完全相同的问题,并希望只有一个孩子(不是< g> 的所有子元素)拖动组。
问题是, d3.event.dx / y 的计算是相对于< g>的位置而言。一旦< g> 移动 .attr(transform,translate(x,y)) d3.event.dx / dy 被调整为新的(较小的)值。这导致了一个不稳定的运动。光标速度的一半。我找到了两个可能的解决方案:

This is an old question, but not really answered. I had exactly the same problem and wanted to drag the group by only one child (not all child elements of the <g>). The problem is, that the d3.event.dx/y is calculated relatively to the position of the <g>. And as soon as the <g> is moved by .attr("transform", "translate(x, y)"), the d3.event.dx/dy is adjusted to the new (smaller) value. This results in a jerky movement with approx. the half of the speed of the cursor. I found two possible solutions for this:

首先(最后我最终采用了这种方法):

将拖动手柄rect直接附加到svg而不是< g> 。因此它位于相对于< svg> 的位置,而不是< g> 。然后在拖动功能中移动两个(< rect> < g> )。

Append the drag handle rect directly to the svg and not to the <g>. So it is positioned relatively to the <svg> and not to the <g>. Then move both (the <rect> and the <g>) within the on drag function.

var svg = d3.select("svg");
var group = svg
    .append("g").attr("id", "group")
    .attr("transform", "translate(0, 0)");
group
    .append("rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .style("fill", "green")
    .style("opacity", 0.4);
group
    .append("text")
    .attr("x", 10)
    .attr("y", 5)
    .attr("dominant-baseline", "hanging")
    .text("drag me");
handle = svg
    .append("rect")
        .data([{
        // Position of the rectangle
        x: 0,
        y: 0
    }]) 
    .attr("class", "draghandle")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 20)
    .style("fill", "blue")
    .style("opacity", 0.4)
    .attr("cursor", "move")
    .call(d3.drag().on("drag", function (d) {
            console.log("yep");
            d.x += d3.event.dx;
            d.y += d3.event.dy;
            
            // Move handle rect
            d3.select(this)
                .attr("x", function (d) {
                    return d.x;
                })
                .attr("y", function (d) {
                    return d.y;
                });
            
            // Move Group
            d3.select("#group").attr("transform", "translate(" + [d.x, d.y] + ")");
    }));

<body>
    <svg width="400" height="400"></svg>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</body>

第二名:

检查哪个元素光标是在使用 d3.event.sourceEvent.path [0] 的拖动事件期间,并且只有在句柄< rect> <时才运行拖动功能单击/ code>。使用这种方法,所有元素都可以分组在一个< g> 中(不需要额外的< rect> 在集团外面)。这种方法的缺点是,如果光标在鼠标按下的情况下移动到拖动手柄上,也会执行拖动。

Check on which element the cursor was during the drag event with d3.event.sourceEvent.path[0] and run the drag function only if the handle <rect> was clicked. With this approach, all elements can be grouped within one <g> (no need for an additional <rect> outside the group). The downside of this method is, that the drag is also executed, if the cursor is moved over the drag handle with mouse down.

var svg = d3.select("svg");
var group = svg
    .append("g")
    .data([{
        // Position of the rectangle
        x: 0,
        y: 0
    }])
    .attr("id", "group")
    .attr("transform", function (d) {
            return "translate(" + d.x + ", " + d.y + ")"
    })
    .call(d3.drag().on("drag", function (d) {
        if (d3.event.sourceEvent.path[0].classList.value === "draghandle") {
            console.log("yep");
            d.x += d3.event.dx;
            d.y += d3.event.dy;
            d3.select(this).attr("transform", function (d) {
                return "translate(" + [d.x, d.y] + ")"
            })
        } else {
            console.log("nope");
            return;
        }
    }));
group
    .append("rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .style("fill", "green")
    .style("opacity", 0.4);
group
    .append("text")
    .attr("x", 10)
    .attr("y", 5)
    .attr("dominant-baseline", "hanging")
    .text("drag me");
handle = group
    .append("rect")
    .attr("class", "draghandle")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 20)
    .style("fill", "blue")
    .style("opacity", 0.4)
    .attr("cursor", "move");

<body>
    <svg width="400" height="400"></svg>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</body>

这篇关于D3js:使用其中一个孩子拖动一个组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆