Перемещение Line по canvas WPF
Как сделать плавное перемещение Line по canvas при помощи мыши, как не пробовал нормальное перемещение организовать не удалось.
private bool _isAttached = false;
private FrameworkElement _attachedElement;
private Point _clickPoint;
public MainWindow()
{
InitializeComponent();
canvas.MouseMove += MainCanvasOnMouseMove;
}
// создание линии
private void ButtonCreateLine_Click(object sender, RoutedEventArgs e)
{
Line line = new Line()
{
X1 = 200,
X2 = 300,
Y1 = 200,
Y2 = 300,
Stroke = System.Windows.Media.Brushes.Black,
StrokeThickness = defaultStrokeThickness
};
line.MouseLeftButtonUp += LineOnMouseLeftButtonUp;
line.MouseLeftButtonDown += LineOnMouseLeftButtonDown;
canvas.Children.Add(line);
}
// отпускаем левую мышь
private void LineOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
_isAttached = false;
}
// зажимаем левую мышь
private void LineOnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
_clickPoint = mouseButtonEventArgs.GetPosition(sender as FrameworkElement);
_attachedElement = sender as FrameworkElement;
_isAttached = true;
}
// движение мыши по канвасу
private void MainCanvasOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
if (_isAttached && _attachedElement != null && _clickPoint.X <= canvas.Width)
{
if(_attachedElement.GetType() == typeof(Line))
{
//тут много что пробовал, так и не получилось сделать грамотное перемещение
Line line = (Line)_attachedElement;
line.X1 += mouseEventArgs.GetPosition(canvas).X - _clickPoint.X;
line.X2 += mouseEventArgs.GetPosition(canvas).X - _clickPoint.X;
line.Y1 += mouseEventArgs.GetPosition(canvas).Y - _clickPoint.Y;
line.Y2 += mouseEventArgs.GetPosition(canvas).Y - _clickPoint.Y;
}
}
}
Ответы (1 шт):
Автор решения: Laukhin Andrey
→ Ссылка
Несколько замечаний:
- Дельту для перемещения объекта нужно считать не от координат первичного нажатия на линию
_clickPoint, а от предыдущего положения курсора (_lastPos). - Граничное условие
_clickPoint.X <= canvas.Widthлучше изменить на<= canvas.ActualWidth, т.к. выравнивание canvas может быть задано по разному. В данном случае, это условие не нужно, ведь событие происходит в рамках canvas. - Событие
ButtonUpправильно вешать на canvas, а не линию, т.к. в момент отпускания кнопки курсор может быть не на линии.
Пример:
public partial class MainWindow : Window
{
private bool _isAttached = false;
private FrameworkElement _attachedElement;
private Point _lastPos;
public MainWindow()
{
InitializeComponent();
canvas.MouseMove += MainCanvasOnMouseMove;
canvas.MouseLeftButtonUp += MainCanvasOnLeftButtonUp;
}
// создание линии
private void ButtonCreateLine_Click(object sender, RoutedEventArgs e)
{
Line line = new Line()
{
X1 = 200,
X2 = 300,
Y1 = 200,
Y2 = 300,
Stroke = System.Windows.Media.Brushes.Black,
StrokeThickness = 5
};
line.MouseLeftButtonDown += LineOnMouseLeftButtonDown;
canvas.Children.Add(line);
}
// отпускаем левую мышь
private void MainCanvasOnLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
_isAttached = false;
}
// зажимаем левую мышь
private void LineOnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
_lastPos = mouseButtonEventArgs.GetPosition(sender as FrameworkElement);
_attachedElement = sender as FrameworkElement;
_isAttached = true;
}
// движение мыши по канвасу
private void MainCanvasOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
Point currentPos = mouseEventArgs.GetPosition(sender as FrameworkElement);
if (_isAttached && _attachedElement != null)
{
if (_attachedElement.GetType() == typeof(Line))
{
Line line = (Line)_attachedElement;
line.X1 += currentPos.X - _lastPos.X;
line.X2 += currentPos.X - _lastPos.X;
line.Y1 += currentPos.Y - _lastPos.Y;
line.Y2 += currentPos.Y - _lastPos.Y;
_lastPos.X = currentPos.X;
_lastPos.Y = currentPos.Y;
}
}
}
}
P.S. Я обычно разделяю расчет дельты и перерисовку объекта, чтобы перерисовка была с заданной частотой.