2015-06-01 13 views
6

Một vấn đề với sự kiện tiêu chuẩn mouseout là nó không chỉ dừng khi con trỏ rời khỏi vùng màn hình được bao quanh bởi chu vi ngoài của phần tử, mà còn khi con trỏ di chuyển qua một số phần tử khác có trong chu vi này.Làm thế nào để đạt được hiệu ứng mouseleave với các hậu duệ không được định vị hoàn toàn?

Lý do cho sự kiện mouseleave của jQuery là chỉ báo hiệu chỉ thời điểm con trỏ rời khỏi khu vực được bao quanh bởi chu vi ngoài của phần tử.

Thật không may, điều này dường như chỉ hoạt động nếu phần tử "cản trở" là hậu duệ của phần tử "bị che khuất". Nếu phần tử "cản trở" nằm ở vị trí tuyệt đối, thì khi chuột di chuột qua nó, sự kiện mouseleave trên phần tử "bị che khuất" bị bắn.

Ví dụ, với đoạn HTML sau:

<div id="b-div"> 
    <div id="d-div"><span>d</span></div> 
</div> 
<div id="c-div"><span>c</span></div> 

... #d-div là một bona fide-hậu duệ của #b-div, trong khi #c-div là không, nhưng, nhưng chúng tôi có thể tạo kiểu nó để nó "cản trở "#b-div đều giống nhau. Điều này được minh họa trong this jsFiddle.

Nếu bây giờ một định nghĩa các sự kiện sau đây trên #b-div:

$('#b-div').bind({ 
    mouseenter: function() { 
     $(this).addClass('outlined'); 
    }, 
    mouseleave: function() { 
     $(this).removeClass('outlined'); 
    } 
}); 

... sau đó lơ lửng chuột trong phạm vi vành đai ngoài #b-div 's gây ra một phác thảo màu xanh xuất hiện trên vành đai này, trừ chuột là trên #c-div.

Có cách nào để có được hiệu quả tương tự với #b-div#c-divmouseleave đạt được với #b-div#d-div?

EDIT: Tôi đã sửa ví dụ được hiển thị trong jsFiddle. Phiên bản gốc của ví dụ này cho thấy trường hợp đặc biệt không đại diện trong đó tất cả các phần tử cản trở chồng chéo với phần tử bị che khuất. Trong trường hợp đặc biệt này, hiệu ứng mong muốn có thể là được mô phỏng bằng cách xác định các sự kiện tương tự trên cả phần cản trở và các yếu tố cản trở, do đó, có hiệu lực, biến phần tử cản trở thành bản vá của phần tử bị che khuất. Điều này sẽ không hoạt động khi phần tử cản trở không được chứa hoàn toàn trong phạm vi ngoài của phần tử bị che khuất (như được chỉ ra trong jsFiddle đã sửa đổi). Nói chung, bất kỳ giải pháp nào dựa trên việc sử dụng sự kiện mouseover trên phần tử cản trở sẽ bị lỗi, vì sự cố thực sự là ngăn (hoặc không hiệu quả) giả mạo mouseleave trên phần tử bị che khuất.

+0

Ý anh là như thế này -> ** https: //jsfiddle.net/adeneo/q1Lgzr4c/1/** – adeneo

+0

@adeneo: nó quay ra rằng ví dụ minh họa ban đầu của tôi một chút trường hợp đặc biệt không đại diện; Tôi đã cập nhật ví dụ để sửa lỗi này. Xin lỗi vì điều đó. – kjo

+0

Điều gì gần như hoạt động là kiểm tra 'e.relatedTarget' https://jsfiddle.net/p5yf0dcs/2/ Vấn đề là bây giờ bạn sẽ không mất điểm nổi bật khi thoát ra khỏi' b-div' –

Trả lời

7

này, dựa trên bài đầu tiên của bạn, trong đó #c-div được hoàn toàn chứa trong #b-div:

$('#b-div, #c-div').on({ 
    mouseenter: function (ev) { 
    $('#b-div').addClass('outlined'); 
    }, 
    mouseleave: function (ev) { 
    $('#b-div').removeClass('outlined'); 
    } 
}); 

Fiddle 1


Kể từ #c-div có thể không luôn luôn được chứa hoàn toàn trong vòng #b-div, bạn có thể sử dụng mã hiện tại của bạn nếu bạn thêm kiểu này:

