正如 lib3d 所说,您应该使用Set。然而,不是使用forEach
循环集合内容并应用属性/功能,而是可以将共享属性/功能添加到集合本身,这会将其应用于集合的内容。稍后会详细介绍,首先看看如何创建集合。
设置处理
有两种方法可以创建集合并向其添加元素:显式和隐式。
显式
这意味着您自己管理集合,并自己将元素添加到集合中`
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)
);
这样你就可以完全控制什么进入集合,什么不进入。
隐式
您还可以在绘制元素时标记起点和终点。在起点和终点之间绘制的任何元素都将添加到集合中。
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 中的元素。如果您需要,这使得它可以真正用于传递上下文、坐标等。
使用集合
现在回到使用集合的好处。让我们在这里回顾一下您的用例:您想应用属性并将鼠标悬停在任意数量的路径上。
如果我们在上面的显式示例中创建一个集合,我们最终会得到以下结果:
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
});
然后添加悬停:
elementSet.hover(
function(){
this.animate({
"fill": "#FF3300"
}, 500);
},
function(){
this.animate({
"fill": "#33CCFF"
}, 500)
}
);
集合也支持链接,就像元素一样:
elementSet.push(
/* elements */
).attr({
/* attributes */
}).hover(
/* hover fn's
);
要查看最终结果,这里有一个小提琴
扩展悬停功能
如果您想将 onhover 高亮应用到所有元素,您可以再次应用 set 上的属性:
onMouseOver: function () {
elementSet.animate({
fill: '#FF3300'
}, 500);
};
onMouseOut: function () {
elementSet.animate({
fill: '#33CCFF'
}, 500);
};
elementSet.hover(onMouseOver, onMouseOut);
可以在此处找到查看此内容的小提琴
使用 jQuery
为了能够通过 jQuery 绑定悬停功能,必须访问元素的节点。元素本身不是 DOM 节点,而是 Raphael 对象。通过使用element.node
可以在该节点上使用 jquery 来添加行为。我个人的经验是,这工作得很好,但是你永远不想通过 jquery 修改节点,因为这会导致非常意外的行为。Raphael 提供了您需要的所有功能,不需要使用 jquery。