Welcome to Code Forum!

Join a community that supports you and your coding journey from day one. We strive to be a friendly, supportive community that empowers everyone to be better developers. By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.

    GIF shows where to locate </> in the thread and or post editor toolbar.
    To learn more about how to use our BBCode feature, review our "How to post your code into threads" here.

    Thank you, Code Forum.

JavaScript Konva collission doesn't stop dragging over element

udarts

New Coder
I am using Konva to drag and detect collision, that works, but what I want to do is prevent to be able to drag over an item when the collision has been detected, I am not able to.

I know about: dragBoundFunc, but that works with absolute positioning and the haveIntersection works with the relative positioning of the elements. So that is not handy.

Sample code:

Code:
<!DOCTYPE html>
<html>
  <head>
    <script src="https://unpkg.com/[email protected]/konva.min.js"></script>
    <meta charset="utf-8" />
    <title>Konva Drag and Drop Collision Detection Demo</title>
    <style>
      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
        background-color: #f0f0f0;
      }
    </style>
  </head>

  <body>
    <div id="container"></div>
    <script>
      var width = window.innerWidth;
      var height = window.innerHeight;

      var stage = new Konva.Stage({
        container: 'container',
        width: width,
        height: height,
      });

      var layer = new Konva.Layer();
      stage.add(layer);

      function createShape() {
        var group = new Konva.Group({
          x: Math.random() * width,
          y: Math.random() * height,
          draggable: true,
        });
        var shape = new Konva.Rect({
          width: 30 + Math.random() * 30,
          height: 30 + Math.random() * 30,
          fill: 'grey',
          rotation: 360 * Math.random(),
          name: 'fillShape',
        });
        group.add(shape);

        var boundingBox = shape.getClientRect({ relativeTo: group });

        var box = new Konva.Rect({
          x: boundingBox.x,
          y: boundingBox.y,
          width: boundingBox.width,
          height: boundingBox.height,
          stroke: 'red',
          strokeWidth: 1,
        });
        group.add(box);
        return group;
      }

      for (var i = 0; i < 10; i++) {
        layer.add(createShape());
      }
      layer.on('dragmove', function (e) {
        var target = e.target;
        var targetRect = e.target.getClientRect();
        layer.children.forEach(function (group) {
          // do not check intersection with itself
          if (group === target) {
            return;
          }
          if (haveIntersection(group.getClientRect(), targetRect)) {
            console.log('tar', target);
            console.log('tarRec', targetRect);
            group.findOne('.fillShape').fill('red');
            target.attrs.x(target._lastPos.x);
          } else {
            group.findOne('.fillShape').fill('grey');
          }
        });
      });

      function haveIntersection(r1, r2) {
        return !(
          r2.x > r1.x + r1.width ||
          r2.x + r2.width < r1.x ||
          r2.y > r1.y + r1.height ||
          r2.y + r2.height < r1.y
        );
      }
    </script>
  </body>
</html>
 
Hey! So I’ve never actually worked with Konva before 😅, but after a bit of Googling, I think I found something that could help! It looks like you can prevent dragging over an item by resetting the position when a collision is detected. You can use target.position(target._lastPos) to return it to the last valid position.

Here’s a quick tweak to your code:

Code:
layer.on('dragmove', function (e) {var target = e.target;var targetRect = target.getClientRect();var hasCollision = false;

layer.children.forEach(function (group) {if (group === target) return; // don’t check itself
 
<span>if</span> (haveIntersection(<span>group</span>.getClientRect(), targetRect)) {<br>  <span>group</span>.findOne(<span>'.fillShape'</span>).fill(<span>'red'</span>);<br>  hasCollision = <span>true</span>;<br>} <span>else</span> {<br>  <span>group</span>.findOne(<span>'.fillShape'</span>).fill(<span>'grey'</span>);<br>}<br>
});

// If there’s a collision, snap it backif (hasCollision) {target.position(target._lastPos);}});

Hope this helps even though I’m not super familiar with the library! Let me know if it works. 🙂
 
T
Hey! So I’ve never actually worked with Konva before 😅, but after a bit of Googling, I think I found something that could help! It looks like you can prevent dragging over an item by resetting the position when a collision is detected. You can use target.position(target._lastPos) to return it to the last valid position.

Here’s a quick tweak to your code:

Code:
layer.on('dragmove', function (e) {var target = e.target;var targetRect = target.getClientRect();var hasCollision = false;

layer.children.forEach(function (group) {if (group === target) return; // don’t check itself
 
<span>if</span> (haveIntersection(<span>group</span>.getClientRect(), targetRect)) {<br>  <span>group</span>.findOne(<span>'.fillShape'</span>).fill(<span>'red'</span>);<br>  hasCollision = <span>true</span>;<br>} <span>else</span> {<br>  <span>group</span>.findOne(<span>'.fillShape'</span>).fill(<span>'grey'</span>);<br>}<br>
});

// If there’s a collision, snap it backif (hasCollision) {target.position(target._lastPos);}});

Hope this helps even though I’m not super familiar with the library! Let me know if it works. 🙂
Thanks for your reply. It seems that the _lastPos is an absolute position. And that doesn't seem to be the correct, since target.getClientRect() includes a relative position. I've tried to look for the option to convert absolute to relative position, but not able to find it.
 

Buy us a coffee!

Buy me a coffee.
Back
Top Bottom