6

ビューボックスを使用して、固定サイズのキャンバスを拡大縮小しています(意味のある画像を形成するさまざまなパスが含まれています)。

<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でネイティブにレンダリングすると上に表示され、エミュレーターでレンダリングすると下に表示されます。エミュレーターが目的の結果を生成しているので、2番目のパスが赤いパネルを超えている理由を誰かに説明してもらえますか?

私のPCでネイティブにレンダリング エミュレーターでレンダリング

4

2 に答える 2

5

本当に矛盾はありません...何が起こっているのかというと、あなたは本当に小さくレンダリングするものを取っているということです(あなたの道は非常に小さいです):

スクリーンショット

小さな箱を見てください

...そしてそれを非常に大きくスケールアップし、レイアウトに最も近いピクセル全体に丸めるように指示しますUseLayoutRounding

結果の信頼性が低い理由は、実際にはコンテンツがレイアウトされていないため、 Pathsが独立してスケーリングされているためです。Canvasしたがって、パスポイントの1つが不均一なピクセル境界に到達すると(一部の画面解像度では発生する可能性があり、他の解像度では発生しない可能性があります)、スケーリングされていないキャンバス内の最も近い仮想ピクセルに丸められ、これはからスケーリングされてから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、実際に独自のレイアウトを実行するコンテナを使用することをお勧めします。当然の選択はGrid、パスをそのままスケーリングできる方法です。それらをロックステップにGrid維持します(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でも再現されるので、Pathの問題ではないようです。ViewBoxのスケーリングに問題があるようです。UseLayoutRounding="False"スタックパネルで-問題が再現されないことがわかりました。また、ViewBoxのスケーリングの問題を探しているときに、関連するスレッドを見つけました。プロパティを使用することをお勧めしSnapsToDevicePixelsますが、Windowsストアのxamlアプリでは使用できません。

要約すると、私はビューボックススケーリングアルゴリズムの内部知識を持つプロではありませんが、ビューボックススケーリングの問題のようです。考えられる回避策は、UseLayoutRoundingが別のマシンでのテストに合格した場合にfalseに設定することです。5の倍数は、適切な回避策のようには見えませんが、確認できます。別の注意点として、なぜそれが起こっているのか知りたいだけなら、答えが得られ、数ピクセルのアンダーフロー/オーバーフローがアプリケーションにとって問題になる可能性があります。

于 2013-04-09T06:12:28.497 に答える