Dynamically move object on canvas - c#

Scenario as follows.
I have an canvas on which I want to move, lets say an rectangel, across the screen. The way the rectangle is supposed to move is determined by one specific path (like a railway, the rectangle is supposed to only move on the rails). The position on which the rectangle is currently located is provided by external source.
Current Location is provided every ~200-500ms.
So far I have tried the following:
simple TranslateTransform. Does the trick, but the rectangle jumps from Point a to b. No smooth Translation.
Storyboard with a doubleAnimation
Smoother, but the rectangle doesn´t follow the required path.
DoubleAnimationUsingPath. Rectangle is moving on the path. But now I am not able to provide the current position by external source.
Easiest for me would be a way to use an DoubleAnimationUsingPath and providing the X-Koordinate by external source.
But I am not sure if overall storyboards and animations are the best way to tackel that Problem.
If you know of any completely different Approach I am more than happy hear about it.
Kind regards

Just to get an idea of what can be done with animations, take a look at this little demo of a object moving along a track:
<Canvas>
<Canvas.Resources>
<PathGeometry x:Key="track">
<PathFigure StartPoint="200,100" IsClosed="True">
<LineSegment Point="300,100"/>
<ArcSegment SweepDirection="Clockwise"
Size="100,100" Point="300,300"/>
<LineSegment Point="200,300"/>
<ArcSegment SweepDirection="Clockwise"
Size="100,100" Point="200,100"/>
</PathFigure>
</PathGeometry>
</Canvas.Resources>
<Canvas.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<MatrixAnimationUsingPath
Storyboard.TargetName="train"
Storyboard.TargetProperty="RenderTransform.Matrix"
PathGeometry="{StaticResource track}"
DoesRotateWithTangent="True"
Duration="0:0:10"
RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<Path Data="{StaticResource track}" Stroke="Black"
StrokeThickness="6"/>
<Path Data="{StaticResource track}" Stroke="White"
StrokeThickness="4" StrokeDashArray="2,2"/>
<Rectangle x:Name="train" Width="10" Height="6" Fill="Red"
Canvas.Left="-5" Canvas.Top="-3"
RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<MatrixTransform />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>

Related

Is it Possible to animate path.Data

I have code something like this:
<Path x:Name="arrow" StrokeThickness="3" Stroke="Black" Data="M34,115 C45,106 91,119 105,112 119,105 172,75.004352 188,82.003591" />
what I want is to animate the Data property of the path. I'm searching this from last two days didn't find a solution.
what I actually want is to show path bit by bit.
Does anyone have any Idea?
"what I actually want is to show path bit by bit"
Do you mean something like this?
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" >
<Grid.Resources>
<Storyboard x:Key="CWTrace">
<!-- To run opposite direction, just swap the 'From' and 'To' values. -->
<DoubleAnimation BeginTime="00:00:0.5" RepeatBehavior="Forever"
Storyboard.TargetName="arrow"
Storyboard.TargetProperty="StrokeDashOffset"
Duration="0:0:5" From="100" To="0"/>
</Storyboard>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource CWTrace}"/>
</EventTrigger>
</Grid.Triggers>
<Path x:Name="arrow"
StrokeDashOffset="0" StrokeDashArray="100"
StrokeThickness="3" Stroke="Black"
Data="M34,115 C45,106 91,119 105,112 119,105 172,75.004352 188,82.003591"/>
</Grid>
Obviously remove the RepeatBehavior for a one time anim, and tinker with values to get exactly what you're after. Cheers.

round robin image rotation what is the best way to do in WPF

I am looking to find the best way to do this in wpf. I already asked this question and got an answer which implement it in opencv. round robin image rotation what is the best way to do in opencv
What is the best way to do this in wpf.
Apparently I can create a writableBitmap and copy the pixels manually, but I don't think it is the best way to do this.
Edit 1
To clarify what I am asking: I like to implement the same algorithm that suggested in this SO question (round robin image rotation what is the best way to do in opencv) using WPF.
What is the best way to do this in WPF which is efficient (memory and speed).
You can use an ImageBrush to draw on a rectangle and adjust the ViewPort property of the brush to slide the image. If you wanted to do an animation with this, here is a sample XAML in WPF which uses animation to automatically adjust the viewport property of the brush and perform a slide animation. Hope this is helpful.
<Window x:Class="TestWpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Rectangle>
<Rectangle.Fill>
<DrawingBrush x:Name="MyBrush" Viewport="0,0,1,1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,100,100" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<ImageBrush ImageSource="lSXfX.png" />
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<RectAnimation
Storyboard.TargetName="MyBrush"
Storyboard.TargetProperty="Viewport"
From="0 0 1 1" To="1 0 1 1" Duration="0:0:10"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Grid>
</Window>

Is there an equivalent to CombinedGeometry in WinRT XAML?

I'm trying to draw a square with a round hole in it, so that one can see what's behind the rectangle. I've used the following code to accomplish this in WPF:
<Path Grid.Row="0" Grid.Column="1" Stretch="Uniform" Stroke="Black" Fill="Yellow">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,100,100"></RectangleGeometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"></EllipseGeometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
The CombinedGeometry class doesn't appear to exist in WinRT-XAML. Basically I want to create a game board that you drop pieces into from the top, and animate the pieces falling into place behind the board.
Any suggestions for what I should use instead of a CombinedGeometry? ... or suggestions on how to get CombinedGeometry to work in WinRT-XAML?
Thanks!
Dave
It is not really an equivalent, but it can do the Job :
<!-- Creates a composite shape from three geometries. -->
<GeometryGroup FillRule="EvenOdd">
<LineGeometry StartPoint="10,10" EndPoint="50,30" />
<EllipseGeometry Center="40,70" RadiusX="30" RadiusY="30" />
<RectangleGeometry Rect="30,55 100 30" />
</GeometryGroup>
</Path.Data>

