10

私は、ポリゴンを画面の左側から完全に画面を横切って移動させ、次に画面の右側から完全に離してから、元に戻そうとしています。

私はこれを機能させました。しかし、何らかの理由で、左マージンが負になるとすぐに、アニメーションが突然遅くなります。左マージンが正になるとすぐに、再び速度が上がります。

なぜこれが起こるのですか?どうすればそれを止めることができますか?

これを示す完全なコードは次のとおりです。

<Window x:Class="Geometry.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <PathGeometry x:Key="MyGeometry">
            <PathGeometry.Figures>
                <PathFigure>
                    <PathFigure.Segments>
                        <LineSegment Point="0.30,0" />
                        <LineSegment Point="0.70,1" />
                        <LineSegment Point="0.40,1" />
                        <LineSegment Point="0,0" />
                    </PathFigure.Segments>
                </PathFigure>
            </PathGeometry.Figures>
        </PathGeometry>
        <Storyboard x:Key="MovingAnimation">
            <ThicknessAnimationUsingKeyFrames RepeatBehavior="1:0:0" FillBehavior="HoldEnd" Storyboard.TargetName="_path" Storyboard.TargetProperty="Margin" >
                <DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="-2.0,0,0,0"  />
                <LinearThicknessKeyFrame KeyTime="0:0:10" Value="1.0,0,0,0"  />
                <LinearThicknessKeyFrame KeyTime="0:0:20" Value="-2.0,0,0,0"  />
            </ThicknessAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard Storyboard="{StaticResource MovingAnimation}" ></BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <Label>Margin:</Label>
            <TextBlock Text="{Binding ElementName=_path, Path=Margin.Left, StringFormat={}{0:0.#}}" />
        </StackPanel>
    <Canvas Name="_canvas" Grid.Row="1">
        <Border Margin="0" Width="1" Height="1" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Border.RenderTransform>
                <ScaleTransform 
                    ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}" 
                    ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
                    CenterX="0"
                    CenterY="0">
                </ScaleTransform>
            </Border.RenderTransform>
            <Path 
                Name="_path" 
                Fill="#CCCCFF" 
                Data="{StaticResource MyGeometry}" 
                Width="1.0" 
                Height="1.0" 
                >
        </Path>
        </Border>
    </Canvas>
    </Grid>
</Window>
4

3 に答える 3

4

負のマージンのアニメーションが遅い理由はわかりませんが、回避策を見つけました。

Marginのをアニメーション化する代わりに、パスを含むオブジェクトの の値Pathをアニメーション化しました。スケールの前に翻訳が適用されるように、を の前に配置する必要がありました。これにより、 に使用したのとほぼ同じ値をアニメーションで使用できます。XTranslateTransformBorderTranslateTransformScaleTransformMargin

    <Storyboard x:Key="MovingAnimation">
        <ThicknessAnimationUsingKeyFrames RepeatBehavior="1:0:0"  Storyboard.TargetName="_blank" Storyboard.TargetProperty="Margin" >
            <LinearThicknessKeyFrame KeyTime="0:0:0" Value="-1.5,0,0,0"  />
            <LinearThicknessKeyFrame KeyTime="0:0:10" Value="1,0,0,0"  />
            <LinearThicknessKeyFrame KeyTime="0:0:20" Value="-1.5,0,0,0"  />
        </ThicknessAnimationUsingKeyFrames>
    </Storyboard>

X醜い部分は、キー フレームの値を のプロパティに直接適用する簡単な方法が見つからなかったことです。そのため、要素バインディングとプレースホルダーオブジェクトTranslateTransformをごまかして使用しました。Canvas

    <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="5">
        <TextBlock Margin="0,0,5,0" Text="Margin.Left:"/>
        <TextBlock Text="{Binding ElementName=_blank, Path=Margin.Left, StringFormat={}{0:0.#}}" />
    </StackPanel>
    <Canvas Name="_blank" />  <!--Placeholder object-->
    <Canvas Name="_canvas" Grid.Row="1">
        <Border Margin="0" Width="1" Height="1"
                Name="_border"
                VerticalAlignment="Center" HorizontalAlignment="Center">
            <Border.RenderTransform>
                <TransformGroup>
                    <TranslateTransform X="{Binding Margin.Left, ElementName=_blank}"/>
                    <ScaleTransform 
                        ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}" 
                        ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
                        CenterX="0"
                        CenterY="0">
                    </ScaleTransform>
                </TransformGroup>
            </Border.RenderTransform>

アニメーションがまだ a に適用され、Margin次にTranslateTransformthrough 要素バインディングに適用されている場合でも、負のマージンの遅延はなくなります。

Path負のマージンの遅延は、スケーリングされていた の存在と関係があると思われBorderますが、それは私の推測です。

値を のプロパティにKeyFrame直接バインドする方法を見つけることができれば、この回避策の見苦しさが大幅に軽減されます。XTranslateTransform

編集: 使用する適切なバインディングを考え出しました:

    <Storyboard x:Key="MovingAnimation2">
        <DoubleAnimationUsingKeyFrames RepeatBehavior="1:0:0"  Storyboard.TargetName="tt" Storyboard.TargetProperty="X" >
            <LinearDoubleKeyFrame KeyTime="0:0:0" Value="-1.5"  />
            <LinearDoubleKeyFrame KeyTime="0:0:5" Value="1"  />
            <LinearDoubleKeyFrame KeyTime="0:0:10" Value="-1.5"  />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>

