MSJ
MSJ

Reputation: 41

Kinetic JS Dragbound function limit drag on line

If I have a kinetic line

for example:

line = new Kinetic.Line({

    x: 80,
    y:80,
    points: [10, 10, 60, 60, 60-headlen*Math.cos(angle-Math.PI/6),60-headlen*Math.sin(angle-Math.PI/6),60, 60, 60-headlen*Math.cos(angle+Math.PI/6),60-headlen*Math.sin(angle+Math.PI/6)],
    stroke: "green",
 //  draggable: true,
   strokeWidth: 4,
   name: "letter_arrow",
   offset: [140,140]




});

and say some circles

    var anchor = new Kinetic.Circle({
      x: x,
      y: y,
      stroke: 'red',
      fill: 'white',
      strokeWidth: 2,
      radius: 8,
      name: name,
      draggable: false,
      dragOnTop: false,
      //TODO SET THIS TO 0!!!!!
      opacity: 1
    });

where x and y will be the first 2 points of the line (10,10) and (60,60)

how can i make the circles drag bound, so that they can only be dragged on a imaginal line made through the first two points (10,10) and (60,60) i read the tutorials about drag bounds but i have no clue maybe you can help me

regards

Upvotes: 0

Views: 830

Answers (2)

Quentin
Quentin

Reputation: 1310

In MarkE's code, I believe the way to calculate anchor.b should be

anchor.b = y1 - anchor.slope * x1;

instead of

anchor.b = y1 / (anchor.slope * x1);

The formula is y = ax + b. That could cause the bad behavior. http://jsfiddle.net/UHwW9/26/

Upvotes: 0

markE
markE

Reputation: 105035

You can add a custom dragBoundFunc to limit your anchors movement to a line:

// dragBoundFunc will constrain your shape to your desired x/y
// you receive the current mouse position in pos.x and pos.y
// you return the x/y where you want the shape to be located 

dragBoundFunc: function(pos) {

    // get the mouse x position

    var x=pos.x;

    // if the mouse is left or right of the line
    // force the anchor to the far-left or far-right of the line

    if(x<lineMinX){ return({ x:lineMinX, y:lineMinY}); }
    if(x>lineMaxX){ return({ x:lineMaxX, y:lineMaxY}); }

    // if the mouse between the left and right points of the line
    // calc the desired y-position based on the formula: y = lineSlope * x + lineB

    return({x:x,y:lineSlope*x+lineB});
}

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/UHwW9/

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Prototype</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>

<style>
#container{
  border:solid 1px #ccc;
  margin-top: 10px;
  width:300px;
  height:300px;
}
</style>        
<script>
$(function(){

    var stage = new Kinetic.Stage({
        container: 'container',
        width: 300,
        height: 300
    });
    var layer = new Kinetic.Layer();
    stage.add(layer);

    var x1=10;
    var y1=10;
    var x2=60;
    var y2=60;

    var line=new Kinetic.Line({
        points:[x1,y1,x2,y2],
        stroke:"gray"
    });
    layer.add(line);

    var anchor1=newAnchor(x1,y1,x2,y2);

    function newAnchor(x1,y1,x2,y2){

        var anchor = new Kinetic.Circle({
            x: x1,
            y: y1,
            radius: 8,
            fill: 'skyblue',
            stroke: 'lightgray',
            strokeWidth: 3,
            draggable:true,
            dragBoundFunc: function(pos) {
                var x=pos.x;
                if(x<this.minX){
                    return({x:this.minX,y:this.minY});
                }
                if(x>this.maxX){
                    return({x:this.maxX,y:this.maxY});
                }
                return({x:x,y:this.slope*x+this.b});
            }

        });
        // dragBoundFunc stuff
        anchor.minX=x1;
        anchor.minY=y1;
        anchor.maxX=x2;
        anchor.maxY=y2;
        anchor.slope=(y1-y2)/(x1-x2);
        anchor.b=y1/(anchor.slope*x1);
        // 
        layer.add(anchor);
        layer.draw();
        return(anchor);
    }

}); // end $(function(){});

</script>       
</head>

<body>
    <button id="rotateBtn">rotate</button>
    <div id="container"></div>
</body>
</html>

Upvotes: 2

Related Questions