2013-01-21 31 views
17

Tôi đang cố gắng có trình xử lý nhấp chuột phổ biến cho tất cả các phần tử tôi đang thêm vào canvas SVG. Nhưng tôi không thể ủy nhiệm người xử lý cho các thành phần mới được tạo ra.Tổ chức sự kiện trên các yếu tố SVG

Đây là mã tôi đã cố gắng để ủy, nhưng may mắn không

$("#floor").on('click','.drawnLine', function() { 
    //#floor is the SVG Element 
    //.drawnLine is the <line> element that is added dynamically 
    console.log($(this).data('index')); 
}); 

Cập nhật: Mở hướng dẫn jQuery của .on() nó được đề cập rằng

Lưu ý: được ủy sự kiện không hoạt động đối với SVG.

Vì vậy, bây giờ câu hỏi là giải pháp khác cho vấn đề này?

+0

jQuery được thiết kế cho HTML DOM, tương tự nhưng không giống với DOM SVG.Những gì bạn đang cố gắng làm có lẽ không được hỗ trợ. (Tương tự, tôi cần thay thế một vài phương thức jQuery để thêm/xóa các lớp bằng các phiên bản tương thích SVG của riêng tôi trong một dự án trước đó.) Hy vọng rằng ai đó có thể đề xuất một sự thay thế tốt đẹp. –

+0

[http://keith-wood.name/svg.html](http://keith-wood.name/svg.html) – Ohgodwhy

+0

@Ohgodwhy, Tổ chức sự kiện cũng không hoạt động với thư viện đó. – Starx

Trả lời

12

Khi jQuery thất bại với SVG, bạn có thể sử dụng vanilla js. May mắn là mọi trình duyệt hỗ trợ svg cũng hỗ trợ trình nghe sự kiện. Sự kiện ủy nhiệm js thuần túy không quá xấu xí:

$("#floor")[0].addEventListener('click', function(e) { 
    // do nothing if the target does not have the class drawnLine 
    if (!e.target.classList.contains("drawnLine")) return; 
    console.log($(this).data('index')); 
}); 

Nhưng bạn cũng có thể tạo chức năng của riêng mình để ủy quyền các sự kiện của mình rõ ràng hơn.

+1

Một tùy chọn khác trong những ngày này là 'e.target.classList.contains (" drawnLine ")', tôi khuyên bạn nên cho bất cứ điều gì mới. –

+1

Lưu ý rằng bạn có thể cô lập các phần tử con bạn muốn trở thành mục tiêu sự kiện bằng cách đặt 'pointer-events: none' trên tổ tiên giữa các phần tử đó và phần tử mà bạn đính kèm trình xử lý sự kiện và' pointer-events: auto' các yếu tố mục tiêu. Ví dụ. nếu các phần tử '.drawnLine' của bạn nằm trong' 'trong' ', đặt' pointer-events' thành 'none' trên' 'và' 'và' tự động' trên các phần tử '.drawnLine'. – ericsoco

8

TL/DR: Đính kèm trình xử lý sự kiện vào phần tử gốc không phải SVG.

Ghi chú trong tài liệu jQuery có phần gây hiểu nhầm.

Sự kiện được ủy quyền không hoạt động đối với SVG.

Nó có lẽ nên được ...

sự kiện được ủy không làm việc khi người nghe được gắn vào SVG.

Tổ chức sự kiện của jQuery không hoạt động khi trình xử lý sự kiện được gắn với phần tử SVG; tuy nhiên, nếu bạn thay thế trình lắng nghe vào một phụ huynh không SVG của SVG, sự kiện tuyên truyền hoạt động như mong đợi và bất kỳ bộ chọn nào phù hợp với các phần tử SVG sẽ thực sự kích hoạt chức năng xử lý sự kiện của bạn.

Gắn người nghe đến các yếu tố SVG sẽ không công việc:

$("#floor").on('click','.drawnLine', function() { 
    console.log($(this).data('index')); 
}); 

Nhưng gắn nó vào một yếu tố phụ huynh sẽ làm việc:

$(document.body).on('click','#floor .drawnLine', function() { 
    console.log($(this).data('index')); 
}); 

Lưu ý: một đứa tôi đã nhận thấy rằng nếu mục tiêu sự kiện là một phần tử SVG, sự kiện sẽ không phát sinh tất cả các cách đến document.body trên iOS. Vì vậy, nếu bạn muốn người dùng iOS có thể kích hoạt chức năng xử lý của bạn, bạn cần đính kèm trình xử lý sự kiện của mình vào một số phần tử ở giữa (chẳng hạn như phần tử div mà SVG của bạn nằm).

+0

Cảm ơn. Đây là một phản ứng rất hữu ích. Bây giờ tôi có thể dễ dàng truy cập dữ liệu d3 được liên kết với phần tử đích, mà không cần quá nhiều trình xử lý sự kiện. – hrabinowitz

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