如何在 Raphael 中使用路径实现“甜甜圈洞”

Posted

技术标签:

【中文标题】如何在 Raphael 中使用路径实现“甜甜圈洞”【英文标题】:How to achieve 'donut holes' with paths in Raphael 【发布时间】:2011-03-21 22:47:08 【问题描述】:

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

根据W3 path spec:

复合路径(即具有多个子路径的路径)可以在对象中产生诸如“甜甜圈洞”之类的效果。

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

非常感谢。

【问题讨论】:

事实上它并不是 Raphael 特有的,而是更普遍地适用于 SVG。 【参考方案1】:

如果您知道诀窍,这会变得非常简单。例如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 beta,但不适用于 3.6

【讨论】:

我正在尝试使用这种技术来填充圆形甜甜圈,知道如何让圆形功能反向绘制以便正确填充吗? @Neil 据我所知,您必须使用路径才能完成这项工作。 @robertc 谢谢我确实用路径实现了这一点,谢谢你的提示。 我正要问同样的问题。结果(坐标不同)可以在这里看到:jsfiddle.net/cWHdk/2 嗨@robertc。我正在寻找与您相反的解决方案。这是我的问题:***.com/questions/20847767/…【参考方案2】:

要在 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 技术中是相当标准的。

【讨论】:

嗨@本。我正在寻找与您相反的解决方案。这是我的问题:***.com/questions/20847767/…【参考方案3】:

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

不要尝试用“Raphael.Element.attr()”来设置它。它不起作用。我改用 jQuery.attr() 函数:

// assuming paper is a Raphael.Paper object
path = paper.path('Mx,ysome path commands for the main shapeZ'
                  +'Mx,ysome path commands for the holeZ'
);

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

我已经在复杂的路径上使用它并取得了成功。

【讨论】:

只是想对此进行非 jQuery 更新:path[0].setAttribute('fill-rule', 'evenodd'); 有效【参考方案4】:

对于任何想要做圆形甜甜圈的人,非常简单的插件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');
;

【讨论】:

如果您添加一个很棒的小提琴示例

以上是关于如何在 Raphael 中使用路径实现“甜甜圈洞”的主要内容,如果未能解决你的问题,请参考以下文章

如何从 svg 中的所有点知道路径的 m 或 M 点?(使用 raphael.js)

raphael.js 如何将 id 添加到路径

如何使用 Raphael.js 绘制“透明笔画”

如何在 Raphael.js / IE 中“固定”模式?

在 Raphael js 中使路径和图像可拖动

使用 png 填充图像移动 Raphael 路径,而不破坏 IE 中的图像或相对于元素移动图像?