Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move elements along with svg group

Tags:

d3.js

I have a circle that gets appended on drag drop. I want the circle to move along with group when I move the group around with mouse

Here's what I have tried which isn't working:

//targetG is the group element

targetG.append("rect")
                        .attr("fill", "none")
                        .style("stroke", "black")
                        .style("stroke-width", "2px")
                        .attr("width", 200)
                        .attr("height", 200)
                        .style("fill", "white")
                        .call(
                                d3.behavior.drag()
                                .on('drag', moveRect).origin(function () {
                            var t = d3.select(this);
                            return {x: t.attr("x"), y: t.attr("y")};
                        }));

Here's the full code in fiddle: http://jsfiddle.net/vk62y7un/

like image 515
kittu Avatar asked Jul 16 '15 07:07

kittu


2 Answers

There's a couple of small problems that need to be fixed.


Your translate component split function is splitting by ,.

translate = (translate.substring(0, translate.indexOf(")"))).split(",");

While this works in Chrome, it should be splitting by space for IE.

translate = (translate.substring(0, translate.indexOf(")"))).split(",");
if (translate.length === 1)
    translate = translate[0].split(' ');

The circle wasn't being attached to the g because of this.


Your (container) drag event is attached to the rectangle inside the g. This should be attached to the g instead. Correspondingly the drag functions should manipulate the transform (translate) attribute and not the x and y.

var targetG = svg.append("g")
        .attr("transform", "translate(150,150)")
        .call(
        d3.behavior.drag()
        .on('drag', moveRect).origin(function () {
        ...

and

function moveRect() {
    d3.select(this)
            .attr('transform', 'translate(' + d3.event.x + ' ' + d3.event.y +')');
}

The origin (for the g now) should be the (parsed) transform (translate) attribute at the start of the drag.

        ....
        var tc = d3.select(this).attr('transform').replace(/[a-z()]/g, '').split(' ');
        if (tc.length === 1)
            tc = tc[0].split(',')
        return { x: Number(tc[0]), y: Number(tc[1]) };
    }));

Notice, the ===1 check and split - that's so that it works in IE and Chrome.


Fiddle (works in IE and Chrome) - http://jsfiddle.net/3hyu6om8/

like image 90
potatopeelings Avatar answered Sep 18 '22 22:09

potatopeelings


The problem is when you try to drag rectangle you don't select circles. I made some changes and you could drag circles along rectangle.

Add this part to your code:

var groupAll = d3.behavior.drag()
        .origin(Object)
        .on("drag", function(d, i) {
        var child = this;
        var move = d3.transform(child.getAttribute("transform")).translate;
        var x = d3.event.dx + move[0];
        var y = d3.event.dy + move[1];
        d3.select(child).attr("transform", "translate(" + x + "," + y +   ")");

        }); 

Complete Code here.

like image 42
Gabriel Avatar answered Sep 20 '22 22:09

Gabriel