在WPF中向鼠标旋转图形(如模拟转盘)

在WPF / C#中,如何旋转“图形”以面向当前鼠标位置?

基本上我想要的是一个“轮”UI控件(如模拟音量表盘 )。 我希望能够单击并拖动表盘,它将旋转以跟随鼠标。 然后,当我释放鼠标时,它将停止跟随(显然!)。

我该如何创建其中一个? 一个人已经存在吗?

我没有看到这样的任何控件(尽管我看了WPF控件供应商提供的所有控件已经有一段时间了),但是创建一个控件相对简单。

您所要做的就是创建一个包含图像(或XAML绘图)的自定义控件,您可以旋转它以跟随鼠标。 然后,将RotateTransform绑定到自定义控件上的“角度”DependencyProperty,以便在更新“angle”时,图像/绘图旋转以匹配:

       

将RenderTransformOrigin设置为“0.5,0.5”可确保控件围绕其中心旋转,而不是围绕左上角旋转; 我们还必须在角度计算中对此进行补偿。

在控件的代码隐藏文件中,添加鼠标处理程序和Angle DependencyProperty:

 public partial class VolumeControl : UserControl { // Using a DependencyProperty backing store for Angle. public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(VolumeControl), new UIPropertyMetadata(0.0)); public double Angle { get { return (double)GetValue(AngleProperty); } set { SetValue(AngleProperty, value); } } public VolumeControl() { InitializeComponent(); this.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown); this.MouseUp += new MouseButtonEventHandler(OnMouseUp); this.MouseMove += new MouseEventHandler(OnMouseMove); } private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Mouse.Capture(this); } private void OnMouseUp(object sender, MouseButtonEventArgs e) { Mouse.Capture(null); } private void OnMouseMove(object sender, MouseEventArgs e) { if (Mouse.Captured == this) { // Get the current mouse position relative to the volume control Point currentLocation = Mouse.GetPosition(this); // We want to rotate around the center of the knob, not the top corner Point knobCenter = new Point(this.ActualHeight / 2, this.ActualWidth / 2); // Calculate an angle double radians = Math.Atan((currentLocation.Y - knobCenter.Y) / (currentLocation.X - knobCenter.X)); this.Angle = radians * 180 / Math.PI; // Apply a 180 degree shift when X is negative so that we can rotate // all of the way around if (currentLocation.X - knobCenter.X < 0) { this.Angle += 180; } } } } 

捕获鼠标确保您的控件将继续获得鼠标更新,即使用户鼠标离开控件(直到他们放开点击),并通过获取鼠标相对于当前元素(控件)的位置,无论控件在屏幕上实际呈现的位置如何,您的计算应始终相同。

在此示例中,当鼠标移动时,我们计算它与控件中心之间的角度,然后将此角度设置为我们创建的Angle DependencyProperty。 由于我们正在显示的图像与此角度属性绑定,因此WPF会自动应用新值,这会导致旋钮与鼠标移动一起旋转。

在解决方案中使用控件很容易; 只需添加:

  

如果要将旋钮的值绑定到应用程序中的某些内容,可以将其绑定到VolumeControl上的Angle属性; 该值目前以度为单位,但可以添加一个额外的属性,以在度数角度和对您有意义的值(例如,0到10之间的值)之间进行转换。

要添加到该post,鼠标点和对象点之间的角度计算如下:

 dot = currentLocation.X * objectPosition.X + currentLocation.Y * objectPosition.Y; angle = Math.Acos(dot); 

在我的情况下,我动态创建了将朝鼠标方向旋转的形状。 为了解决这个问题,我使用了轻量级function 我需要的是:

  • 当前所选形状的中心点
  • 从最后一个鼠标hover步骤开始的点
  • 从当前的鼠标hover步骤开始

没有必要使用Math库中的方法。 我计算的角度取决于当前鼠标在点与前一个鼠标在点之间的差异以及与中心点相关的位置。 最后,我在当前对象的exisitng角度上添加角度。

 private void HandleLeftMouseDown(MouseButtonEventArgs eventargs) { //Calculate the center point of selected object //... //assuming Point1 is the top left point var xCenter = (_selectedObject.Point2.X - _selectedObject.Point1.X) / 2 + _selectedObject.Point1.X var yCenter = (_selectedObject.Point2.Y - _selectedObject.Point1.Y) / 2 + _selectedObject.Point1.Y _selectedObjectCenterPoint = new Point((double) xCenter, (double) yCenter); //init set of last mouse over step with the mouse click point var clickPoint = eventargs.GetPosition(source); _lastMouseOverPoint = new Point(clickPoint.X,clickPoint.Y); } private void HandleMouseMove(MouseEventArgs eventArgs) { Point pointMouseOver = eventArgs.GetPosition(_source); //Get the difference to the last mouse over point var xd = pointMouseOver.X - _lastMouseOverPoint.X; var yd = pointMouseOver.Y - _lastMouseOverPoint.Y; // the direction depends on the current mouse over position in relation to the center point of the shape if (pointMouseOver.X < _selectedObjectCenterPoint.X) yd *= -1; if (pointMouseOver.Y > _selectedObjectCenterPoint.Y) xd *= -1; //add to the existing Angle //not necessary to calculate the degree measure _selectedObject.Angle += (xd + yd); //save mouse over point _lastMouseOverPoint = new Point(pointMouseOver.X, pointMouseOver.Y); }