Настройка линий

60

Наконечники и стыки линий

При рисовании фигур Line и Polyline можно указать форму начальной и конечной точек линии, используя свойства StrokeStartLineCap и StrokeEndLineCap. (Эти свойства не имеют эффекта в других фигурах, поскольку те замкнуты.)

Изначально свойства StrokeStartLineCap и StrokeEndLineCap установлены в Flat, что означает немедленное завершение линии в ее конечных координатах. К другим возможным вариантам относятся Round (линия мягко скругляется), Triangle (обе стороны линии сводятся в точку) и Square (линия завершается четкой границей). Все эти значения добавляют линии длину — другими словами, они выводят ее за ту позицию, в которой она закончилась бы в противном случае. Дополнительное расстояние составляет половину толщины линии.

Единственное отличие между Flat и Square состоит в том, что линии, завершающиеся как Square, просто на половину толщины длиннее с каждой стороны. Во всех остальных отношениях они выглядят одинаково.

Ниже показаны различные варианты концов линий:

<Grid Margin="15">
    <Grid.RowDefinitions>
      <RowDefinition></RowDefinition>
      <RowDefinition></RowDefinition>
      <RowDefinition></RowDefinition>
      <RowDefinition></RowDefinition>

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>      
      <ColumnDefinition></ColumnDefinition>
      <ColumnDefinition Width="Auto"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    
    <Polyline Stroke="LightBlue" StrokeThickness="15" StrokeEndLineCap="Flat" SnapsToDevicePixels="True"
      Points="10,10 30,0 50,20 90,10 200,10" >
    </Polyline>
    <TextBlock Grid.Column="1">Flat Line Cap</TextBlock>

    <Polyline Stroke="LightBlue" StrokeThickness="15" Grid.Row="1" StrokeEndLineCap="Square" SnapsToDevicePixels="True"
      Points="10,10 30,0 50,20 90,10 200,10" >
    </Polyline>
    <TextBlock Grid.Row="1" Grid.Column="1">Square Line Cap</TextBlock>

    <Polyline Stroke="LightBlue" StrokeThickness="15" Grid.Row="2" StrokeEndLineCap="Round" SnapsToDevicePixels="True"
      Points="10,10 30,0 50,20 90,10 200,10" >
    </Polyline>
    <TextBlock Grid.Row="2" Grid.Column="1">Round Line Cap</TextBlock>

    <Polyline Stroke="LightBlue" StrokeThickness="15" Grid.Row="3" StrokeEndLineCap="Triangle"  SnapsToDevicePixels="True"
         Points="10,10 30,0 50,20 90,10 200,10" >
    </Polyline>
    <TextBlock Grid.Row="3" Grid.Column="1">Triangle Line Cap</TextBlock>    
    </Grid>
Концы линий

Все фигуры, кроме Line, позволяют изменять вид и форму углов через свойство StrokeLineJoin. Здесь существует три варианта: Miter (значение по умолчанию) использует четкие грани, Bevel обрезает угол в точке сопряжения, a Round — плавно скругляет его. На рисунке можно видеть разницу между ними:

Стыки линий

При использовании граней Miter при толстых линиях и очень малых углах может получиться, что угол превышает половину толщины линии. Если вы установите толщину 3, то выступающий угол может в полтора раза превышать толщину линии. В последней линии на рисунке используется большое значение заострения с узким углом.

Пунктирные линии

Вместо рисования скучных сплошных линий на границах вашей фигуры можно использовать пунктирные (dashed) линии — т.е. линии, прерываемые пробелами в соответствии с указанным шаблоном.

При создании пунктирной линии в WPF вы не ограничены определенным набором жестко заданных вариантов. Вместо этого можно выбирать длину сплошного сегмента и длину прерванного сегмента (пробела), устанавливая свойство StrokeDashArray.

Например, рассмотрим следующую линию:

<Polyline Stroke="Blue" StrokeThickness="14" StrokeDashArray="1 2"
   Points="10,30 60,0 90,40 120,10 350,10">
</Polyline>

Здесь задана длина сплошного сегмента — 1 и ширина пробела — 2. Эти значения интерпретируются относительно толщины линии. Поэтому если линия имеет толщину 14 единиц (как в данном примере), то сплошная часть будет иметь длину 14 единиц, а ширина пропуска — 28. Линия повторяет этот шаблон на протяжении всей своей длины.

С другой стороны, если поменять местами эти значения, задав их следующим образом:

StrokeDashArray="2 1"

то получится линия с длиной сплошного участка в 28 единиц и шириной пропуска в 14 единиц. На рисунке показаны обе линии. Несложно заметить, что когда сегмент очень толстой линии приходится на угол, он может быть обрезан неровно:

Пунктирные линии

Можно также использовать и нецелочисленные значения. Например, следующее значение StrokeDashArray вполне допустимо:

StrokeDashArray="5 0.2 3 0.2"

Здесь применяется более сложная последовательность — штрих длиной 5x14, затем пробел шириной 0.2x14, за которым идет штрих длиной 3x14 и еще один — длиной 0.2x14. В конце этой последовательности линия повторяет тот же шаблон сначала.

Интересная вещь происходит, когда StrokeDashArray передается нечетное количество значений. Рассмотрим пример:

StrokeDashArray="3 0.5 2"

При рисовании этой линии WPF начинает с линии длиной в 3 толщины, за которой следует пробел в половину толщины линии, за которым идет штрих длиной в 2 толщины. Но когда шаблон повторяется, он начинается с пробела в 3 толщины, за ним идет линия длиной в половину толщины и опять пробел. По сути, пунктирная линия чередует шаблоны между сегментами линии и пробелами.

Если нужно, чтобы шаблон пунктирной линии начинался с его середины, можно применить свойство StrokeDashOffset, которое представляет собой начинающийся с О индекс, указывающий на одно из значений из StrokeDashArray. Например, если установить StrokeDashOffset равным 1 в предыдущем примере, то линия начнется с пробела в половину толщины. Установите 2 — и линия начнется с сегмента в 2 толщины.

И, наконец, можно управлять внешним видом наконечников сегментов линии. Изначально они рисуются как прямой срез, но можно установить значение StrokeDashCap в Bevel, Square и Triangle — смысл этих значений рассматривался в предыдущем разделе. Не забывайте, что все эти настройки добавляют половину толщины линии в конец каждого штриха. Если не принять этого во внимание, можно получить штрихи, которые "наползают" друг на друга. Решение состоит в добавлении ширины пробела, чтобы компенсировать этот эффект.

При использовании свойства StrokeDashCap с линией (но не с фигурой) часто имеет смысл установить StartLineCap и EndLineCap в одно и то же значение. Это сделает внешний вид линии более согласованным.

Пройди тесты
Лучший чат для C# программистов