4

Just wondering how I might go about drawing arrow heads along a path. The path will change direction and go through several different points. The arrow heads are designed to show the user which direction along the path they need to travel.

I've tried to use a brush but it didn't work as I need the arrow heads to orientate them selfs along the path...

vdh_ant
  • 12,720
  • 13
  • 66
  • 86

1 Answers1

5

See Path Animations Overview and MatrixAnimationUsingPath

It can be used to move a control along a PathGeometry and if you set DoesRotateWithTangent the control will also rotate along the direction of the path.

EDIT1:

<Page.Resources>
    <PathGeometry x:Key="Path" x:Shared="False" Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"/>
</Page.Resources>
<Canvas Width="400" Height="400">
    <Path Data="{StaticResource Path}" Stroke="Blue" StrokeThickness="1"/>
    <Path
        x:Name="Arrow1"
        Stretch="Fill"
        Width="16" Height="16" StrokeLineJoin="Miter"
        Data="M 0 -5 L 10 -5 M 5 0 L 10 -5 L 5 -10" 
        Stroke="Black" StrokeThickness="3">
        <Path.RenderTransform>
            <TransformGroup>
                <TranslateTransform X="-8" Y="-8"/>
                <MatrixTransform>
                    <MatrixTransform.Matrix>
                        <Matrix/>
                    </MatrixTransform.Matrix>
                </MatrixTransform>
            </TransformGroup>
        </Path.RenderTransform>
        <Path.Triggers>
            <EventTrigger RoutedEvent="Path.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <MatrixAnimationUsingPath
                            Storyboard.TargetName="Arrow1"
                            Storyboard.TargetProperty="RenderTransform.Children[1].Matrix"                                
                            DoesRotateWithTangent="True"
                            Duration="0:0:5" 
                            BeginTime="0:0:0"
                            RepeatBehavior="Forever" PathGeometry="{StaticResource Path}" >                               
                        </MatrixAnimationUsingPath>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Path.Triggers>
    </Path>
</Canvas>

EDIT2: Calculating how many arrows you need

I assume you're creating a custom control and are programmatically adding arrows? If so i think the simplest way would be to specify a Duration for a single loop and a BeginTimeGap, the time between the BeginTimes of subsequent arrows. The number of arrows you have to add would be Duration/BeginTimeGap, or in simplified code:

while (BeginTime < Duration) 
{ 
    //add arrow with BeginTime and Duration; 
    BeginTime += BeginTimeGap; 
}

Getting the right speed and spacing between arrows would come down to tweaking these two values.

Bubblewrap
  • 7,266
  • 1
  • 35
  • 33
  • I've had a look and I don't think that this is anything along the lines of what I'm after. – vdh_ant Sep 08 '10 at 15:24
  • You sure? Try running the xaml i added...if that's not what you want, could try to clarify in your question? – Bubblewrap Sep 08 '10 at 15:55
  • Ok, I'm interested ;) Ok how would this be modified to have one arrow head moving along the line spaced by 40px... So its like a continual stream of arrow heads? – vdh_ant Sep 08 '10 at 16:11
  • If you have a static path that won't change the simple solution would be to add multiple arrows, but set a different BeginTime on each animation. If the path is variable you'd have to create a custom control that accepts a PathGeometry and programmatically creates arrows like Arrow1 in code based on the PathGeometry. In the code you could also calculate an ideal gap between BeginTimes of the arrows – Bubblewrap Sep 08 '10 at 18:24
  • How would I work out how many arrows I would need... Otherwise I can see myself just going in a loop and creating endless amounts of arrows... – vdh_ant Sep 08 '10 at 18:43
  • Is there event that runs that I could tap into on the first arrow that would tell me when it reaches the end... Although there would have to be a better way that that... – vdh_ant Sep 08 '10 at 18:43
  • Event would be possible i think, but calculating it would be prettier. See my 2nd edit. – Bubblewrap Sep 09 '10 at 07:00
  • The problem with calculating it is that I don't know how long the line is (i.e. the longer the line the more time is required)... do you know if there is anyway to ask a path how long it is so that I can calculate this? – vdh_ant Sep 09 '10 at 12:42
  • Unfortunately i know of no simple method to get the length of the path. I've seen that GetFlattenedPathGeometry was mentioned elsewhere, i'm guessing the PathGeometry that this method returns could be used to manually calculate the length by iterating over the pathsegments, which i assume would straight lines since it's a polygonal approximation. – Bubblewrap Sep 09 '10 at 14:52