views:

168

answers:

2

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...

+1  A: 

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
I've had a look and I don't think that this is anything along the lines of what I'm after.
vdh_ant
You sure? Try running the xaml i added...if that's not what you want, could try to clarify in your question?
Bubblewrap
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
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
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
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
Event would be possible i think, but calculating it would be prettier. See my 2nd edit.
Bubblewrap
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
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
+1  A: 

see this link

mdm20
Note I don't just want arrow heads at either end, but actually have arrow heads every X pixels along the path... Does that make sense?
vdh_ant
His code already contains the logic to align the arrow to the path, you just need to repeat it along the path instead of just at one end.
mdm20
Ok I'll have to have a look at it tonight and see how it goes. I was hoping to have something out of the box, but this looks promising.
vdh_ant
I have been looking at this and I don't think that its going to be a simple as you have suggested... The reason being that if I want to draw arrow heads every x pixels along the path I need to know where those points are... discovering those points isn't a trivial task. Finding points is, but finding non-set points along this is more difficult... Any idea on same code I might use to do this?
vdh_ant