6

所以我有我的画布和我的路径:

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);

但我的问题是如何在所有路径上使用一个悬停功能,我有这个:

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

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

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

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

4

4 回答 4

12

正如 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。

于 2013-04-22T07:22:16.463 回答
1

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

您可以执行以下操作:

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

style1(mapShape1);
style1(mapShape2);
style1(mapShape3);

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

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

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

于 2013-04-22T07:49:21.757 回答
0

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

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

于 2013-04-20T07:48:30.723 回答
0
$(mapShape1, mapShape2, mapShape3).live('hover', function() { });

Live 应该更好地使用添加到 DOM 悬停的动态元素不适用于之后创建的元素,并且“on”仅适用于指定了第三个参数的创建的 dom 元素。

于 2013-04-23T12:25:11.517 回答