下面是WPF中的一个小型图形演示。它看起来像这样:
当它运行时,如果我在窗口的主区域周围移动鼠标,动画会变慢(至少在我的系统上)。如果我将鼠标指针完全移出窗口,动画会恢复速度。
有关如何防止鼠标移动干扰动画速度的任何建议吗?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
namespace WPF_Golden_Section
{
class DrawingVisualElement : FrameworkElement
{
public DrawingVisual visual;
public DrawingVisualElement() { visual = new DrawingVisual(); }
protected override int VisualChildrenCount { get { return 1; } }
protected override Visual GetVisualChild(int index) { return visual; }
}
public static class CanvasUtils
{
public static Canvas SetCoordinateSystem(this Canvas canvas, Double xMin, Double xMax, Double yMin, Double yMax)
{
var width = xMax - xMin;
var height = yMax - yMin;
var translateX = -xMin;
var translateY = height + yMin;
var group = new TransformGroup();
group.Children.Add(new TranslateTransform(translateX, -translateY));
group.Children.Add(new ScaleTransform(canvas.ActualWidth / width, canvas.ActualHeight / -height));
canvas.RenderTransform = group;
return canvas;
}
}
public static class ColorUtils
{
public static Color Write(this Color color)
{
Console.Write("Color[{0} {1} {2} {3}]", color.A, color.R, color.G, color.B);
return color;
}
static byte ColorComponentToByte(double n)
{
return
(byte)
Math.Round(Math.Min(Math.Max(n, 0), 1) * 255);
}
public static Color Rgb(double r, double g, double b)
{
return
Color.FromRgb(
ColorComponentToByte(r),
ColorComponentToByte(g),
ColorComponentToByte(b));
}
public static Color SetArgb(this Color color, double a, double r, double g, double b)
{
color.A = ColorComponentToByte(a);
color.R = ColorComponentToByte(r);
color.G = ColorComponentToByte(g);
color.B = ColorComponentToByte(b);
return color;
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Width = 600;
Height = 600;
var dockPanel = new DockPanel();
Content = dockPanel;
var slider =
new Slider()
{
Minimum = 0.1,
Maximum = 10,
LargeChange = 0.001,
Value = 1
};
dockPanel.Children.Add(slider);
DockPanel.SetDock(slider, Dock.Top);
var incrementSlider =
new Slider()
{
Maximum = 0.001,
Minimum = 0.00001,
Value = 0.0001
};
dockPanel.Children.Add(incrementSlider);
DockPanel.SetDock(incrementSlider, Dock.Top);
var pauseButton = new Button() { Content = "Pause" };
dockPanel.Children.Add(pauseButton);
DockPanel.SetDock(pauseButton, Dock.Top);
var canvas = new Canvas();
dockPanel.Children.Add(canvas);
DockPanel.SetDock(canvas, Dock.Top);
SizeChanged += (s, e) => canvas.SetCoordinateSystem(-400, 400, -400, 400);
var element = new DrawingVisualElement();
Action draw = () =>
{
canvas.Children.Clear();
// var element = new DrawingVisualElement();
using (var dc = element.visual.RenderOpen())
{
for (var i = 0.0; i < 720.0; i += slider.Value)
{
var radius = Math.Sin(i / 720.0 * Math.PI) * 30;
var phi = (1 + Math.Sqrt(5)) / 2;
var omega = 2 * Math.PI * (phi - 1) * i;
var x = Math.Cos(omega) * 0.5 * i;
var y = Math.Sin(omega) * 0.5 * i;
dc.DrawEllipse(
new SolidColorBrush(ColorUtils.Rgb(i / 360.0, i / 360.0, 0.25)),
new Pen(Brushes.Black, Math.Max(radius / 6, 1)),
new Point(x, y),
radius / 2,
radius / 2);
}
}
canvas.Children.Add(element);
};
slider.ValueChanged += (s, e) =>
{
Title = slider.Value.ToString() + " " + incrementSlider.Value;
draw();
};
var timer = new DispatcherTimer();
timer.Tick += (s, e) =>
{
if (slider.Value < 10.0)
slider.Value += incrementSlider.Value;
};
timer.Start();
pauseButton.Click += (s, e) =>
{
if (timer.IsEnabled)
timer.Stop();
else
timer.Start();
};
slider.Value = 3.5;
incrementSlider.Value = 0.00001;
}
}
}
答案 0 :(得分:3)
如果你在WPF,CompositionTarget.Rendering事件中使用第三个动画选项,那么我发现没有减速。我已经使用slider.ValueChanged:
调整了样本中的代码 slider.Value = 3.5;
incrementSlider.Value = 0.00001;
EventHandler renderer = (s, e) =>
{
if (slider.Value < 10.0)
slider.Value += incrementSlider.Value;
//Title = slider.Value.ToString() + " " + incrementSlider.Value;
draw();
_frameCounter++;
};
CompositionTarget.Rendering += renderer;
pauseButton.Click += (sender, args) => CompositionTarget.Rendering -= renderer;
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += (s, e) =>
{
Title = string.Format("fps: {0}", _frameCounter);
_frameCounter = 0;
};
timer.Start();
CompositionTarget.Rendering以固定的60 fps速率发射,除非机器负载很重。您可以在互联网上找到代码来调整framedrops并避免可见的减速。
对于因示例中的鼠标活动导致的减速,我没有很好的解释。我的第一个想法是它是路由事件的基础上的瓶颈,但是通过从ValueChanged事件中提取draw方法来调整计时器间隔或重构似乎并没有解决问题。
BTW我喜欢你的样品。
答案 1 :(得分:0)
可能是热门测试。您可以尝试在画布上将IsHitTestVisible设置为false。