2011-12-23 40 views
21

Khi tôi kéo một phần tử qua một số khác div mà tôi có sự kiện di chuột qua, sự kiện không kích hoạt. Tuy nhiên, nó hoạt động nếu tôi di chuột qua nó mà không cần kéo.Cách bắt đầu sự kiện di chuột khi kéo

Có cách nào để phát hiện sự kiện di chuột trên một phần tử không nếu tôi kéo một số khác lên nó?

+0

Bạn có đang sử dụng jQuery UI không? – Purag

+0

Không, tôi đang sử dụng kéo được tạo tùy chỉnh – user969724

+0

Nó sẽ giúp thấy mã đó. Hoặc đặt nó trong câu hỏi hoặc dán nó vào một [jsfiddle] (http://jsfiddle.net). – Purag

Trả lời

13

Đây là ví dụ sử dụng giải pháp tọa độ XY.

Working example on jsfiddle

Ví dụ có thể được cải thiện, nhưng là một điểm khởi đầu tốt.

Chỉ cần theo dõi vị trí chuột và kiểm tra xem nó có nằm trong bất kỳ hộp giới hạn nào của đối tượng có thể phân tách hay không. Do đó, nếu sự kiện mouseup kích hoạt trên bất kỳ một trong số chúng, đối tượng kéo sẽ bị loại bỏ. Bạn cũng có thể sử dụng tọa độ của đối tượng mà bạn đang kéo để phát hiện nếu nó nằm trên hộp có thể di chuyển được, nhưng nó đòi hỏi mã nhiều hơn một chút để tìm kiếm các thanh co hẹp và sử dụng chuột đủ cho tôi.

Mã sử ​​dụng jQuery nhưng không có jQueryUI. Tôi đã thử nghiệm trong Chrome, Firefox và Opera, nhưng không phải là IE :)

Tôi cũng đang thêm mã vào đây nếu không thể truy cập jsfiddle.

HTML

<p>Drag orange boxes to grey ones</p> 
<div class="droppable"></div> 
<div class="droppable"></div> 
<div class="droppable"></div> 
<div class="droppable"></div> 

<div class="draggable"></div> 
<div class="draggable"></div> 
<div class="draggable"></div> 

CSS

.droppable { 
    width:50px; 
    height:50px; 
    float: left; 
    background-color: #DDD; 
    margin: 5px; 
} 

.draggable { 
    width:40px; 
    height:40px; 
    float: right; 
    background-color: #FC0; 
    margin: 5px; 
    cursor: pointer; 
} 

.dropped { 
    background-color: #FC0; 
} 

.somethingover { 
    background-color: #FCD; 
} 

JS

var dragged, mousex, mousey, coordinates = []; 

var continueDragging = function(e) { 
    // Change the location of the draggable object 
    dragged.css({ 
     "left": e.pageX - (dragged.width()/2), 
     "top": e.pageY - (dragged.height()/2) 
    }); 

    // Check if we hit any boxes 
    for (var i in coordinates) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       // Lets change the background color 
       coordinates[i].dom.addClass("somethingover"); 
      } 
     } else { 
      // Nope, we did not hit any objects yet 
      coordinates[i].dom.removeClass("somethingover"); 
     } 
    } 

    // Keep the last positions of the mouse coord.s 
    mousex = e.pageX; 
    mousey = e.pageY; 
} 

var endDragging = function(e) { 
    // Remove document event listeners 
    $(document).unbind("mousemove", continueDragging); 
    $(document).unbind("mouseup", endDragging); 

    // Check if we hit any boxes 
    for (var i in coordinates) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       droptarget = coordinates[i].dom; 
       droptarget.removeClass("somethingover").addClass("dropped"); 
       dragged.hide("fast", function() { 
        $(this).remove(); 
       }); 
      } 
     } 
    } 

    // Reset variables 
    mousex = 0; 
    mousey = 0; 
    dragged = null; 
    coordinates = []; 
} 

