Prototype可以扩展SVG元素吗?

Pha*_*son 12 javascript svg prototypejs

我正在尝试开发一个交互式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>
Run Code Online (Sandbox Code Playgroud)

运行的结果是:

<div id="nottamap">
nottamap
<g id="counties">
$("counties").identify is not a function
Run Code Online (Sandbox Code Playgroud)

$()只是拒绝扩展传递给它的元素,如果它是SVG元素的一部分.有没有关于Prototype与XML元素的交互,我不理解,还是有更好的方法来解决这个问题?

clo*_*eek 10

Prototype通过它的Element.addMethods方法增加元素.如果查看源代码,可以看到这个相关部分:

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

if (F.ElementExtensions) {
  copy(Element.Methods, elementPrototype);
  copy(Element.Methods.Simulated, elementPrototype, true);
}
Run Code Online (Sandbox Code Playgroud)

这里它有利于HTMLElement.prototype哪些SVG元素不继承.它回归到Element.prototype那些也不支持SVG的浏览器(咳嗽 IE 咳嗽).您可以选择直接编辑源并复制所有复制操作SVGElement.


当你意识到可以使用更简单的黑客时,这听起来像是很多工作.Element.*直接使用静态方法仍然有效.而不是$('counties').identify()使用Element.identify('counties').你可能会做这样的事情:

$$('.classname').invoke('hide');
Run Code Online (Sandbox Code Playgroud)

你可以采用很好的功能等价物:

$$('.classname').each(Element.hide);
// or replace Element.hide with Effect.fade or any other effect
Run Code Online (Sandbox Code Playgroud)

缺点是你失去了使用方法链的能力.


Tho*_*unn 6

clockworkgeek改变原型源代码的建议对我来说非常有用.在原型v.7.7中,只需要将相关部分更改为

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);
}
Run Code Online (Sandbox Code Playgroud)

在原型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);
}
Run Code Online (Sandbox Code Playgroud)

我在这篇博客文章中找到了现成的解决方案