我正在尝试开发一个交互式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元素的交互,我不理解,还是有更好的方法来解决这个问题?
答案 0 :(得分:10)
Prototype通过它的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元素不会继承。在那些也不支持SVG的浏览器( cough IE cough )中,它会回退到Element.prototype
。您可以选择直接编辑源代码并将所有复制操作复制到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
缺点是你失去了使用方法链的能力。
答案 1 :(得分:6)
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);
}
中找到了现成的解决方案