var startDragging = function(e) { 
    // Find coordinates of the droppable bounding boxes 
    $(".droppable").each(function() { 
     var lefttop = $(this).offset(); 
     // and save them in a container for later access 
     coordinates.push({ 
      dom: $(this), 
      left: lefttop.left, 
      top: lefttop.top, 
      right: lefttop.left + $(this).width(), 
      bottom: lefttop.top + $(this).height() 
     }); 
    }); 

    // When the mouse down event is received 
    if (e.type == "mousedown") { 
     dragged = $(this); 
     // Change the position of the draggable 
     dragged.css({ 
      "left": e.pageX - (dragged.width()/2), 
      "top": e.pageY - (dragged.height()/2), 
      "position": "absolute" 
     }); 
     // Bind the events for dragging and stopping 
     $(document).bind("mousemove", continueDragging); 
     $(document).bind("mouseup", endDragging); 
    } 
} 

// Start the dragging 
$(".draggable").bind("mousedown", startDragging); 
+0

Lúc đầu tôi hơi hoài nghi nhưng kỹ thuật này đã làm việc rất tốt cho tôi - cảm ơn rất nhiều! – OrganicPanda

+0

giải pháp tuyệt vời! cảm ơn !! – Denis

3

Có hai cách cơ bản bạn có thể làm điều này:

  1. theo dõi mousemove và phản ứng với x/y phối
  2. có một mục tiêu rõ ràng rằng có một z-index cao hơn container kéo

Tùy chọn đầu tiên không thực sự sử dụng sự kiện di chuột qua, nhưng sẽ cung cấp cho bạn kết quả tương tự. Hãy lưu ý rằng một số trình duyệt (tức là) sẽ không kích hoạt mouseover trên các phần tử trong suốt, vì vậy bạn phải giả mạo nó bằng cách đặt hình nền trong suốt hoặc đặt hình ảnh ngẫu nhiên làm nền và định vị nó bên ngoài phần tử như thế này :

element { 
background: url(/path/to/img) no-repeat -10000px 0; 
} 
+0

Điều đó có thể * can thiệp vào phần tử đang được kéo, tùy thuộc vào cách thiết lập nó. – Purag

0

modifing một chút mã đăng bởi emrahgunduz, đặc biệt là vòng lặp for, bạn cũng có thể quản lý diện tích droppable lồng nhau.

var dragged, mousex, mousey, coordinates = []; 

var continueDragging = function(e) { 
    // Change the location of the draggable object 
    dragged.css({ 
     "left": e.pageX - (dragged.width()/2), 
     "top": e.pageY - (dragged.height()/2) 
    }); 

    // Check if we hit any boxes 
    for (var i = coordinates.length - 1; i >= 0; i--) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       // Lets change the background color 
       $('.droppable').removeClass("somethingover"); 
       coordinates[i].dom.addClass("somethingover"); 
       break; 
      } 
     } else { 
      // Nope, we did not hit any objects yet 
      coordinates[i].dom.removeClass("somethingover"); 
     } 
    } 

    // Keep the last positions of the mouse coord.s 
    mousex = e.pageX; 
    mousey = e.pageY; 
}; 

var endDragging = function(e) { 
    // Remove document event listeners 
    $(document).unbind("mousemove", continueDragging); 
    $(document).unbind("mouseup", endDragging); 

    // Check if we hit any boxes 
    for (var i = coordinates.length - 1; i >= 0; i--) { 
     if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
      if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
       // Yes, the mouse is on a droppable area 
       droptarget = coordinates[i].dom; 
       droptarget.removeClass("somethingover").addClass("dropped"); 
       dragged.hide("fast", function() { 
        $(this).remove(); 
       }); 
      } 
     } 
    } 

    // Reset variables 
    mousex = 0; 
    mousey = 0; 
    dragged = null; 
    coordinates = []; 
}; 

