I have created myself a small prototype for a marquee. It moves the label from the right edge of the screen to the left. Once there, it starts again at the right so that it looks infinite. Like a news ticker.
My problem is that, the label shifts its position very juddery. It just seems rude and bumpy. I move the label every 33 ms to 1.0 to the left.
My renderer running on the hardware side (Tier 2). Framework: 4.5
XAML:
<Window x:Class="Canny.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="811" Name="main">
<Canvas Name="myCanvas" Background="Black">
<Label Name="lb1" Content="Lauftext+++" Foreground="WhiteSmoke" FontSize="25" Canvas.Left="618" Canvas.Top="10" FontFamily="Courier New" FontWeight="ExtraBold" FontStretch="UltraExpanded"/>
</Canvas>
XAML.CS:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
namespace Canny
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer timer;
double newPos;
readonly double actualWidthLb;
int renderingTier;
public MainWindow()
{
InitializeComponent();
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(33.0);
timer.Tick += timer_Tick;
newPos = myCanvas.ActualWidth;
actualWidthLb = lb1.ActualWidth;
timer.Start();
renderingTier = (RenderCapability.Tier >> 16);
}
void timer_Tick(object sender, EventArgs e)
{
newPos -= 1.0;
Canvas.SetLeft(lb1,newPos);
if (Canvas.GetLeft(lb1) + actualWidthLb <= 0)
{
Canvas.SetLeft(lb1, myCanvas.ActualWidth);
newPos = myCanvas.ActualWidth;
}
}
}
}
I thank you in advance about advices!
Have you tried to lower the timer intervall? 33ms are about 30Hz. This rate is much too slow for our eyes to be experienced as a fluently moving picture. Our eyes are faster than this! Thats why you start at least witha rate of 50Hz (20ms) but for a real smooth experience you better start with 70Hz which is similar to 14ms or even faster. (frequency: f = 1/T). To adjust the scrolling speed you could lower the steps (e.g incrementing position value x = x - 0.1 -> slower or x = x - 0.01 -> 100x slower compared to incrementing x by -1.0) and vice versa.
You may consider to use your DispatcherTimer with a DispatcherPriority (via constructor) with a priority something like Render or higher...
But if you are using WPF why don't make use of the nice animation features provided? It's quickly and easily done with Blend. MSDN - How to: Animate an Object Along a Path (Double Animation)