Reputation: 935
I have a case where I am creating a view pane, paths "inside" it. To give the impression the paths are inside I am clipping them. I would also like to be able to drag these paths. The usual suggestions is to use SVG transform
attribute. But this presents two problems:
Complete JSFiddle.
The data is:
var outlines = [
[{ "x": 100.0, "y": 100.0}, {"x": 200.0, "y": 100.0}, {"x": 200.0, "y": 200.0}, {"x": 100.0,"y": 200.0}, {"x": 100.0, "y": 100.0}],
[{ "x": -100.0, "y": 200.0}, {"x": 100.0, "y": 200.0}, {"x": 100.0, "y": 300.0}, {"x": -100.0,"y": 300.0}, {"x": -100.0, "y": 200.0}],
];
I create the paths like this:
layout
.selectAll('.instance')
.data(outlines)
.enter()
.append('path')
.attr('class', 'instance')
.attr('d', function(d) { return line(d); })
.call(drag);
And the drag is:
var drag = d3.behavior.drag()
.origin(function(d) {
return {
x: 0,
y: 0
};
})
.on("dragstart", function(d) {
d3.event.sourceEvent.stopPropagation();
})
.on("drag", function(d) {
d3.select(this)
.classed("dragging", true)
.attr('transform', function(d) { return 'translate(' + d3.event.x + ',' + d3.event.y + ')'; });
})
.on("dragend", function(d) {
d3.select(this)
.classed("dragging", false)
.attr('transform', null);
});
I think I would like to actually move the paths to the new location. But I am not sure how to manipulate the data with the d3.event offsets. How do I do that? Or are there better ways to do this?
Upvotes: 0
Views: 712
Reputation: 2100
To work properly, the transform
must be strictly inside the clip-path
(or to put it in another way, if an element has a clip-path and a transform attributes, then the coordinates of the clip-path are shifted just like the rest of the object.
The easy way to solve this in your case is to wrap your rectangles inside clip-path'd groups:
layout
.selectAll('.instance')
.data(outlines)
.enter()
.append("g") //this group defines the clipping
.attr("clip-path","url(#clip)")
.append('path') //this path can be moved around
.attr('class', 'instance')
.attr('d', function(d) {
return line(d);
})
.call(drag)
See https://jsfiddle.net/xhfcdbb7/
I've also removed all other references to clip-path (this way, the group remains clip to the same absolute rectangle, whether it is dragged or not)
Upvotes: 1