var startDragging = function(e) { 
    // Find coordinates of the droppable bounding boxes 
    $(".droppable").each(function() { 
     var lefttop = $(this).offset(); 
     // and save them in a container for later access 
     coordinates.push({ 
     dom: $(this), 
     left: lefttop.left, 
     top: lefttop.top, 
     right: lefttop.left + $(this).width(), 
     bottom: lefttop.top + $(this).height() 
    }); 
}; 

// When the mouse down event is received 
if (e.type == "mousedown") { 
    dragged = $(this); 
    // Change the position of the draggable 
    dragged.css({ 
     "left": e.pageX - (dragged.width()/2), 
     "top": e.pageY - (dragged.height()/2), 
     "position": "absolute" 
    }); 
    // Bind the events for dragging and stopping 
    $(document).bind("mousemove", continueDragging); 
    $(document).bind("mouseup", endDragging); 
} 

// Start the dragging 
$(".draggable").bind("mousedown", startDragging); 
6

Trong tất cả các câu trả lời được trình bày, tôi không nhìn thấy câu trả lời đơn giản và rõ ràng nhất (có thể tôi đang thiếu điều gì đó trong câu hỏi OP). Nhưng, nếu ai đó vấp ngã khi sau này, và cần giải pháp nhanh và đơn giản trong JS tinh khiết ..

Bạn làm điều đó bằng cách thay đổi yếu tố className ondragover, và thay đổi trở lại lớp gốc ondragleave

my_element.ondragover = function(ev) { 
ev.preventDefault(); 
this.className = 'myElem_dragover'; 
} 
my_element.ondragleave = function(ev) { 
ev.preventDefault(); 
this.className = 'myElem_orig'; 
} 

CSS

.myElem_orig {  //this is your initial class for element 
    top: 30px; 
    left: 20px; 
    ..... 
    background-color: blue; 
} 

.myElem_orig:hover { //this is hover state, just changing bg color 
    background-color: red; 
} 

.myElem_dragover { //new class, needs all attributes from original class 
    top: 30px; 
    left: 20px; 
    ........ 
    background-color: red; //behaves the same like hover does 
} 

chỉnh sửa:
quên ment ion, bạn cần phải mang lại lớp gốc ondrop quá, nếu không div sẽ ở trong lớp kéo lên

+1

Tôi cho rằng câu hỏi này được cập nhật trước khi sử dụng rộng rãi thuộc tính có thể kéo HTML được tích hợp sẵn, đây chắc chắn là cách dễ nhất để thoát trừ khi bạn đang thực hiện các hành vi tùy chỉnh. –

+0

Đó là những gì tôi đang tìm kiếm, không phải bất kỳ hành vi tùy chỉnh nào. Cảm ơn. – Wellyngton

+0

Tôi đồng ý với greg. Câu trả lời này là tuyệt vời bây giờ-một-ngày và sẽ nhận được phổ biến rất sớm tôi cảm thấy. –

0

Tìm thấy một lỗi nhỏ trong ví dụ jsfiddle. Khi bạn rời khỏi khu vực thả theo chiều dọc, khu vực thả vẫn có lớp 'somethinghover'.

http://jsfiddle.net/MAazv

Thay thế này

if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) { 
 
    if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
 
    // Yes, the mouse is on a droppable area 
 
    // Lets change the background color 
 
    coordinates[i].dom.addClass("somethingover"); 
 
    } 
 
} else { 
 
    // Nope, we did not hit any objects yet 
 
    coordinates[i].dom.removeClass("somethingover"); 
 
}

http://jsfiddle.net/MAazv/122

với điều này:

if (mousex >= coordinates[i].left && mousex <= coordinates[i].right && mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) { 
 
    // Yes, the mouse is on a droppable area 
 
    // Lets change the background color 
 
    coordinates[i].dom.addClass("somethingover"); 
 
} else { 
 
    // Nope, we did not hit any objects yet 
 
    coordinates[i].dom.removeClass("somethingover"); 
 
}

Các vấn đề liên quan