#c-div { 
    pointer-events: none; 
} 

Nhưng điều này sẽ làm cho tôi không thể tương tác với #c-div bằng chuột.

Fiddle 2


Nếu bạn làm cần phải tương tác với #c-div, nó không hoàn toàn trong vòng #b-div, bạn có thể sử dụng Element.getBoundingClientRect như thế này:

$('#b-div, #c-div').on('mousemove mouseleave', 
    function(ev) { 
    var br= $('#b-div')[0].getBoundingClientRect(); 
    $('#b-div').toggleClass(
     'outlined', 
     ev.pageX > br.left && ev.pageX < br.left+br.width && 
     ev.pageY > br.top && ev.pageY < br.top +br.height 
    ) 
    } 
); 

Fiddle 3

+0

Khi nhìn thấy giải pháp của bạn, tôi nhận ra rằng ví dụ ban đầu của tôi là thiếu sót nghiêm trọng. Tôi đã sửa nó ngay bây giờ. Tôi tin tưởng rằng với phiên bản mới nó sẽ rõ ràng hơn tại sao các giải pháp như một bạn đề xuất sẽ không hoạt động nói chung (lơ lửng trên các phần của yếu tố cản trở không chồng chéo với yếu tố cản trở không được kích hoạt ' sự kiện mouseenter'). Tôi xin lỗi vì sự thiếu rõ ràng trong bài đăng gốc của tôi. – kjo

+1

Bạn có thể thêm 'pointer-events: none' vào kiểu' # c-div' - * trừ khi * nó có nội dung mà bạn cần tương tác bằng chuột. –

+0

@kjo bạn vẫn cần câu trả lời hay bạn đã tìm thấy giải pháp vấn đề – MaxZoom

0

Nếu bạn không thể sử dụng các đề xuất của Rich là pointer-events: none (có thể bạn cần support IE 10 hoặc bạn cần tương tác với div được định vị hoàn toàn), bạn có thể kiểm tra thủ công sự kiện sẽ không #c-div sử dụng relatedTarget.

Tuy nhiên, bạn cũng phải kiểm tra xem con mouseleave từ #c-div sẽ không bị #b-div hay không.

$('#b-div').bind({ 
 
    mouseenter: function() { 
 
     $(this).addClass('outlined'); 
 
    }, 
 
    mouseleave: function (e) { 
 
     if (e.relatedTarget.id == 'c-div' || $.contains(document.getElementById('c-div'), e.relatedTarget)) { 
 
      return; 
 
     } 
 
     $(this).removeClass('outlined'); 
 
    } 
 
}); 
 

 
$('#c-div').bind({ 
 
    mouseleave: function (e) { 
 
     if (e.relatedTarget.id == 'b-div' || $.contains(document.getElementById('b-div'), e.relatedTarget)) { 
 
      return; 
 
     } 
 
     $('#b-div').removeClass('outlined'); 
 
    } 
 
});
#a-div { 
 
    position: relative; 
 
    margin: 20px; 
 
} 
 
#b-div { 
 
    height: 100px; 
 
    width: 100px; 
 
    background-color: #555; 
 
    padding: 50px; 
 
} 
 
#c-div { 
 
    position: absolute; 
 
    height: 50px; 
 
    width: 200px; 
 
    top: 100px; 
 
    left: 100px; 
 
    background-color: #999; 
 
} 
 
#d-div { 
 
    height: 50px; 
 
    width: 50px; 
 
    background-color: #ddd; 
 
    text-align: center; 
 
} 
 
#c-div span { 
 
    margin: 21.5px; 
 
    line-height: 50px; 
 
} 
 
#d-div span { 
 
    margin: auto; 
 
    line-height: 50px; 
 
} 
 
.outlined { 
 
    outline: 10px solid steelblue; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="a-div"> 
 
    <div id="b-div"><div id="d-div"><span>d</span></div></div> 
 
    <div id="c-div"><span>c</span></div> 
 
</div>

+1

Điều này không làm nổi bật '# b-div' nếu ban đầu bạn di chuột' # c-div', vì vậy tôi không không nghĩ rằng nó hoàn toàn đáp ứng các yêu cầu của OP. –

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