如何提高此控件的性能
本文关键字:性能 控件 何提高 | 更新日期: 2023-09-27 18:29:49
我需要一个项目的字幕,经过多次谷歌搜索和反复尝试,我创建了一个。但是,动画本身有点抖动。我需要一些关于如何提高性能的建议。谢谢p.s.有些代码可能是多余的。。。
public class Marquee : Canvas
{
static Marquee()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Marquee), new FrameworkPropertyMetadata(typeof(Marquee)));
}
private IList<string> _lines = new List<string>();
private IList<string> Lines
{
get
{
return _lines;
}
set
{
_lines = value;
}
}
public double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for FontSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FontSizeProperty =
DependencyProperty.Register("FontSize", typeof(double), typeof(Marquee));
public Brush FontBrush
{
get { return (Brush)GetValue(FontBrushProperty); }
set { SetValue(FontBrushProperty, value); }
}
// Using a DependencyProperty as the backing store for FontBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FontBrushProperty =
DependencyProperty.Register("FontBrush", typeof(Brush), typeof(Marquee));
public string SourceFile { get; set; }
List<RenderTargetBitmap> _images = new List<RenderTargetBitmap>();
private void CreateBitmaps()
{
foreach (var line in Lines)
{
FormattedText ft = new FormattedText(line,
System.Globalization.CultureInfo.CurrentUICulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(FontFamily.Source),
FontSize,
FontBrush);
if (ft.Height == 0 || ft.Width == 0)
continue;
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawText(ft, new Point(0, 0));
drawingContext.Close();
RenderTargetBitmap bmp = new RenderTargetBitmap((int)ft.Width, (int)ft.Height, 72, 72, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
bmp.Freeze();
_images.Add(bmp);
}
}
private int nextImgIndex = 0;
private Image _Image;
private void GetNextImage()
{
if (_images.Count == 0)
return;
if (nextImgIndex >= _images.Count)
nextImgIndex = 0;
_Image.Source = _images.ElementAt(nextImgIndex++);
}
private string _curStr = null;
private string CurrentString
{
get
{
return _curStr;
}
set
{
_curStr = value;
}
}
TextBlock _textBlock = new TextBlock();
DispatcherTimer timer;
public Marquee()
{
Loaded += Marquee_Loaded;
FontSize = 12;
FontBrush = Brushes.Black;
if (Rate == 0d)
{
Rate = 150d;
}
this.CacheMode = new BitmapCache(2);
FontBrush.Freeze();
_Image = new Image();
_Image.CacheMode = new BitmapCache();
_Image.ClipToBounds = false;
FontFamily = new FontFamily("Calibri");
this.Children.Add(_Image);
}
void Marquee_Loaded(object sender, RoutedEventArgs e)
{
ReadFile();
CreateBitmaps();
CreateAnimation();
//throw new NotImplementedException();
}
//[ValueConversion(typeof(string), typeof(TimeSpan))]
//public class StringFormatConverter : IValueConverter
//{
// public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
// {
// string[] vals = ((string)value).Split(new[] { ':' });
// if (vals.Count() != 3)
// throw new FormatException(string.Format("Invalid timespan format : {0}", value));
// return new TimeSpan(int.Parse(vals[0]), int.Parse(vals[1]), int.Parse(vals[2]));
// }
// public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
// {
// throw new NotImplementedException();
// }
//}
DoubleAnimation anim;
TranslateTransform transform;
Duration duration;
public double Rate { get; set; }
void CreateAnimation()
{
if (CurrentString == null)
return;
GetNextImage();
transform = new TranslateTransform(Application.Current.MainWindow.ActualWidth, 0);
_Image.RenderTransform = transform;
var width = _Image.Source.Width;
double secs = (Application.Current.MainWindow.ActualWidth + width) / Rate;
duration = new Duration(TimeSpan.FromSeconds(secs));
anim = new DoubleAnimation(-width, duration);
anim.Completed += anim_Completed;
transform.BeginAnimation(TranslateTransform.XProperty, anim);
}
void anim_Completed(object sender, EventArgs e)
{
CreateAnimation();
}
double MeasureStringLength(string text)
{
if (text == null)
return 0;
FormattedText ft = new FormattedText(text,
System.Globalization.CultureInfo.CurrentUICulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(_textBlock.FontFamily.ToString()),
FontSize,
FontBrush);
return ft.Width;
}
public FontFamily FontFamily
{
get { return (FontFamily)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
// Using a DependencyProperty as the backing store for FontFamily. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FontFamilyProperty =
DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(Marquee));
FormattedText GetFormattedText(string text)
{
if (text == null)
return null;
FormattedText ft = new FormattedText(text,
System.Globalization.CultureInfo.CurrentUICulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(_textBlock.FontFamily.ToString()),
FontSize,
FontBrush);
return ft;
}
void ReadFile()
{
if (SourceFile == null)
return;
StreamReader fR = new StreamReader(SourceFile);
string line;
while ((line = fR.ReadLine()) != null)
{
Lines.Add(line);
}
if (Lines.Count > 0)
CurrentString = Lines[0];
}
}
我以以下方式修改了您的控件(删除变换动画,使用直接渲染而不是渲染到图像缓存):
public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register("Offset", typeof(double),
typeof(Marquee), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
//
public double Offset {
get { return (double)GetValue(OffsetProperty); }
}
protected override void OnRender(DrawingContext dc) {
dc.DrawText(currentText, new Point(Offset, 0)); // direct render
}
int nextTextIndex = 0;
FormattedText currentText;
void GetNextText() {
if(formattedTexts.Count == 0) return;
currentText = formattedTexts[(nextTextIndex++) % formattedTexts.Count];
}
void CreateAnimation() {
if(CurrentString == null)
return;
GetNextText();
double width = currentText.Width;
double secs = (Application.Current.MainWindow.ActualWidth + width) / Rate;
duration = new Duration(TimeSpan.FromSeconds(secs));
anim = new DoubleAnimation(0, -width, duration);
anim.Completed += anim_Completed;
BeginAnimation(OffsetProperty, anim);
}
//
void anim_Completed(object sender, EventArgs e) {
anim.Completed -= anim_Completed;
CreateAnimation();
}
List<FormattedText> formattedTexts = new List<FormattedText>();
void CreateTexts() {
foreach(var line in Lines) {
FormattedText ft = new FormattedText(line,
System.Globalization.CultureInfo.CurrentUICulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(FontFamily.Source),
FontSize,
FontBrush);
if(ft.Height == 0 || ft.Width == 0)
continue;
formattedTexts.Add(ft);
}
}
现在它对我来说更流畅了。