This question is locked. New answers and comments are not allowed.
I'd like to create a 360-degree gauge representing a compass, and I'd like the needle to be animated. When the needle goes from, say, North-West (315) to North-East (45), I'd like it to go the shortest way, through North (0). Similarly, when it goes from SW to SE, it should go through South (180).
Can I achieve this with your gauge?
Eric.
Can I achieve this with your gauge?
Eric.
7 Answers, 1 is accepted
0
Accepted
Hi Eric,
The compass-like radial gauge can be created using following XAML:
Unfortunately you can’t switch build-in indicator’s animation to go the shortest way. It always walk from current to the next value through the values in the [current, next] interval. But you can create your own animation routines which will work as you’d like. You need check if the sweep angle between current and next value is more than 180 degree and then operate depends on the test result:
Check out Telerik Trainer , the state of the art learning tool for Telerik products.
The compass-like radial gauge can be created using following XAML:
<UserControl x:Class="TestGaugeApplication.Page" |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" |
xmlns:control="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Gauge" |
xmlns:gauge="clr-namespace:Telerik.Windows.Controls.Gauges;assembly=Telerik.Windows.Controls.Gauge" |
Width="500" Height="400"> |
<UserControl.Resources> |
<ResourceDictionary> |
<DataTemplate x:Key="TickLabelEmpty"> |
<Grid /> |
</DataTemplate> |
<Style x:Key="MajorCustomTicks" TargetType="TextBlock"> |
<Setter Property="FontFamily" Value="Arial" /> |
<Setter Property="FontSize" Value="14" /> |
<Setter Property="FontWeight" Value="Bold" /> |
</Style> |
<ControlTemplate x:Key="CompasNeedleTemplate" TargetType="gauge:Needle"> |
<Grid x:Name="PART_Grid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> |
<Grid.ColumnDefinitions> |
<ColumnDefinition Width="*" /> |
<!-- Column 0 - tail --> |
<ColumnDefinition Width="*" /> |
<!-- Column 1 - pin point --> |
<ColumnDefinition Width="*" /> |
<!-- Column 2 - arrow --> |
</Grid.ColumnDefinitions> |
<Grid.RowDefinitions> |
<RowDefinition Height="*" /> |
</Grid.RowDefinitions> |
<Grid x:Name="PART_Shape" Grid.ColumnSpan="3" Margin="0"> |
<Grid.ColumnDefinitions> |
<ColumnDefinition Width="50*" /> |
<ColumnDefinition Width="50*" /> |
</Grid.ColumnDefinitions> |
<Grid.RowDefinitions> |
<RowDefinition Height="0.3*" /> |
<RowDefinition Height="0.4*" /> |
<RowDefinition Height="0.3*" /> |
</Grid.RowDefinitions> |
<Path Grid.Row="1" |
Grid.Column="1" |
Stretch="Fill" |
Fill="Blue" |
StrokeThickness="1"> |
<Path.Data> |
<PathGeometry> |
<PathFigure StartPoint="1,0.5"> |
<LineSegment Point="0,1" /> |
<LineSegment Point="0,0" /> |
</PathFigure> |
</PathGeometry> |
</Path.Data> |
</Path> |
<Path Grid.Row="1" |
Grid.Column="0" |
Stretch="Fill" |
Fill="Red" |
StrokeThickness="1"> |
<Path.Data> |
<PathGeometry> |
<PathFigure StartPoint="1,0"> |
<LineSegment Point="1,1" /> |
<LineSegment Point="0,0.5" /> |
</PathFigure> |
</PathGeometry> |
</Path.Data> |
</Path> |
</Grid> |
<Grid Grid.Column="1"> |
<Grid.RowDefinitions> |
<RowDefinition Height="0.125*" /> |
<RowDefinition Height="0.75*" /> |
<RowDefinition Height="0.125*" /> |
</Grid.RowDefinitions> |
<Grid.ColumnDefinitions> |
<ColumnDefinition Width="0.125*" /> |
<ColumnDefinition Width="0.75*" /> |
<ColumnDefinition Width="0.125*" /> |
</Grid.ColumnDefinitions> |
<Ellipse Grid.Column="1" Grid.Row="1" Stretch="Uniform" |
Fill="White"> |
</Ellipse> |
</Grid> |
<Grid Grid.Column="1"> |
<Grid.RowDefinitions> |
<RowDefinition Height="0.25*" /> |
<RowDefinition Height="0.5*" /> |
<RowDefinition Height="0.25*" /> |
</Grid.RowDefinitions> |
<Grid.ColumnDefinitions> |
<ColumnDefinition Width="0.25*" /> |
<ColumnDefinition Width="0.5*" /> |
<ColumnDefinition Width="0.25*" /> |
</Grid.ColumnDefinitions> |
<Ellipse Grid.Column="1" Grid.Row="1" Stretch="Uniform" |
Fill="White"> |
</Ellipse> |
</Grid> |
</Grid> |
</ControlTemplate> |
<Style x:Key="CompasNeedleStyle" TargetType="gauge:Needle"> |
<Setter Property="Location" Value="OverCenter" /> |
<Setter Property="RelativeHeight" Value="0.4" /> |
<Setter Property="RelativeShift" Value="1.4" /> |
<Setter Property="Template" Value="{StaticResource CompasNeedleTemplate}" /> |
</Style> |
</ResourceDictionary> |
</UserControl.Resources> |
<Grid x:Name="LayoutRoot" Background="White"> |
<control:RadGauge x:Name="radGauge" Width="350" Height="350"> |
<gauge:RadialGauge> |
<gauge:RadialScale StartAngle="270" |
SweepAngle="360" |
Radius="0.83" |
Min="0" |
Max="360" |
MajorTickStep="90" |
ShowLastLabel="False" |
LabelRotationMode="None"> |
<gauge:RadialScale.Label> |
<gauge:LabelProperties ItemTemplate="{StaticResource TickLabelEmpty}"> |
</gauge:LabelProperties> |
</gauge:RadialScale.Label> |
<gauge:TickList> |
<gauge:CustomTickMark Value="0"> |
<gauge:CustomTickMark.ItemTemplate> |
<DataTemplate> |
<Grid> |
<TextBlock Foreground="Blue" |
Style="{StaticResource MajorCustomTicks}" |
Text="N" /> |
</Grid> |
</DataTemplate> |
</gauge:CustomTickMark.ItemTemplate> |
</gauge:CustomTickMark> |
<gauge:CustomTickMark Value="90"> |
<gauge:CustomTickMark.ItemTemplate> |
<DataTemplate> |
<Grid> |
<TextBlock Foreground="Blue" |
Style="{StaticResource MajorCustomTicks}" |
Text="E" /> |
</Grid> |
</DataTemplate> |
</gauge:CustomTickMark.ItemTemplate> |
</gauge:CustomTickMark> |
<gauge:CustomTickMark Value="180"> |
<gauge:CustomTickMark.ItemTemplate> |
<DataTemplate> |
<Grid> |
<TextBlock Foreground="Blue" |
Style="{StaticResource MajorCustomTicks}" |
Text="S" /> |
</Grid> |
</DataTemplate> |
</gauge:CustomTickMark.ItemTemplate> |
</gauge:CustomTickMark> |
<gauge:CustomTickMark Value="270"> |
<gauge:CustomTickMark.ItemTemplate> |
<DataTemplate> |
<Grid> |
<TextBlock Foreground="Blue" |
Style="{StaticResource MajorCustomTicks}" |
Text="W" /> |
</Grid> |
</DataTemplate> |
</gauge:CustomTickMark.ItemTemplate> |
</gauge:CustomTickMark> |
</gauge:TickList> |
<gauge:IndicatorList> |
<gauge:Needle x:Name="needle" Style="{StaticResource CompasNeedleStyle}" /> |
</gauge:IndicatorList> |
</gauge:RadialScale> |
</gauge:RadialGauge> |
</control:RadGauge> |
</Grid> |
</UserControl> |
Unfortunately you can’t switch build-in indicator’s animation to go the shortest way. It always walk from current to the next value through the values in the [current, next] interval. But you can create your own animation routines which will work as you’d like. You need check if the sweep angle between current and next value is more than 180 degree and then operate depends on the test result:
- If distance is less than 180 degree – create 1 double animation which will change value of the needle from current to next value.
- If distance is more than 180 degree – create 2 double animations. One from current value to 0 or 360 depends on direction of change. And second from 0 or 260 to the next value.
Following code represents how it can be done:
/// <summary> |
/// Indicates whether the 2 animations should be used |
/// </summary> |
private bool doubleAnimation = false; |
/// <summary> |
/// From value for second animation |
/// </summary> |
private double secondFromValue; |
/// <summary> |
/// To value for second animation |
/// </summary> |
private double secondToValue; |
private void SetNewValueToIndicator(double newValue) |
{ |
CreateAndRunAnimation(needle.Value, newValue); |
} |
private Storyboard CreateAnimation(double fromValue, double toValue, Duration duration) |
{ |
// Create DoubleAnimations and set their properties. |
DoubleAnimation needleValueAnimation = new DoubleAnimation(); |
needleValueAnimation.Duration = duration; |
Storyboard storyboard = new Storyboard(); |
storyboard.Children.Add(needleValueAnimation); |
Storyboard.SetTarget(needleValueAnimation, needle); |
Storyboard.SetTargetProperty(needleValueAnimation, new PropertyPath("(Needle.Value)")); |
needleValueAnimation.From = (double.IsNaN(fromValue) ? 0 : fromValue); |
needleValueAnimation.To = toValue; |
return storyboard; |
} |
private void CreateAndRunAnimation(double fromValue, double toValue) |
{ |
Duration duration; |
double distance = Math.Abs(toValue - fromValue); |
if (distance > 180) |
{ |
doubleAnimation = true; |
if (toValue > 180) |
{ |
secondFromValue = 360; |
secondToValue = toValue; |
toValue = 0; |
} |
else if (fromValue > 180) |
{ |
secondFromValue = 0; |
secondToValue = toValue; |
toValue = 360; |
} |
duration = new Duration(TimeSpan.FromSeconds(0.4)); |
} |
else |
{ |
doubleAnimation = false; |
duration = new Duration(TimeSpan.FromSeconds(0.8)); |
} |
Storyboard storyboard = CreateAnimation(fromValue, toValue, duration); |
storyboard.Completed += new EventHandler(Storyboard_Completed); |
storyboard.Begin(); |
} |
private void Storyboard_Completed(object sender, EventArgs e) |
{ |
if (doubleAnimation) |
{ |
// Create a duration of 1 seconds. |
Duration duration = new Duration(TimeSpan.FromSeconds(0.4)); |
Storyboard storyboard = CreateAnimation(secondFromValue, secondToValue, duration); |
storyboard.Begin(); |
} |
} |
All the best,
Andrey Murzov
the Telerik team
Check out Telerik Trainer , the state of the art learning tool for Telerik products.
0
Eric
Top achievements
Rank 1
answered on 26 Mar 2009, 05:44 PM
Many thanks.
Eric
Eric
0
Danette Cross
Top achievements
Rank 1
answered on 30 Jun 2010, 10:38 PM
What references do we use for the storyboard and doubleanimation? I have using statements for Telerik.Windows.Controls and Telerik.Windows.Controls.Guages but seems I am missing an assembly reference.
0
Hi Danette,
The Storyboard and DoubleAnimation classes are contained in the System.Windows.Media.Animation namespace.
Sincerely yours,
Andrey Murzov
the Telerik team
The Storyboard and DoubleAnimation classes are contained in the System.Windows.Media.Animation namespace.
Sincerely yours,
Andrey Murzov
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Chris
Top achievements
Rank 1
answered on 01 May 2012, 12:27 PM
Sorry to Hijack the thread but we have just purchased the RadControls and we have a need to create a compas that allows the user to move the needle and subsequently the guage value with the mouse, so they can in essence select a bearing by draging the needle, could anyone provide me with some guidance with the best way to achieve this ??
Many Thanks in advance
Many Thanks in advance
0
Hello Chris,
Simply set the RadialScale.IsInteractive property to true and you will be able to drag the needle and position it by clicking on the scale.
Kind regards,
Simply set the RadialScale.IsInteractive property to true and you will be able to drag the needle and position it by clicking on the scale.
Kind regards,
Andrey Murzov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Chris
Top achievements
Rank 1
answered on 04 May 2012, 10:14 AM
Many Thanks, it worked liked a charm :-)