如何在拉斐尔的路径上实现“甜甜圈洞”

时间:2010-07-28 03:17:16

标签: vector svg path raphael

我想绘制一个有洞的形状,这样我就可以fill塑造它的形状,而不是那些用这种颜色填充的洞(让它们保持透明)。

根据W3 path spec

  

复合路径(即具有多个子路径的路径)可以在对象中实现“甜甜圈洞”等效果。

有人可以举一个非常简单的例子说明如何使用Raphael中的矢量路径执行此操作吗?

非常感谢。

4 个答案:

答案 0 :(得分:19)

如果你知道这个诀窍,那么事情就会变得非常简单。例如this doesn't work

paper.path("M 50 50 L 50 150 L 150 150 L 150 50 z" + 
          " M 75 75 L 75 125 L 125 125 L 125 75 z")
.attr("fill", "#f00");

但是this does work *:

paper.path("M 50 50 L 50 150 L 150 150 L 150 50 z" +
          " M 75 75 L 125 75 L 125 125 L 75 125 z")
.attr("fill", "#f00");

不同之处在于,要显示甜甜圈,内部路径必须将顶点以相反的顺序绘制到外部路径(即顺时针绘制一个,逆时针绘制另一个)。我在text.xml.svg.devel archives找到了一个小窍门。

(*)至少,它适用于Chrome,Opera和Firefox 4.0测试版,但不适用于3.6

答案 1 :(得分:4)

要在Firefox 3.6中使用,您需要关闭漏洞;即,在定义内边界时使坐标连接回自身。奇怪的是,对于外边界来说,这似乎并不必要。

paper.path("M 50 50 L 50 150 L 150 150 L 150 50 z" +
          " M 75 75 L 125 75 L 125 125 L 75 125 L 75 75 z")
.attr("fill", "#f00");

只需快速注释即可跟进评论 - 顺时针/逆时针概念起初可能看起来很奇怪,但它在整个GIS / CAD技术中非常标准。

答案 2 :(得分:3)

我认为正确的方法是将属性“fill-rule”设置为值“evenodd”。看看svg spec

请勿尝试使用“Raphael.Element.attr()”进行设置。它不起作用。我改为使用jQuery.attr()函数:

// assuming paper is a Raphael.Paper object
path = paper.path('Mx,y{some path commands for the main shape}Z'
                  +'Mx,y{some path commands for the hole}Z'
);

// this doesn't work
path.attr({'fill-rule': 'evenodd'});
// neither this
path.attr({fillRule: 'evenodd'});

// if you inspect the object returned by paper.path
// you can see it has a reference to the DOM element
console.debug(path)

// so a bit of jQuery and it's done
$(path[0]).attr('fill-rule', 'evenodd');

我在复杂的路径上使用了这个并且成功的结果。

答案 3 :(得分:2)

对于任何想做圆形甜甜圈的人来说,非常简单的插件Raphael-donut-plugin

要点:

Raphael.fn.donut = function(x, y, innerRadius, outerRadius) {
  y -= outerRadius;
  return this.path('M'+x+' '+y+'a'+outerRadius+' '+outerRadius +
      ' 0 1 0 1 0m-1 '+
      (outerRadius - innerRadius)+
      'a'+innerRadius+' '+innerRadius+
      ' 0 1 1 -1 0');
};