Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG basics: moving the endpoint of a line

Tags:

svg

snap.svg

I'd like to create a straight line in SVG that is anchored at one point. When the user clicks and drags the other endpoint, that endpoint follows their cursor. I'm using snap.svg for this.

My idea to do this was to first draw a line:

var line = paper.line( 300, 250, 450, 150 );

line.attr({
  stroke: "#000",
  strokeWidth: 5,
  strokeLinecap:"round"
});

then create a controlling circle that I track drag events on. In the drag callback I would update the x2 and y2 properties of the line using the dx and dy arguments passed.

The first thing I noticed is that simply setting the attributes causing things to blow up. I'm not entirely sure I understand why this is, but it seems like it might be the case that my callback is called repeatedly before it has a chance to run. Then when it 'catches up' to itself it somehow overshoots. I'm not too sure.

Anyway, through Googling I was able to determine that using the transform property on the controlling circle would allow me to emulate the default drag method:

var move = function(dx,dy) {
  // This appends the new transform to the original
  this.attr({
    transform: this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]
  });
} 

// Maybe this saves the current transform if it hasn't happened yet?
var start = function() {
  this.data('origTransform', this.transform().local );
}

var circle = paper.circle( 450, 150, 5 );

circle.drag(move, start);

At this point, I'm stuck. I can't use the same transform trick for the x2 and y2 attributes of the line. And if I set them directly I get that overshooting problem.

SVG pros – any thoughts on how to do this?

like image 995
jamesplease Avatar asked Jan 24 '26 02:01

jamesplease


1 Answers

I made sample code. http://jsdo.it/defghi1977/kxK1


var paper = Snap().attr({width:"500",height:"500"});
var line = paper.line(0,0,100,100)
    .attr({strokeWidth:5,stroke:"black",strokeLinecap:"round"});
var circle = paper.circle(100,100,10).attr({fill:"red"});
var x,y;
circle.drag(function(dx,dy){
    circle.attr({cx:+x+dx,cy:+y+dy});
    line.attr({x2:+x+dx,y2:+y+dy});
},function(){
    x = line.attr("x2");
    y = line.attr("y2");
},function(){});
like image 169
defghi1977 Avatar answered Jan 26 '26 01:01

defghi1977



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!