2012-02-03 36 views
12

Tôi đang cố gắng phát triển một bản đồ SVG tương tác và dường như không thể lấy Prototype để mở rộng các phần tử SVG nội dòng. Dưới đây là code ví dụ của tôi (loại bỏ dữ liệu đường dẫn vì nó rất lớn):Prototype có thể mở rộng các phần tử SVG không?

<svg id="map" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="330" height="500" viewBox="-16037,-19651 28871,44234"> 
    <g id="state_outline"> 
     <path id="state" fill="white" stroke-width="200" d="..." /> 
     <path id="water" fill="#a0a0ff" d="..." /> 
    </g> 
    <g id="counties"> 
     <path class="county" id="adams" d="..." /> 
     ... 
    </g> 
</svg> 

<div id="nottamap"></div>  

<script type="text/javascript"> 
    console.log($('nottamap')); 
    console.log($('nottamap').identify()); 
    console.log($('counties')); 
    console.log($('counties').identify()); 
</script> 

Kết quả của việc chạy đó là:

<div id="nottamap"> 
nottamap 
<g id="counties"> 
$("counties").identify is not a function 

$() chỉ từ chối để mở rộng các yếu tố truyền cho nó nếu nó là một phần của phần tử SVG. Có điều gì đó về sự tương tác của Prototype với các phần tử XML mà tôi không hiểu, hay có cách nào tốt hơn cho tôi để đi về điều này?

+1

Câu hỏi hấp dẫn. Tôi không biết các trình duyệt thực hiện các phần tử SVG như thế nào; chúng rõ ràng không phải là các nút DOM. – Pointy

+1

JSFiddle Demo: http://jsfiddle.net/SMTsm/ –

+1

(Bản trình diễn hơi khác: http://jsfiddle.net/SMTsm/2/) –

Trả lời

10

Prototype tăng thêm các phần tử thông qua phương thức Element.addMethods. Nếu bạn nhìn vào the source code bạn có thể thấy một phần có liên quan này:

var elementPrototype = window.HTMLElement ? HTMLElement.prototype : 
    Element.prototype; 

if (F.ElementExtensions) { 
    copy(Element.Methods, elementPrototype); 
    copy(Element.Methods.Simulated, elementPrototype, true); 
} 

Ở đây nó ủng hộ HTMLElement.prototype mà yếu tố SVG không kế thừa. Nó rơi trở lại Element.prototype trong các trình duyệt đó (ho IE ho) cũng không hỗ trợ SVG. Bạn có thể chọn chỉnh sửa trực tiếp nguồn và sao chép tất cả các hành động sao chép sang SVGElement.


Điều đó nghe có vẻ như rất nhiều công việc khi bạn nhận ra rằng một hack đơn giản hơn có thể được sử dụng. Các phương thức tĩnh Element.* vẫn hoạt động khi được sử dụng trực tiếp. Thay vì $('counties').identify(), hãy sử dụng Element.identify('counties'). Nơi bạn có thể làm điều gì đó như thế này:

$$('.classname').invoke('hide'); 

Bạn có thể áp dụng tương đương với chức năng đẹp đó là:

$$('.classname').each(Element.hide); 
// or replace Element.hide with Effect.fade or any other effect 

Nhược điểm là bạn sẽ mất khả năng sử dụng phương pháp chaining.

+0

Tuyệt vời! Đây chính xác là những gì tôi cần. –

6

đề xuất của clockworkgeek để thay đổi mã nguồn mẫu thử nghiệm hoạt động rất tốt đối với tôi. .. Trong nguyên mẫu v 1.7, tất cả phải mất là để thay đổi một phần liên quan đến

var elementPrototype = window.HTMLElement ? HTMLElement.prototype : 
    Element.prototype; 

if (F.ElementExtensions) { 
    if (window.SVGElement) { 
    copy(Element.Methods, SVGElement.prototype); 
    copy(Element.Methods.Simulated, SVGElement.prototype, true); 
    } 
    copy(Element.Methods, elementPrototype); 
    copy(Element.Methods.Simulated, elementPrototype, true); 
} 

trong nguyên mẫu v 1.7.1, những thay đổi cần thiết là:

var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype : 
    Element.prototype; 

if (F.ElementExtensions) { 
    if (window.SVGElement) { 
    mergeMethods(SVGElement.prototype, Element.Methods); 
    mergeMethods(SVGElement.prototype, Element.Methods.Simulated, true); 
    } 
    mergeMethods(ELEMENT_PROTOTYPE, Element.Methods); 
    mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true); 
} 

Tôi tìm thấy giải pháp làm sẵn trong this blog post

+0

Bạn có thể làm điều này mà không làm thay đổi nguồn không? Tôi không thể chọn lọc mở rộng các yếu tố Svg? – kstubs

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