D3js:使用其中一个子级拖动组

D3js: Dragging a group by using one of it#39;s children(D3js:使用其中一个子级拖动组)
本文介绍了D3js:使用其中一个子级拖动组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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> 定位.然后在 on drag 函数中同时移动(<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> 时才运行拖动功能代码>被点击.使用这种方法,所有元素都可以在一个 <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.target.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:使用其中一个子级拖动组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)