feat: add thumb cache to avoid drag conflict.

This commit is contained in:
rabbitism
2024-01-18 23:43:44 +08:00
parent 696058fe46
commit 9057803cb4

View File

@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
@@ -100,11 +101,13 @@ public class RangeSlider: TemplatedControl
} }
private Thumb? _currentThumb;
private void PointerPress(object sender, PointerPressedEventArgs e) private void PointerPress(object sender, PointerPressedEventArgs e)
{ {
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{ {
var point = e.GetCurrentPoint(_track); var point = e.GetCurrentPoint(_track);
_currentThumb = GetThumbByPoint(point);
MoveToPoint(point); MoveToPoint(point);
_isDragging = true; _isDragging = true;
} }
@@ -126,29 +129,71 @@ public class RangeSlider: TemplatedControl
private void PointerRelease(object sender, PointerReleasedEventArgs e) private void PointerRelease(object sender, PointerReleasedEventArgs e)
{ {
_isDragging = false; _isDragging = false;
_currentThumb = null;
} }
private void MoveToPoint(PointerPoint posOnTrack) private void MoveToPoint(PointerPoint posOnTrack)
{ {
if (_track is null) return; if (_track is null) return;
var isHorizontal = Orientation == Orientation.Horizontal; var value = GetValueByPoint(posOnTrack);
var thumbLength = _track.GetThumbLength(); var thumb = GetThumbByPoint(posOnTrack);
var trackLength = _track.GetTrackLength() - thumbLength; if (_currentThumb !=null && _currentThumb != thumb) return;
var pos = isHorizontal ? posOnTrack.Position.X : posOnTrack.Position.Y; if (thumb is null) return;
var lowerPosition = isHorizontal? _track.LowerThumb.Bounds.X : _track.LowerThumb.Bounds.Y; if (thumb == _track.LowerThumb)
var upperPosition = isHorizontal? _track.UpperThumb.Bounds.X : _track.UpperThumb.Bounds.Y; {
bool lower = Math.Abs(pos - lowerPosition) < Math.Abs(pos - upperPosition); SetCurrentValue(LowerValueProperty, value);
var logicalPosition = MathUtilities.Clamp((pos - thumbLength*0.5) / trackLength, 0.0, 1.0); }
var invert = isHorizontal ? IsDirectionReversed ? 1.0 : 0 : else
IsDirectionReversed ? 0 : 1.0; {
var calValue = Math.Abs(invert - logicalPosition); SetCurrentValue(UpperValueProperty, value);
var range = Maximum - Minimum; }
var finalValue = calValue * range + Minimum;
SetCurrentValue(lower? LowerValueProperty: UpperValueProperty, finalValue);
} }
private double SnapToTick(double value) private double SnapToTick(double value)
{ {
return value; return value;
} }
private Thumb? GetThumbByPoint(PointerPoint point)
{
var isHorizontal = Orientation == Orientation.Horizontal;
var lowerThumbPosition = isHorizontal? _track?.LowerThumb?.Bounds.Position.X : _track?.LowerThumb?.Bounds.Position.Y;
var upperThumbPosition = isHorizontal? _track?.UpperThumb?.Bounds.Position.X : _track?.UpperThumb?.Bounds.Position.Y;
var thumbWidth = isHorizontal? _track?.LowerThumb?.Bounds.Width : _track?.LowerThumb?.Bounds.Height;
var pointerPosition = isHorizontal? point.Position.X : point.Position.Y;
var lowerDistance = Math.Abs((lowerThumbPosition ?? 0) - pointerPosition);
var upperDistance = Math.Abs((upperThumbPosition ?? 0) - pointerPosition);
if (lowerDistance<upperDistance)
{
return _track?.LowerThumb;
}
else
{
return _track?.UpperThumb;
}
}
private double GetValueByPoint(PointerPoint point)
{
if (_track is null) return 0;
var isHorizontal = Orientation == Orientation.Horizontal;
var trackLength = _track.GetTrackLength();
var pointPosition = isHorizontal ? point.Position.X : point.Position.Y;
var thumbLength = _track.GetThumbLength() * 0.5;
if(pointPosition < thumbLength)
return isHorizontal? Minimum : Maximum;
if (pointPosition > trackLength - thumbLength)
return isHorizontal? Maximum : Minimum;
trackLength -= thumbLength * 2;
pointPosition = MathUtilities.Clamp(pointPosition / trackLength, 0.0, 1.0);
var invert = isHorizontal
? IsDirectionReversed ? 1.0 : 0
: IsDirectionReversed ? 0 : 1.0;
var calValue = Math.Abs(invert - pointPosition);
var range = Maximum - Minimum;
var finalValue = calValue * range + Minimum;
return finalValue;
}
} }