在 WPF 中无缝平铺矩形

发布于 2024-07-22 15:01:04 字数 1179 浏览 5 评论 0原文

我想在 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?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南渊 2024-07-29 15:01:04

您可以考虑使用指南(请参阅 MSDN 上的GuidelineSet) 并重写矩形的 OnRender 方法,以便它们的边界与设备的像素边界对齐。 WPF 使用准则来确定是否以及在何处捕捉绘图。

在内部,这正是 SnapsToDevicePixels 用来确保对象与设备像素对齐的方法,但是通过手动放置参考线,您将能够控制何时应用捕捉行为以及何时不应用捕捉行为(因此,当您的图像全部缩放时)当然,您可以避免绘制辅助线,或者仅在形状与其他形状相邻的位置绘制辅助线,并依靠 WPF 的抗锯齿功能来处理其余部分)。 您可能可以使用附加属性来完成此操作,以便可以将其应用于任何元素,但如果您只需要这种行为的一种类型的元素(例如矩形),则可能不需要值得付出额外的努力。

微软似乎也意识到了这个问题 - WPF 4.0 预计将具有布局舍入功能与 Silverlight 中的版本类似,当启用布局舍入时,在渲染过程中舍入非整数值。

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.

痕至 2024-07-29 15:01:04

我猜这些间隙不是实际的间隙,而是绘制的笔触。 当你缩小它时,你只是将笔画缩小到不再可见的程度。 我尝试用矩形的颜色绘制笔画,该颜色在任何比例下都可以正常工作。

<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" Stroke="#CFC"/>
    <Rectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF" Stroke="#CCF"/>
  </Canvas>
</Page>

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.

<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" Stroke="#CFC"/>
    <Rectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF" Stroke="#CCF"/>
  </Canvas>
</Page>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文