Примеры и код команд:
- Начальная точка (M,m) и отрезок прямой (L,l)
- Горизонтальная линия (H,h) и вертикальная (V,v)
- Дуга элипса – Elliptical Arc (A,a)
- Кубическая кривая Безье – The cubic Bézier curve
- Гладкая поликривая Безье – Smooth cubic poly Bezier curve
- Кривые Безье второго порядка – Quadratic Bezier Curves
- Гладкая поликривая Безье второго порядка – Smooth Quadratic poly Bezier
- Правила и команды заполнения путей – fill-rule=”nonzero | evenodd”
8. Правила и команды заполнения путей – fill-rule=”nonzero | evenodd”
Я думаю, что все, кто рисовал в любом векторном редакторе, встречались с эффектом белых, непрокрашенных пятен при заполнении фигур цветом. Это не вызывало больших проблем и легко устранялось дополнительными щелчками мышки по незакрашенным областям рисунка. Но как быть, если нужно написать скрипт, реализующий анимацию с закрашиванием всей фигуры или её отдельных сегментов?
Для этого нужно чётко разобраться в алгоритме заполнения цветом сегментов фигур. Логично предположить, что должны заполняться внутренние области фигуры, а наружные оставаться незакрашенными.
Но как понять, где внутренняя, а где наружная область фигуры, если она имеет сложные контуры с многократными пересечениями линий. Что брать за точку отсчета, относительно чего смотреть?
Ответы на эти вопросы дает спецификация команды fill-rule, которая имеет два значения:nonzero | evenodd
Это правило определяет внутреннию точку на холсте, путем рисования луча от этой точки до бесконечности в любом направлении и затем проверяются места, где сегмент фигуры пересекает луч . Отсчет начинается с нуля. Единица (+1) добавляется каждый раз, когда сегмент пересекает луч слева направо и вычитается единица (-1), когда сегмент пересекает луч справо налево . После подсчета пересечений, если результат равен нулю, то точка считается снаружи пути (сегмент не закрашивается). В противном случае она внутри.
1 2 3 |
<path d="M25,225 25,25 225,25 225,225 25,225 M75,175 75,75 175,75 175,175 75,175" style="stroke:blue; fill-rule:nonzero; stroke-width:2; fill:dodgerblue; /> |
Из текста правила “nonzero” становится понятно, что результат заполнения цветом зависит от направления путей, образующие сегменты фигуры и количества их пересечений с лучом.
На Рис.1 два подпути образуют два сегмента, которые пересекают в одинаковом направлении луч, идущий из точки в бесконечность (зеленая линия). Алгебраическая сумма всех пересечений составляет +2, то есть результат не равен нулю, поэтому все сегменты фигуры будут закрашены.
1 2 3 |
<path d="M25,225 25,25 225,25 225,225 25,225 M75,175 175,175 175,75 75,75 75,175" style="stroke:blue; fill-rule:nonzero; stroke-width:2; fill:dodgerblue;/> |
1 2 3 4 |
<path d="M25,225 25,25 225,25 225,225 25,225 M65,185 185,185 185,65 65,65 65,185 M105,145 105,105 145,105 145,145 105,145" style="stroke:blue; fill-rule:nonzero; stroke-width:2; fill:dodgerblue;/> |
На Рис.3 имеем три сегмента пересекающие луч в разных направлениях. Посчитаем для каждого сегмента алгебраическую сумму:
A=+1;
B= -1+1=0; – не закрашивается
C=+1-1+1=+1;
Из этих примеров можно вывести две закономерности:
1. При одинаковом направлении двух и более подпутей параметра d=”…” все сегменты фигуры будут окрашены.
2. При разном направлении двух и более подпутей параметра d=”…” и при условии, что все соседние подпути имеют разные направления,- будут окрашены все нечетные сегменты. Соответственно чётные будут неокрашены.
Правило заполнения fill-rule=”evenodd”
Это более простое правило для понимания. Направление подпутей не учитывается. Точно так же, как и для правила “nonzero” проводится луч из точки внутри фигуры в бесконечность и производится подсчет порядковых номеров пересекаемых сегментов. Все нечетные сегменты будут окрашены.
1 2 3 |
<path d="M25,225 25,25 225,25 225,225 25,225 M75,175 75,75 175,75 175,175 75,175 " style="stroke:blue; fill-rule:evenodd; stroke-width:2; fill:dodgerblue; fill-opacity:0.6;/> |
1 2 3 |
<path d="M25,225 25,25 225,25 225,225 25,225 M75,175 175,175 175,75 75,75 75,175 " style="stroke:blue; stroke-width:2; fill-rule:evenodd; fill:dodgerblue; fill-opacity:0.6; /> |
1 2 3 4 |
<path d="M25,225 25,25 225,25 225,225 25,225 M65,185 185,185 185,65 65,65 65,185 M105,145 145,145 145,105 105,105 105,145" style="stroke:blue; fill-rule:evenodd; stroke-width:2; fill:dodgerblue; fill-opacity:0.6;"/> |
На Рис.6 использованы 3 подпути, которые образуют 3 сегмента. Правило работает – (все нечетные сегменты) – 1 и 3 закрашены.
1 2 3 4 |
<path d="M25,225 25,25 225,25 225,225z M25,185 185,185 225,65z M70,145 145,145 145,90 90,90z" style="stroke:blue; stroke-width:2; fill:dodgerblue; fill-rule:evenodd;fill-opacity:0.6;"/> |
⇚ SVG path часть 4