これにより、余分なキャンバス プレースホルダー オブジェクトが取り除かれます。

    <Canvas Name="_canvas" Grid.Row="1">
        <Border Margin="0" Width="1" Height="1"
                Name="_border"
                VerticalAlignment="Center" HorizontalAlignment="Center">
            <Border.RenderTransform>
                <TransformGroup>
                    <TranslateTransform x:Name="tt"/>
                    <ScaleTransform 
                        ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}" 
                        ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
                        CenterX="0"
                        CenterY="0">
                    </ScaleTransform>
                </TransformGroup>
            </Border.RenderTransform>
于 2013-06-10T14:33:10.263 に答える
3

Marginプロパティをアニメーション化すると、追加の測定/配置パスがトリガーされ、パフォーマンスへの影響が少し大きくなります (ただし、この例では目立たない場合があります)。一方、「レンダリングのみ」のプロパティのアニメーションは、レイアウトの再配置をトリガーしないため、パフォーマンスが向上します。

あなたが取得したいことを行うための少し簡単な方法を見てください:

<Window x:Class="Geometry.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="518" Width="530">
<Window.Resources>
    <PathGeometry x:Key="MyGeometry">
        <PathGeometry.Figures>
            <PathFigure>
                <PathFigure.Segments>
                    <LineSegment Point="0.30,0" />
                    <LineSegment Point="0.70,1" />
                    <LineSegment Point="0.40,1" />
                    <LineSegment Point="0,0" />
                </PathFigure.Segments>
            </PathFigure>
        </PathGeometry.Figures>
    </PathGeometry>
    <Storyboard x:Key="MovingAnimation">
        <DoubleAnimationUsingKeyFrames RepeatBehavior="1:0:0" FillBehavior="HoldEnd" Storyboard.TargetName="_scaleTransform" Storyboard.TargetProperty="CenterX" >
            <LinearDoubleKeyFrame KeyTime="0:0:0" Value="1.2" />
            <LinearDoubleKeyFrame KeyTime="0:0:10" Value="-0.5" />
            <LinearDoubleKeyFrame KeyTime="0:0:20" Value="1.2" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">
        <BeginStoryboard Storyboard="{StaticResource MovingAnimation}" ></BeginStoryboard>
    </EventTrigger>
</Window.Triggers>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0" Orientation="Horizontal">
        <Label>Margin:</Label>
        <TextBlock Text="{Binding ElementName=_scaleTransform, Path=CenterX, StringFormat={}{0:0.#}}" VerticalAlignment="Center" />
    </StackPanel>
<!--
    <Border Grid.Row="1" Margin="150" BorderBrush="Red" BorderThickness="1">
-->
    <Grid Name="_canvas" Grid.Row="1">
        <Path Name="_path" Fill="#CCCCFF" Data="{StaticResource MyGeometry}" 
              Width="1.0"
              Height="1.0"
              HorizontalAlignment="Center"
              VerticalAlignment="Center">
            <Path.RenderTransform>
                <ScaleTransform x:Name="_scaleTransform"
                    ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}" 
                    ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
                    CenterX="1.2"
                    CenterY="0.5">
                </ScaleTransform>
            </Path.RenderTransform>
        </Path>
    </Grid>
<!--
    </Border>
-->
</Grid>
</Window>
于 2013-06-10T14:33:57.217 に答える
1

これまでの 2 つの回答から、図形を画面上で飛び回らせたい場合は、余白をアニメーション化しないことは明らかです。

  • Stewbob は、移動変換の X 値をアニメートすることで問題を解決しました。
  • Sevenate は、スケール変換の中心 X 値をアニメーション化することで問題を解決しました。

もう 1 つの解決策は、ポリゴンを境界線でラップして余白をアニメーション化する代わりに、キャンバスでラップして左の値をアニメーション化することです。

キャンバスにラップする:

    <Canvas Name="_canvasFrame" Grid.Row="1">
        <Canvas Margin="0" Width="1" Height="1">
            <Canvas.RenderTransform>
                <ScaleTransform 
                ScaleX="{Binding ElementName=_canvasFrame, Path=ActualWidth}" 
                ScaleY="{Binding ElementName=_canvasFrame, Path=ActualHeight}"
                CenterX="0"
                CenterY="0">
                </ScaleTransform>
            </Canvas.RenderTransform>
            <Path 
            Name="_path" 
            Fill="#CCCCFF" 
            Data="{StaticResource MyGeometry}" 
            Width="1.0" Height="1.0" 
            >
            </Path>
        </Canvas>
    </Canvas>

次に、左の値をアニメーション化します。

    <Storyboard x:Key="MovingAnimation">
        <DoubleAnimationUsingKeyFrames 
                          RepeatBehavior="1:0:0" 
                          FillBehavior="HoldEnd" 
                          Storyboard.TargetName="_path" 
                          Storyboard.TargetProperty="(Canvas.Left)" >
            <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="-1.0"  />
            <LinearDoubleKeyFrame KeyTime="0:0:10" Value="1.0"  />
            <LinearDoubleKeyFrame KeyTime="0:0:20" Value="-1.0"  />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
于 2013-06-10T22:24:24.720 に答える