Raphael中多个路径的相同hoverfunction

所以我有我的canvas和路径:

var paper1 = Raphael(10, 50, 960, 560); var mapShape1 = paper1.path("M339.098,175.503c0,0-55.555,58.823-16.34,75.163s227.451,49.02,227.451,49.02s67.321-25.49,47.713-50.98s-71.896-78.432-71.896-78.432L339.098,175.503z"); var mapShape2 = paper1.path("M548.902,306.876c0,0-209.15-32.026-228.758-46.405s-27.451-27.451-20.262-42.484s26.797-44.444,26.797-44.444l-41.83-86.928l-76.471,77.125c0,0-25.49,169.935,48.366,171.242s292.157-4.575,292.157-4.575V306.876z"); var mapShape3 = paper1.path("M296.614,86.614l38.562,83.66l194.771-7.843l75.817,81.7c0,0,130.066-84.967,73.203-118.301S503.15,48.706,463.935,51.974S296.614,86.614,296.614,86.614z"); 

我按照这样的方式设置它们:(我相信这可以改进,有没有办法一次完成所有路径???)

 function style1(shape){ shape.attr({ "fill": "#33CCFF", "stroke": "000000", "stroke-width": "5" }); } style1(mapShape1); style1(mapShape2); style1(mapShape3); 

但我的问题是如何在所有路径上使用单个hoverfunction,我有这个:

  mapShape1.hover( function(){ this.animate({ "fill": "#FF3300" }, 500); }, function(){ this.animate({ "fill": "#33CCFF" }, 500) } ); 

