6

我正在使用 Viewbox 来缩放固定大小的画布(包含一起形成有意义的图片的各种路径)。

<StackPanel Background="Red" Width="400" UseLayoutRounding="True">
    <StackPanel.Resources>
        <Style TargetType="Viewbox">
            <Setter Property="Height" Value="400" />
            <Setter Property="Margin" Value="0,0,0,50" />
        </Style>
        <Style TargetType="Path">
            <Setter Property="Stroke" Value="Blue" />
            <Setter Property="StrokeThickness" Value="2" />
        </Style>
    </StackPanel.Resources>
    <Viewbox>
        <Canvas Width="5" Height="5">
            <Path Data="M 1,1 h 3 v 3 h -3 z" />
        </Canvas>
    </Viewbox>
    <Viewbox>
        <Canvas Width="6" Height="6">
            <Path Data="M 1,1 h 4 v 4 h -4 z" />
        </Canvas>
    </Viewbox>
</StackPanel>

此 xaml 在我的 PC 上本地呈现时显示在顶部,在模拟器上呈现时显示在底部。由于模拟器正在产生所需的结果,有人可以向我解释为什么第二条路径超出了红色面板吗?

在我的电脑上原生渲染 在模拟器上渲染

4

2 回答 2

5

真的没有差异......正在发生的事情是你正在采取一些渲染非常小的东西(你的路径非常小):

截屏

看看那些小盒子

...并将其放大到非常大,并通过以下方式告诉布局四舍五入到最接近的整个像素UseLayoutRounding

结果不可靠的原因是Paths 独立于 s 进行缩放,Canvas因为它实际上并没有布局其内容。因此,当您的路径点之一落在不均匀的像素边界上(这可能发生在某些屏幕分辨率而不是其他屏幕分辨率上)时,它会四舍五入到未缩放的画布内最近的虚拟像素,并且从 缩放Viewbox然后再次四舍五入到最近的整个像素(使用Viewbox由 的缩放确定的相同比例Canvas)加剧了舍入误差。如果我们关闭StackPanel.Background(默认为透明)设置Canvas.Background为绿色并调低笔画颜色的不透明度,您可以更容易地看到这个图示:

截屏

您可以看到路径舍入与画布不同

因此,您要么必须关闭,UseLayoutRounding以便在操作中包含小数点,要么简化您的布局,以免发生错误。

例如,如果您通过删除不合适和多余的固定大小画布来让路径自行扩展,并设置Path.Stretch = Uniform您最终得到:

    <StackPanel Background="Red" Width="400" UseLayoutRounding="True">
        <StackPanel.Resources>
            <Style TargetType="Viewbox">
                <Setter Property="Height" Value="400" />
                <Setter Property="Margin" Value="0,0,0,50" />
            </Style>
            <Style TargetType="Path">
                <Setter Property="Stroke" Value="Blue" />
                <Setter Property="StrokeThickness" Value="2" />
                <Setter Property="Stretch" Value="Uniform" />
            </Style>
        </StackPanel.Resources>
        <Viewbox>
            <Path Data="M 1,1 h 3 v 3 h -3 z" />
        </Viewbox>
        <Viewbox>
            <Path Data="M 1,1 h 4 v 4 h -4 z" />
        </Viewbox>
    </StackPanel>

导致: 截屏

可能是您真正想要的

但是,如果这是一个过度简化,并且您实际上有多个路径打算放入您的Canvas.GridGrid他们保持同步(Canvass 不会布置他们的孩子)。代码如下所示:

    <StackPanel Background="Red" Width="400" UseLayoutRounding="True">
        <StackPanel.Resources>
            <Style TargetType="Viewbox">
                <Setter Property="Height" Value="400" />
                <Setter Property="Margin" Value="0,0,0,50" />
            </Style>
            <Style TargetType="Path">
                <Setter Property="Stroke" Value="Blue" />
                <Setter Property="StrokeThickness" Value="2" />
                <Setter Property="Stretch" Value="Uniform" />
            </Style>
        </StackPanel.Resources>
        <Viewbox>
            <Grid Width="5" Height="5">
                <Path Data="M 1,1 h 3 v 3 h -3 z" />
            </Grid>
        </Viewbox>
        <Viewbox>
            <Grid Width="6" Height="6">
                <Path Data="M 1,1 h 4 v 4 h -4 z" />
            </Grid>
        </Viewbox>
    </StackPanel>

结果与没有辅助容器的结果相同

希望这会有所帮助-ck

于 2013-04-11T15:37:14.027 回答
1

我可以用模拟器在我的机器上重现这个问题,显示分辨率为 2560x1440,画布如下。

<Canvas Width="4" Height="4">
    <Rectangle Width="4" Height="4" Fill="Blue" ></Rectangle>
</Canvas>

对于上面的片段 - 画布溢出/超出红色面板。

<Canvas Width="6" Height="6">
    <Rectangle Width="6" Height="6" Fill="Blue" ></Rectangle>
</Canvas>

对于上面的片段 - 画布下溢/不适合红色面板,并在红色面板的右边距上留下一些空间。

如果画布大小保持为 5 的倍数,则它适合红色面板。

Path 似乎不是问题,因为它也可以使用 rect 进行复制。ViewBox 缩放似乎有问题。我发现UseLayoutRounding="False"在 stackpanel 上 - 问题不会重现。在寻找 ViewBox 缩放问题时,我还发现了一个相关的线程。它建议使用SnapsToDevicePixels属性,但这不适用于 Windows 商店 xaml 应用程序。

总而言之,这似乎是 ViewBox 缩放的一个问题,尽管我不是具有内部视图框缩放算法知识的专业人士。可能的解决方法是如果 UseLayoutRounding 在另一台机器上通过测试,则将其设置为 false。5 的倍数看起来不是很好的解决方法,但您可以检查一下。在单独的说明中 - 如果您只是想知道它为什么会发生,您会得到答案,并且可能是几个像素的下溢/溢出可能对您的应用程序很重要。

于 2013-04-09T06:12:28.497 回答