结合Raphael和jQuery实现浏览器兼容性

在发现IE无法处理javascript onmouseout ,我决定使用jQuery,以便自动处理跨浏览器兼容性。 当鼠标hover在svg路径上时,我正在创建一个由svg路径定义的区域,并且我在澳大利亚示例中调整了Raphael网站上提供的代码。

在此代码中,澳大利亚的每个州都由拉斐尔路径定义,例如塔斯马尼亚州:

  aus.tas = R.path("...").attr(attr); 

然后将此路径(’st’)传递给函数:

 st[0].onmouseover = function () { ... }; 

与我预期的相反,代码是st[0].onmouseover而不仅仅是st.onmouseover 。 因此,路径实际上必须是一个数组,而st[0] ,无论是什么,都是hover在上面的东西。

为了用jQuery等价物替换onmouseover (我相信是.mouseout() ),我需要为st[0]分配一个类,所以我可以用jQuery引用它。 我的问题是,我该怎么做? 如果代码是st.onmouseover它会很简单,但为什么路径( st )是一个数组? 究竟是什么st[0] ? 我到底怎么了?

注意: 该演示是使用旧版本的Raphael制作的。 现在Raphael有自己的自定义事件处理程序,包括.mouseover().hover()


缺点:

只需将DOM对象包装成一个jQuery Object,或者使用Raphael内置的自定义事件处理程序:

 $(st[0]).mouseover( ... ); // This uses the jQuery .mouseover() method 

或者,可能更方便,IE支持:

 $(st[0]).hover( ... ); // This uses the jQuery .hover() method 

或者,使用Raphael内置的事件处理程序方法

 st.mouseover( ... ); // This uses the Raphael .mouseover() method st.hover( ... ); // This uses the Raphael .hover() method 

很长一段时间:

您可以使用node [0]获取对DOM对象的引用,因为RaphaelObject[0]始终是对DOM元素的引用:

 aus.tas = R.path("...").attr(attr); // aus.tas is a Raphael object // aus.tas[0] is aus.tas.node is the reference to the DOM Object $(aus.tas[0]).mouseover(function() { // Could have also use aus.tas.node ... }); // Raphael now has custom event handlers aus.tas.mouseover(function() { ... }); aus.tas.hover(function() { ... }, function() { ... }); 

所以,有了你的function:

 (function (st, state) { // st is a Raphael Object // st[0] is st.node is the reference to the DOM Object // This is now using jQuery for mouseover! $(st[0]).mouseover(function() { ... }); ... })(aus[state], state); 

另外,我建议调查jQuery .hover()函数,它可以很好地处理IE:

 (function (st, state) { // This is now using jQuery not Raphael for hover! $(st[0]).hover(function() { ... // the mouseenter function }, function() { ... // the mouseleave function }); ... })(aus[state], state); 

作为简化演示,这里是如何使用.hover().hover()mouseout绑定到Raphael元素( 在IE 8中测试 ):

 ​$(function() { var elie, paper = Raphael("canvas", 500, 500); // Create Raphael element elie = paper.rect(0,0,100,100).attr("fill","#000"); // Get reference to DOM object using .node and bind // mouseover and mouseout to it: $(elie[0]).hover(function() { elie.attr("fill","#FFF"); },function() { elie.attr("fill","#000"); }); });​ 

尝试使用这个jsFiddle

此外,Raphael .hover()方法似乎也适用于IE。

您不需要为其分配类,以便将其公开给jQuery。 当然不是。 你可以简单地将你的DOM元素传递给jQuery,它将为你带来魔力……

 $(st[0]).mouseout(function() { alert("That mouse is outta here!"); }; 

您正在看到数组语法,因为这通常是Javascript库如何维护对原始元素的引用(基本上只是“包装”它并添加function)。 伪码解释……

 st == Raphael element st[0] == DOM element 

如果您最终只是复制了澳大利亚演示所使用的代码,那么无论您使用哪种处理程序(hover,鼠标hover等),都会遇到IE问题。

在我的头上敲了一会儿后,似乎hover输入/输出function中的st.toFront()取消了IE中的“鼠标输出”事件。 从示例代码中删除这些行,你应该没问题。

这是一些javascript技巧,st传入。查看澳大利亚示例中的JS代码。

 (function (st, state) { .. some code referring to st[0] in here .. })(aus[state], state); 

因此,此代码中的st [0] 引用来自aus [state]的路径DOM节点

在Firebug控制台中使用这个简单示例自己尝试一下:

 (function(a,b) {alert(a); })("hello", "b"); 

心连心

在我的例子中,实际问题是每隔一个毫秒调用.toFront,因为.hover(fooFunction,outFunction)在每次鼠标光标移动时调用fooFunction。 实际上,这个名字相当暗示它是一个hover调用,而不是一个mouseenter 🙂

因此,诀窍是确保你的fooFunction或其内容只执行一次(onmouseenter)。 即使在IE中,这对我来说也很完美,无需访问任何DOM节点或尝试访问其他我不想触摸的内容:

 var MouseEventHelper = { hover: function (el, funcIn, funcOut) { var entered = false; el.hover( function (e) { if (entered) { return; } funcIn(e); entered = true; }, function (e) { funcOut(e); entered = false; } ); } } 

然后替换你的hover调用,如下所示:

 var el = paper.rect(...); MouseEventHelper.hover( el, function (e) { // do whatever you want! el.toFront(); } function (e) { } );