但它一次只适用于一种形状,我想这样做

 $(mapShape1, mapShape2, mapShape3).hover(... 

但这不起作用。 我错过了什么?

正如lib3d所说,你应该使用Set 。 但是,不是使用forEach循环设置内容并应用属性/function,而是可以在集合本身上添加共享属性/function,这将将其应用于集合的内容。 稍后将详细介绍如何创建集合。

设置处理

有两种方法可以创建一个集合并向其添加元素:显式和隐式。

明确的

这意味着您自己管理集合,并自行添加元素集

 var paper, shapeA, shapeB, shapeC, elementSet; paper = Raphael(10, 50, 960, 560); elementSet = paper.set(); shapeA = paper.path("M339.098,175.503c0,0-55.555,58.823-16.34,75.163s227.451,49.02,227.451,49.02s67.321-25.49,47.713-50.98s-71.896-78.432-71.896-78.432L339.098,175.503z"); shapeB = paper.path("M548.902,306.876c0,0-209.15-32.026-228.758-46.405s-27.451-27.451-20.262-42.484s26.797-44.444,26.797-44.444l-41.83-86.928l-76.471,77.125c0,0-25.49,169.935,48.366,171.242s292.157-4.575,292.157-4.575V306.876z"); shapeC = paper.path("M296.614,86.614l38.562,83.66l194.771-7.843l75.817,81.7c0,0,130.066-84.967,73.203-118.301S503.15,48.706,463.935,51.974S296.614,86.614,296.614,86.614z"); // now add A and C to the set, as well as a rectangle elementSet.push( shapeA, shapeC, paper.rect(10, 10, 10, 10, 2) ); 

通过这种方式,您可以完全控制进入集合的内容和不进入集合的内容。

含蓄

您还可以在绘制元素时标记起点和终点。 在start和endpoint之间绘制的任何元素都将添加到集合中。

 var paper, shapA, shapeB, shapeC, elementSet; paper = Raphael(10, 50, 960, 560); paper.setStart(); shapeA = paper.path("M339.098,175.503c0,0-55.555,58.823-16.34,75.163s227.451,49.02,227.451,49.02s67.321-25.49,47.713-50.98s-71.896-78.432-71.896-78.432L339.098,175.503z"); shapeB = paper.path("M548.902,306.876c0,0-209.15-32.026-228.758-46.405s-27.451-27.451-20.262-42.484s26.797-44.444,26.797-44.444l-41.83-86.928l-76.471,77.125c0,0-25.49,169.935,48.366,171.242s292.157-4.575,292.157-4.575V306.876z"); shapeC = paper.path("M296.614,86.614l38.562,83.66l194.771-7.843l75.817,81.7c0,0,130.066-84.967,73.203-118.301S503.15,48.706,463.935,51.974S296.614,86.614,296.614,86.614z"); paper.rect(10, 10, 10, 10, 2); elementSet = paper.setFinish(); 

变量elementSet现在包含形状A,B和C以及矩形。

明确还是隐含?

我个人建议总是使用显式方法。 通过这种方式,您可以100%控制进入您设置的内容和不进入的内容。 另外,我发现setStart()和setFinish()向后命名,我们用“set”“开始”,我们不是“设置”一个“开始”。 如果您现在意图这可能是显而易见的,但这确实是模糊命名的危险 – 下一个开发者可能不知道并假设不同的东西。

更多用法

对于我们创建的应用程序,我们必须绘制,删除,更新和重新定位复杂的元素组。 为了实现这一目标,我们大量使用了套装。 除了集合允许您在集合中的每个元素上应用属性这一事实,集合还允许您将其用作DTO。

例如,以下工作:

 var elementSet = paper.set(); elementSet.push(elemA, elemB, elemC); elementSet.myApp.someDTO = { property: value, something: else }; 

为了一致性和清晰度,我倾向于使用myApp作为命名空间。 它的美妙之处在于即使someDTO包含Raphael元素,您在该集合上应用的任何内容都不会应用于DTO中的元素。 这使得它可以在您需要时传递上下文,坐标等。

使用集合

现在回到使用集合的好处。 让我们在这里查看您的用例:您希望应用属性并将鼠标hover在任意数量的路径上。

如果我们在上面的显式示例中创建一个集合,我们最终会得到以下结果:

 var paper, elementSet; paper = Raphael(10, 50, 960, 560); elementSet = paper.set(); elementSet.push( paper.path("M339.098,175.503c0,0-55.555,58.823-16.34,75.163s227.451,49.02,227.451,49.02s67.321-25.49,47.713-50.98s-71.896-78.432-71.896-78.432L339.098,175.503z"), paper.path("M548.902,306.876c0,0-209.15-32.026-228.758-46.405s-27.451-27.451-20.262-42.484s26.797-44.444,26.797-44.444l-41.83-86.928l-76.471,77.125c0,0-25.49,169.935,48.366,171.242s292.157-4.575,292.157-4.575V306.876z"), paper.path("M296.614,86.614l38.562,83.66l194.771-7.843l75.817,81.7c0,0,130.066-84.967,73.203-118.301S503.15,48.706,463.935,51.974S296.614,86.614,296.614,86.614z"), ); 

现在在集合上应用样式:

 elementSet.attr({ fill: '#33CCFF', stroke: '#000000', 'stroke-width': 5 }); 

然后添加hover:

 elementSet.hover( function(){ this.animate({ "fill": "#FF3300" }, 500); }, function(){ this.animate({ "fill": "#33CCFF" }, 500) } ); 

集合也支持链接,如元素所示:

 elementSet.push( /* elements */ ).attr({ /* attributes */ }).hover( /* hover fn's ); 

要查看最终结果,这里有一个小提琴

扩展的hoverfunction

如果您想将onhover突出显示应用于所有元素,您可以再次应用该集合上的属性:

 onMouseOver: function () { elementSet.animate({ fill: '#FF3300' }, 500); }; onMouseOut: function () { elementSet.animate({ fill: '#33CCFF' }, 500); }; elementSet.hover(onMouseOver, onMouseOut); 

可以在这里找到一个小提琴

使用jQuery

为了能够通过jQuery绑定hoverfunction,必须访问元素的节点 。 元素本身不是DOM节点,而是Raphael对象。 通过使用element.node可以在该节点上使用jquery来添加行为。 我个人的经验是,这个工作得体,但是你永远不想通过jquery修改节点,因为这会导致真正意想不到的行为。 Raphael提供了您需要的所有function,不需要使用jquery。

为什么不给你的形状一个类,并让jquery选择类?

您可以执行以下操作:

 function style1(shape){ shape.attr({ "fill": "#33CCFF", "stroke": "000000", "stroke-width": "5", "class": '.js-path-hover' }); } style1(mapShape1); style1(mapShape2); style1(mapShape3); 

然后您的hover事件可以设置如下:

 $('.js-path-hover').on('hover', functionNameHere); 

如果raphael不允许你在这些svg对象上写一个类,那么你可以使用D3来选择它们并为它们添加一个类。 我发现将D3,Raphael和jQuery结合起来非常强大。 唯一的问题是你需要跟踪他们的每个限制。

最简单的方法是将路径推入一个集合中,然后在集合上使用forEach来设置每个路径的样式。

然后,您将以相同的方式绑定hover处理程序,首先将处理程序作为闭包变量引用。

 $(mapShape1, mapShape2, mapShape3).live('hover', function() { }); 

实时应该更好地使用添加到DOM的动态元素hover不适用于之后创建的元素,并且’on’仅适用于创建的dom elemetns,并且指定了第3个参数。