如何检测DOM

编程入门 行业动态 更新时间:2024-10-23 13:25:07
如何检测DOM-draggables和FabricJS形状之间的冲突(How to detect collisions between DOM-draggables and FabricJS shapes)

我想在画布上拖动外部图像并且它与该画布对象相交时,找到画布中已经存在的对象。 这是我用于拖放的代码:

if (Modernizr.draganddrop) { // Browser supports HTML5 DnD. // Bind the event listeners for the image elements var images = document.querySelectorAll('#images img'); [].forEach.call(images, function (img) { img.addEventListener('dragstart', handleDragStart, false); img.addEventListener('dragend', handleDragEnd, false); }); // Bind the event listeners for the canvas var canvasContainer = document.getElementById('canvas-container'); canvasContainer.addEventListener('dragenter', handleDragEnter, false); canvasContainer.addEventListener('dragover', handleDragOver, false); canvasContainer.addEventListener('dragleave', handleDragLeave, false); canvasContainer.addEventListener('drop', handleDrop, false); } else { // Replace with a fallback to a library solution. alert("This browser doesn't support the HTML5 Drag and Drop API."); }

上面提到的回调函数是相应定义的。

我已经知道的是,当两个对象存在于画布中时,我们可以找到它们之间的交集。 链接: http : //fabricjs.com/intersection/

但我的问题是,当我将图像从画布外部拖动到画布区域并且它与画布对象相交时,我需要捕捉对象。

任何帮助将非常感激。 谢谢。

I would like to find object that is already present in the canvas as soon as I drag external image over canvas and it intersects with that canvas object. This is the code I am using for drag and drop:

if (Modernizr.draganddrop) { // Browser supports HTML5 DnD. // Bind the event listeners for the image elements var images = document.querySelectorAll('#images img'); [].forEach.call(images, function (img) { img.addEventListener('dragstart', handleDragStart, false); img.addEventListener('dragend', handleDragEnd, false); }); // Bind the event listeners for the canvas var canvasContainer = document.getElementById('canvas-container'); canvasContainer.addEventListener('dragenter', handleDragEnter, false); canvasContainer.addEventListener('dragover', handleDragOver, false); canvasContainer.addEventListener('dragleave', handleDragLeave, false); canvasContainer.addEventListener('drop', handleDrop, false); } else { // Replace with a fallback to a library solution. alert("This browser doesn't support the HTML5 Drag and Drop API."); }

above mentioned callback functions are defined accordingly.

What I already know is that we can find out the intersection between two objects when they are present within the canvas. Link: http://fabricjs.com/intersection/

But my problem is I need to catch the object while I am dragging image from outside the canvas onto the canvas area and it intersects with the canvas object.

Any help would be much appreciated. Thanks.

最满意答案

关于碰撞测试

基本形状往往有两种形式:矩形和圆形。

您需要这些测试来查看这些基本形状是否发生碰撞:

function rectsColliding(r1,r2){ return(!( r1.x > r2.x+r2.width || r1.x+r1.width < r2.x || r1.y > r2.y+r2.height || r1.y+r1.height < r2.y )); } function circlesColliding(c1,c2){ var dx=c2.x-c1.x; var dy=c2.y-c1.y; var sumR=c1.radius+c2.radius; return( dx*dx+dy*dy <= sumR*sumR ); } function rectCircleColliding(circle,rect){ var distX = Math.abs(circle.x - rect.x-rect.w/2); var distY = Math.abs(circle.y - rect.y-rect.h/2); if (distX > (rect.w/2 + circle.r)) { return false; } if (distY > (rect.h/2 + circle.r)) { return false; } if (distX <= (rect.w/2)) { return true; } if (distY <= (rect.h/2)) { return true; } var dx=distX-rect.w/2; var dy=distY-rect.h/2; return (dx*dx+dy*dy<=(circle.r*circle.r)); }

有关draggable的重要通知

本机html5 draggable系统仍然存在一些跨浏览器的不一致性。 当拖动拖拽时,很难获得准确的[x,y]位置。 相反,您可以使用jQueryUI可拖动系统来平滑浏览器之间的不一致性。

计划测试拖动的DOM元素是否与FabricJS形状发生碰撞

听取draggable上的dragmove事件, 在当前[x,y]位置创建一个可拖动的边界框, 创建Fabric.Rect的边界框。 此边界框必须由窗口中FabricJS画布的位置偏移, 调用rectsColliding函数来测试2个边界框是否发生碰撞, 根据DOM-draggable和Fabric.Rect是否发生冲突,做任何你需要的事情。

这是示例代码和演示:

// attach the canvas's bounding box to itself
var canvasElement=document.getElementById("c");
canvasElement.bb=canvasElement.getBoundingClientRect();

// create a wrapper around native canvas element (with id="c")
var canvas = new fabric.Canvas('c');
var rect;

// load an image and begin...
var image1=new Image();
image1.onload=function(){
  createFabrics();
  createDraggables();
}
image1.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png";

// create a fabric rect and add it to the stage
function createFabrics(){
  // create a rectangle object
  rect = new fabric.Rect({
    left: 100,
    top: 20,
    fill: 'green',
    width: 100,
    height: 75,
    lockMovementX:true,
    lockMovementY:true,
    lockScalingX:true,
    lockScalingY:true,
    lockRotation:true,
    hasControls:false,
  });
  rect.bb=rect.getBoundingRect();

  // "add" rectangle onto canvas
  canvas.add(rect);
  canvas.renderAll();
}

// Make the previously created image draggable
// Detect collisions between the image and the FabricJS rect
function createDraggables(){

  var $house=$("#house");
  var $canvas=$("#c");

  // make the canvas element a dropzone
  $canvas.droppable({ drop:dragDrop, hoverClass:'drop-hover' });

  // make the house draggable
  $house.draggable({
    helper:'clone',
    // optional event handlers are...
    start:dragstart,
    drag:dragmove,
    stop:dragend,
  });

  // set the data payload
  $house.data("image",image1); // key-value pair

  function dragstart(e,ui){}
  function dragend(e,ui){}
  function dragDrop(e,ui){}
  function dragmove(e,ui){
      var target=e.target;
      var tbb={
        left:ui.offset.left-canvasElement.bb.left,
        top:ui.offset.top-canvasElement.bb.top,
        width:target.width,
        height:target.height
      }
      if( rectsColliding(tbb,rect.bb) ){
        rect.fill='red';
        canvas.renderAll();
      }else{
        rect.fill='green';
        canvas.renderAll();
      }
  }


  function rectsColliding(r1,r2){
    return(!(
      r1.left          > r2.left+r2.width  ||
      r1.left+r1.width < r2.left           ||
      r1.top           > r2.top+r2.height  ||
      r1.top+r1.height < r2.top
    ));
  }


}  // end createDraggables 
  
body{ background-color: ivory; }
canvas{border:1px solid red;} 
  
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>

<script src="http://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>

<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>

<h4 id=hit>Drag house over green FabricJS rect.<br>Rect will turn red during collisions.</h4>
<img id="house" width=32 height=32 src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png"><br>
<canvas id='c' width=300 height=150></canvas> 
  
 

About testing for collisions

Basic shapes tend to come in 2 flavors: rectangular & circular.

You'll need these tests to see if any of these basic shapes are colliding:

function rectsColliding(r1,r2){ return(!( r1.x > r2.x+r2.width || r1.x+r1.width < r2.x || r1.y > r2.y+r2.height || r1.y+r1.height < r2.y )); } function circlesColliding(c1,c2){ var dx=c2.x-c1.x; var dy=c2.y-c1.y; var sumR=c1.radius+c2.radius; return( dx*dx+dy*dy <= sumR*sumR ); } function rectCircleColliding(circle,rect){ var distX = Math.abs(circle.x - rect.x-rect.w/2); var distY = Math.abs(circle.y - rect.y-rect.h/2); if (distX > (rect.w/2 + circle.r)) { return false; } if (distY > (rect.h/2 + circle.r)) { return false; } if (distX <= (rect.w/2)) { return true; } if (distY <= (rect.h/2)) { return true; } var dx=distX-rect.w/2; var dy=distY-rect.h/2; return (dx*dx+dy*dy<=(circle.r*circle.r)); }

An important notice about draggable

The native html5 draggable system still has some cross-browser inconsistencies. It's difficult to get an accurate [x,y] position when the draggable is being dragged. Instead, you can use the jQueryUI draggable system which has smoothed out the inconsistencies between browsers.

A plan to test if dragged DOM elements collide with FabricJS shapes

listen for the dragmove event on the draggable, Create a bounding box of the draggable at its current [x,y] position, Create a bounding box of the Fabric.Rect. This bounding box must be offset by the position of the FabricJS canvas in the window, Call the rectsColliding function to test if the 2 bounding boxes are colliding, Do whatever you need depending whether the DOM-draggable & Fabric.Rect are colliding.

Here's example code and a Demo:

// attach the canvas's bounding box to itself
var canvasElement=document.getElementById("c");
canvasElement.bb=canvasElement.getBoundingClientRect();

// create a wrapper around native canvas element (with id="c")
var canvas = new fabric.Canvas('c');
var rect;

// load an image and begin...
var image1=new Image();
image1.onload=function(){
  createFabrics();
  createDraggables();
}
image1.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png";

// create a fabric rect and add it to the stage
function createFabrics(){
  // create a rectangle object
  rect = new fabric.Rect({
    left: 100,
    top: 20,
    fill: 'green',
    width: 100,
    height: 75,
    lockMovementX:true,
    lockMovementY:true,
    lockScalingX:true,
    lockScalingY:true,
    lockRotation:true,
    hasControls:false,
  });
  rect.bb=rect.getBoundingRect();

  // "add" rectangle onto canvas
  canvas.add(rect);
  canvas.renderAll();
}

// Make the previously created image draggable
// Detect collisions between the image and the FabricJS rect
function createDraggables(){

  var $house=$("#house");
  var $canvas=$("#c");

  // make the canvas element a dropzone
  $canvas.droppable({ drop:dragDrop, hoverClass:'drop-hover' });

  // make the house draggable
  $house.draggable({
    helper:'clone',
    // optional event handlers are...
    start:dragstart,
    drag:dragmove,
    stop:dragend,
  });

  // set the data payload
  $house.data("image",image1); // key-value pair

  function dragstart(e,ui){}
  function dragend(e,ui){}
  function dragDrop(e,ui){}
  function dragmove(e,ui){
      var target=e.target;
      var tbb={
        left:ui.offset.left-canvasElement.bb.left,
        top:ui.offset.top-canvasElement.bb.top,
        width:target.width,
        height:target.height
      }
      if( rectsColliding(tbb,rect.bb) ){
        rect.fill='red';
        canvas.renderAll();
      }else{
        rect.fill='green';
        canvas.renderAll();
      }
  }


  function rectsColliding(r1,r2){
    return(!(
      r1.left          > r2.left+r2.width  ||
      r1.left+r1.width < r2.left           ||
      r1.top           > r2.top+r2.height  ||
      r1.top+r1.height < r2.top
    ));
  }


}  // end createDraggables 
  
body{ background-color: ivory; }
canvas{border:1px solid red;} 
  
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>

<script src="http://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>

<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>

<h4 id=hit>Drag house over green FabricJS rect.<br>Rect will turn red during collisions.</h4>
<img id="house" width=32 height=32 src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png"><br>
<canvas id='c' width=300 height=150></canvas> 
  
 

更多推荐

本文发布于:2023-08-07 12:17:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1464254.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:DOM

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!