Как достичь "отверстий пончика" с путями в Рафаэле
Я хотел бы нарисовать фигуру с отверстиями в ней, чтобы я мог fill
сформировать ее и не иметь отверстий, заполненных этим цветом (оставьте их прозрачными).
В соответствии с спецификацией пути W3:
Сложные пути (т.е. путь с несколькими подпутами) позволяют разрешать такие эффекты, как "отверстия пончика" в объектах.
Может кто-нибудь, пожалуйста, дайте очень простой пример того, как выполнить это с векторным путем в Raphael?
Большое спасибо.
Ответы
Ответ 1
Это оказывается довольно простым, если вы знаете трюк. Например это не работает:
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");
Но это работает *:
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 архивах.
(*) По крайней мере, он работает в бета-версии Chrome, Opera и Firefox 4.0, но не в версии 3.6
Ответ 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");
Просто краткое примечание, чтобы следить за комментарием - концепция по часовой стрелке/против часовой стрелки может показаться странной вначале, но она довольно стандартная по всем технологиям ГИС/САПР.
Ответ 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 done
$(path[0]).attr('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');
};