Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

javascript - Kineticjs dragBoundFunc for a rect in a rect

i have following code to drag a smaller rect in a bigger rect.

it is almost working, but its possible to move the orange rect out of the white one. Is there any solution for this behavior?? that the bigger rect is the dragborder for the small rect??

And another question... would it be possible to do it for a rect in any polygon as border?

<!DOCTYPE HTML>
<html>
<head>
 <style>
  body {margin: 0px; padding: 20px;}
  canvas {border: 1px solid #777;}
 </style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.3.2.js"></script>
<script>
    var stage = new Kinetic.Stage({
        container: 'container',
        width: 300,
        height: 300
    });
    var layer = new Kinetic.Layer();

    // White box
    var white = new Kinetic.Rect({
        x: 100,
        y: 50,
        width: 150,
        height: 100,
        fill: 'white',
        stroke: 'black',
        strokeWidth: 2
    });

    // orange box
    var orange = new Kinetic.Rect({
        x: 150,
        y: 100,
        width: 50,
        height: 30,
        fill: 'orange',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true,
        // this causes orange box to be stopped if try to leave white box
        dragBoundFunc: function(pos){
            if(theyAreColliding(orange,white)){
                 // orange box is touching white box
                 // let it move ahead
                return ({ x:pos.x, y:pos.y });
            } else{
                 // orange box is not touching white box
                 // don't let orange box move outside
                if (white.getY() > orange.getY()){
                    return({x: pos.x, y: white.getY()+1});
                }
                else if (white.getY() + white.getHeight() - orange.getHeight() < orange.getY()){
                    return({x: pos.x, y: white.getY() + white.getHeight() - orange.getHeight() -1});
                }
                else if (white.getX() > orange.getX()){
                    return({x: white.getX() +1, y: pos.y})
                }
                else if (white.getX() + white.getWidth() - orange.getWidth() < orange.getX()){
                    return({x: white.getX() +white.getWidth() - orange.getWidth() -1, y: pos.y})
                }
            }
        }
    });

    function theyAreColliding(rect1, rect2) {
        return !(rect2.getX() > rect1.getX() ||
                 rect2.getX() + rect2.getWidth() - rect1.getWidth() < rect1.getX() || 
                 rect2.getY() > rect1.getY() ||
                 rect2.getY() + rect2.getHeight() - rect1.getHeight() < rect1.getY());
    }

    layer.add(white);
    layer.add(orange);
    stage.add(layer);

</script>
</body>
</html>

and also the jsfiddle link: http://jsfiddle.net/dNfjM/

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is an improved way of setting your dragBoundFunc

The secret with dragBoundFunc is to allow it to execute fast. Remember that it is being executed with every mousemove.

So, pre-calculate all the minimum and maximum boundaries before and outside dragBoundFunc, like this:

    // pre-calc some bounds so dragBoundFunc has less calc's to do
    var height=orangeRect.getHeight();
    var minX=white.getX();
    var maxX=white.getX()+white.getWidth()-orangeRect.getWidth();
    var minY=white.getY();
    var maxY=white.getY()+white.getHeight()-orangeRect.getHeight();

That way your dragBoundFunc can just test the current position against these pre-calc’ed bounds like this:

      dragBoundFunc: function(pos) {
          var X=pos.x;
          var Y=pos.y;
          if(X<minX){X=minX;}
          if(X>maxX){X=maxX;}
          if(Y<minY){Y=minY;}
          if(Y>maxY){Y=maxY;}
          return({x:X, y:Y});
      }

Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/n5xMs/

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 10px;
      }
      canvas{border:1px solid red;}
    </style>
  </head>
    <body>
      <div id="container"></div>
      <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.4.1.min.js"></script>
      <script>
        var stage = new Kinetic.Stage({
          container: 'container',
          width: 400,
          height: 400
        });
        var layer = new Kinetic.Layer();

        var white = new Kinetic.Rect({
            x: 20,
            y: 20,
            width: 300,
            height: 300,
            fill: 'white',
            stroke: 'black',
            strokeWidth: 2
        });

        var orangeGroup = new Kinetic.Group({
          x: stage.getWidth() / 2,
          y: 70,
          draggable: true,
          dragBoundFunc: function(pos) {
              var X=pos.x;
              var Y=pos.y;
              if(X<minX){X=minX;}
              if(X>maxX){X=maxX;}
              if(Y<minY){Y=minY;}
              if(Y>maxY){Y=maxY;}
              return({x:X, y:Y});
          }
        });

        var orangeText = new Kinetic.Text({
          fontSize: 26,
          fontFamily: 'Calibri',
          text: 'boxed in',
          fill: 'black',
          padding: 10
        });

        var orangeRect = new Kinetic.Rect({
          width: orangeText.getWidth(),
          height: orangeText.getHeight(),
          fill: 'orange',
          stroke: 'blue',
          strokeWidth: 4
        });

        orangeGroup.add(orangeRect).add(orangeText);
        layer.add(white);
        layer.add(orangeGroup);
        stage.add(layer);

        // pre-calc some bounds so dragBoundFunc has less calc's to do
        var height=orangeRect.getHeight();
        var minX=white.getX();
        var maxX=white.getX()+white.getWidth()-orangeRect.getWidth();
        var minY=white.getY();
        var maxY=white.getY()+white.getHeight()-orangeRect.getHeight();

      </script>
  </body>
</html>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...