Tiling rectangles seamlessly in WPF

半腔热情 提交于 2020-01-12 19:32:53

问题


I want to seamlessly tile a bunch of different-colored Rectangles in WPF. That is, I want to put a bunch of rectangles edge-to-edge, and not have gaps between them.

If everything is aligned to pixels, this works fine. But I also want to support arbitrary zoom, and ideally, I don't want to use SnapsToDevicePixels (because it would compromise quality when the image is zoomed way out). But that means my Rectangles sometimes render with gaps. For example:

<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>

If the ScaleTransform's ScaleX is 1, then the Rectangles fit together seamlessly. When it's 0.5, there's a dark gray streak between them. I understand why -- the combined semi-transparent edge pixels don't combine to be 100% opaque. But I would like a way to fix it.

I could always just make the Rectangles overlap, but I won't always know in advance what patterns they'll be in (this is for a game that will eventually support a map editor). Besides, this would cause artifacts around the overlap area when things were zoomed way in (unless I did bevel-cut angles on the underlapping portion, which is an awful lot of work, and still causes problems at corners).

Is there some way I can combine these Rectangles into a single combined "shape" that does render without internal gaps? I've played around with GeometryDrawing, which does exactly that, but then I don't see a way to paint each RectangleGeometry with a different-colored brush.

Are there any other ways to get shapes to tile seamlessly under an arbitrary transform, without resorting to SnapsToDevicePixels?


回答1:


You might consider using guidelines (see GuidelineSet on MSDN) and overriding the Rectangles' OnRender methods so that their boundaries line up with the pixel boundaries of the device. WPF uses guidelines to determine whether and where to snap drawings.

Internally, it's exactly what SnapsToDevicePixels is using to ensure that objects line up with the device's pixels, but by placing guidelines manually you'll be able to control when the snapping behaviour is applied and when it is not (so when your image is zoomed all of the way out, you can avoid drawing guidelines, or only draw guidelines where your shapes lie next to other shapes, and rely on WPF's anti-aliasing to take care of the rest). You might be able to do it with an attached property so that you can apply it to any element, though if it's only one type of element (e.g. Rectangle) that you need this behaviour on, it's probably not worth the extra effort.

It seems like Microsoft is aware of this problem, too - WPF 4.0 is expected to feature Layout Rounding, which, like the version in Silverlight, rounds off non-integer values at the Render pass when layout rounding has been enabled.




回答2:


I guess the gaps are not actual gaps but the stroke that is painted. When you scale it down than you just make the stroke smaller to a point where it is not visible anymore. I tried to paint the stroke in the color of the rectangle wich works just fine on any scale.

&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


来源:https://stackoverflow.com/questions/961872/tiling-rectangles-seamlessly-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!