2012-02-03 53 views
12

我試圖開發一個交互式的SVG地圖,似乎無法獲得原型來擴展內聯SVG元素。這裏是我的示例代碼(去掉路徑數據,因爲它是巨大的):可以Prototype擴展SVG元素嗎?

<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> 

運行的結果是:

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

$()僅僅是拒絕,如果它的一部分延伸傳遞給它的元素的SVG元素。有沒有關於Prototype與XML元素的互動,我不瞭解,還是有更好的方法讓我去做這件事?

+1

迷人的問題。我不知道瀏覽器如何實現SVG元素;他們顯然不是DOM節點。 – Pointy 2012-02-03 23:31:34

+1

JSFiddle演示:http://jsfiddle.net/SMTsm/ – 2012-02-03 23:33:12

+1

(稍微不同的演示:http://jsfiddle.net/SMTsm/2/) – 2012-02-03 23:39:23

回答

10

原型通過它的Element.addMethods方法來增加元素。如果你看一下the source code你可以看到這個相關部分:

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

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

這有利於HTMLElement.prototype其中SVG元素不繼承。它在這些瀏覽器中回落到Element.prototype咳嗽 IE 咳嗽),也不支持SVG。您可以選擇直接編輯源代碼並將所有複製操作複製到SVGElement


這聽起來像很多工作,當你意識到可以使用一個更簡單的黑客。直接使用時,靜態的Element.*方法仍然有效。而不是$('counties').identify()使用Element.identify('counties')。在這裏你可以做這樣的事情:

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

可以採取很好的功能同等物是:

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

的缺點是你失去了使用方法鏈的能力。

+0

太棒了!這正是我需要的。 – 2012-02-08 21:30:29

6

clockworkgeek建議更改原型源代碼對我來說工作得很好。 。在1.7原型V,所需要的是對相關部分更改爲

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); 
} 

在原型v 1.7.1,所需要的變化是:

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); 
} 

我找到了現成的解決方案在this blog post

+0

你可以在不改變源的情況下做到這一點嗎?我不能有選擇地擴展Svg元素嗎? – kstubs 2014-12-05 16:58:58