PointAnimation on Path and BezierSegment

I ran into a problem. I'm trying to animate a simple Path with PointAnimation. I have a working solution for WPF, and I tried to use it in my Metro app. However it's syntactically correct, it doesn't do anything. What I missed? What I need to change in my XAML?
<Path Stroke="DarkMagenta" StrokeThickness="2">
<Path.Data>
<GeometryGroup>
<PathGeometry>
<PathFigure StartPoint="0,0">
<BezierSegment x:Name="bezierSegment1" Point1="100,0" Point2="100,200" Point3="200,200" />
</PathFigure>
</PathGeometry>
</GeometryGroup>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<PointAnimation Storyboard.TargetName="bezierSegment1" Storyboard.TargetProperty="Point1" From="0,0" To="100,0" />
<PointAnimation Storyboard.TargetName="bezierSegment1" Storyboard.TargetProperty="Point2" From="0,0" To="100,200" />
<PointAnimation Storyboard.TargetName="bezierSegment1" Storyboard.TargetProperty="Point3" From="0,0" To="200,200" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
I tried to put the storyboard into resources and begin outside from a Button_Click handler, but it doesn't helped.
Oh yes,yes.
EnableDependentAnimation is an important property to animations that allows you to animate your custom dependency properties. It’s handy, but not enough people know about it yet. Spread the word to save people from banging their heads against the wall!
Thank you Jerry Nixon: http://blog.jerrynixon.com/2012/06/windows-8-animated-pie-slice.html

WPF rotating button

Help me plz. I need to animate rotation of the button on z-axis without using external libraries, only with C# and xaml code.
Is that possible? How can I do that?
Thanks.
Have a look at Viewport2DVisual3D
The example in the link does exactly that.
Edit: Here is the example from the link with an added animation of the Z axis
Looks like this
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera Position="0, 0, 4"/>
</Viewport3D.Camera>
<Viewport2DVisual3D x:Name="v2dv3d">
<Viewport2DVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Viewport2DVisual3D.Transform>
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D Positions="-1,1,0 -1,-1,0 1,-1,0 1,1,0"
TextureCoordinates="0,0 0,1 1,1 1,0" TriangleIndices="0 1 2 0 2 3"/>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
</Viewport2DVisual3D.Material>
<Button Content="Hello, 3D">
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<Rotation3DAnimation Storyboard.TargetName="v2dv3d"
Storyboard.TargetProperty="(Viewport2DVisual3D.Transform).(RotateTransform3D.Rotation)"
Duration="0:0:2"
BeginTime="0:0:0">
<Rotation3DAnimation.From>
<AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
</Rotation3DAnimation.From>
<Rotation3DAnimation.To>
<AxisAngleRotation3D Angle="90" Axis="0, 1, 0" />
</Rotation3DAnimation.To>
</Rotation3DAnimation>
<Rotation3DAnimation Storyboard.TargetName="v2dv3d"
Storyboard.TargetProperty="(Viewport2DVisual3D.Transform).(RotateTransform3D.Rotation)"
Duration="0:0:2"
BeginTime="0:0:2">
<Rotation3DAnimation.From>
<AxisAngleRotation3D Angle="-90" Axis="0, 1, 0" />
</Rotation3DAnimation.From>
<Rotation3DAnimation.To>
<AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
</Rotation3DAnimation.To>
</Rotation3DAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Viewport2DVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFFFF" Direction="0,0,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
Transformations may help you in this case. Look at here if that helps.
The RotateTransform class is used to rotate a WPF object in an X-Y
plane. It can be applied via XAML or directly via imperative code.
If you only need to rotate your button about the Z axis, then you won't need any 3D graphics. All UIElements (such as Buttons) have the property RenderTransform, which enables basic transformation of their default appearance. By means of Storyboards, WPF allows you to animate almost any dependency property. You can use a storyboard, triggered on load, to animate the Angle property of a RotateTransform applied to the button:
<Button Width="100" Height="100" Content="Wheeee!">
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="ButtonRotation" Storyboard.TargetProperty="Angle">
<DoubleAnimation From="0" To="360" Duration="0:0:3" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
<Button.RenderTransform>
<RotateTransform x:Name="ButtonRotation" CenterX="50" CenterY="50" Angle="45"/>
</Button.RenderTransform>
</Button>
The Viewport2DVisual3D, as recommended by #Meleak, also supports animation, and is fun to play with if you have time. To animate the MSDN example, you need to add a name to the AxisAngleRotation3D element and switch it to target the Z axis:
<AxisAngleRotation3D x:Name="RotateAboutZ" Angle="40" Axis="0, 0, 1" />
Then, as above, trigger a storyboard to begin on the Loaded event of the Viewport3D. In either case, if you need more control over the animation, you can make your storyboard a named resource to be referenced by other events, or even build and control it entirely in code.
More about 2D transforms
More about 3D transforms

Categories