Прямоугольная мозаика в WPF - PullRequest
6 голосов
/ 07 июня 2009

Я хочу плавно разложить несколько прямоугольников разного цвета в WPF. То есть я хочу поместить прямоугольники в ряд, чтобы между ними не было пробелов.

Если все выровнено по пикселям, это нормально работает. Но я также хочу поддерживать произвольное масштабирование, и в идеале я не хочу использовать SnapsToDevicePixels (потому что это ухудшит качество, когда изображение будет уменьшено). Но это означает, что мои прямоугольники иногда отображаются с пробелами. Например:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Background="Black">
  <Canvas SnapsToDevicePixels="False">
    <Canvas.RenderTransform>
      <ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
    </Canvas.RenderTransform>
    <Rectangle Canvas.Left="25" Width="100" Height="100" Fill="#CFC"/>
    <Rectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF"/>
  </Canvas>
</Page>

Если ScaleTransform ScaleX равен 1, то прямоугольники соединяются без проблем. Когда это 0,5, между ними появляется темно-серая полоса. Я понимаю, почему - комбинированные полупрозрачные краевые пиксели не могут быть непрозрачными на 100%. Но я бы хотел, чтобы это исправить.

Я всегда мог просто наложить прямоугольники, но я не всегда буду заранее знать, в каких шаблонах они будут (это для игры, которая в конечном итоге будет поддерживать редактор карт). Кроме того, это может привести к появлению артефактов вокруг области перекрытия при увеличении масштаба изображения в (если только я не делал углы наклона на перекрывающейся части, что является ужасной работой и по-прежнему вызывает проблемы на углах) .

Есть ли какой-нибудь способ, которым я могу объединить эти прямоугольники в одну объединенную "фигуру", которая рендерится без внутренних пробелов? Я поиграл с GeometryDrawing, которая делает именно это, но потом я не вижу способа рисовать каждую RectangleGeometry кистью разного цвета.

Существуют ли другие способы беспрепятственного размещения фигур при произвольном преобразовании, не прибегая к SnapsToDevicePixels?

Ответы [ 2 ]

2 голосов
/ 08 июня 2009

Вы можете рассмотреть возможность использования рекомендаций (см. GuidelineSet на MSDN ) и переопределения методов OnRender прямоугольников, чтобы их границы совпадали с границами пикселей устройства. WPF использует руководящие указания, чтобы определить, нужно ли и где привязывать чертежи.

Внутренне это именно то, что SnapsToDevicePixels использует для обеспечения соответствия объектов пикселям устройства, но, разместив указатели вручную, вы сможете контролировать, когда применяется привязка, а когда - нет (например, когда ваше изображение). полностью уменьшен, вы можете избежать рисования руководящих указаний или только рисовать руководящие указания, если ваши фигуры лежат рядом с другими фигурами, и полагаться на сглаживание WPF, чтобы позаботиться обо всем остальном). Вы могли бы быть в состоянии сделать это с прикрепленным свойством, так что вы можете применить его к любому элементу, хотя, если это только один тип элемента (например, Rectangle), на котором вам нужно это поведение, это, вероятно, не стоит дополнительные усилия.

Кажется, что Microsoft тоже знает об этой проблеме - Ожидается, что WPF 4.0 будет включать округление макета , которое, , как и версия в Silverlight , округляет нецелые значения на проходе рендеринга, когда округление макета включено.

0 голосов
/ 21 ноября 2012

Полагаю, пропуски - это не фактические пропуски, а нарисованный штрих. Когда вы уменьшаете его, вы просто уменьшаете размер штриха до точки, где он больше не виден. Я попытался нарисовать обводку цветом прямоугольника, который отлично работает в любом масштабе.

&ltPage xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Background="Black"&gt
  &ltCanvas SnapsToDevicePixels="False"&gt
    &ltCanvas.RenderTransform&gt
      &ltScaleTransform ScaleX="0.5" ScaleY="0.5"/&gt
    &lt/Canvas.RenderTransform&gt
    &ltRectangle Canvas.Left="25" Width="100" Height="100" Fill="#CFC" Stroke="#CFC"/&gt
    &ltRectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF" Stroke="#CCF"/&gt
  &lt/Canvas&gt
&lt/Page&gt
...