You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/Components/SwipeArea/SwipeArea.razor.cs

133 lines
3.6 KiB

using Connected.Annotations;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components;
public partial class SwipeArea : UIComponent
{
internal double? _xDown, _yDown;
private double? _swipeDelta;
internal ElementReference _componentRef;
private static readonly string[] _preventDefaultEventNames = { "touchstart", "touchend", "touchcancel" };
internal int[] _listenerIds;
[Parameter]
[Category(CategoryTypes.SwipeArea.Behavior)]
public RenderFragment ChildContent { get; set; }
[Parameter]
[Category(CategoryTypes.SwipeArea.Behavior)]
public Action<SwipeDirection> OnSwipe { get; set; }
/// <summary>
/// Swipe threshold in pixels. If SwipeDelta is below Sensitivity then OnSwipe is not called.
/// </summary>
[Parameter]
[Category(CategoryTypes.SwipeArea.Behavior)]
public int Sensitivity { get; set; } = 100;
/// <summary>
/// Prevents default behavior of the browser when swiping.
/// Usable espacially when swiping up/down - this will prevent the whole page from scrolling up/down.
/// </summary>
[Parameter]
[Category(CategoryTypes.SwipeArea.Behavior)]
public bool PreventDefault { get; set; }
private bool _preventDefaultChanged;
public override async Task SetParametersAsync(ParameterView parameters)
{
var preventDefault = parameters.GetValueOrDefault<bool>(nameof(PreventDefault));
if (preventDefault != PreventDefault)
{
_preventDefaultChanged = true;
}
await base.SetParametersAsync(parameters);
}
private async Task SetPreventDefaultInternal(bool value)
{
if (value)
{
_listenerIds = await _componentRef.AddDefaultPreventingHandlers(_preventDefaultEventNames);
}
else
{
if (_listenerIds != null)
{
await _componentRef.RemoveDefaultPreventingHandlers(_preventDefaultEventNames, _listenerIds);
_listenerIds = null;
}
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (_preventDefaultChanged)
{
_preventDefaultChanged = false;
await SetPreventDefaultInternal(PreventDefault);
}
}
private void OnTouchStart(TouchEventArgs arg)
{
_xDown = arg.Touches[0].ClientX;
_yDown = arg.Touches[0].ClientY;
}
internal void OnTouchEnd(TouchEventArgs arg)
{
if (_xDown == null || _yDown == null)
return;
var xDiff = _xDown.Value - arg.ChangedTouches[0].ClientX;
var yDiff = _yDown.Value - arg.ChangedTouches[0].ClientY;
if (Math.Abs(xDiff) < Sensitivity && Math.Abs(yDiff) < Sensitivity)
{
_xDown = _yDown = null;
return;
}
if (Math.Abs(xDiff) > Math.Abs(yDiff))
{
if (xDiff > 0)
{
InvokeAsync(() => OnSwipe(SwipeDirection.RightToLeft));
}
else
{
InvokeAsync(() => OnSwipe(SwipeDirection.LeftToRight));
}
_swipeDelta = xDiff;
}
else
{
if (yDiff > 0)
{
InvokeAsync(() => OnSwipe(SwipeDirection.BottomToTop));
}
else
{
InvokeAsync(() => OnSwipe(SwipeDirection.TopToBottom));
}
_swipeDelta = yDiff;
}
_xDown = _yDown = null;
}
/// <summary>
/// The last successful swipe difference in pixels since the last OnSwipe invocation
/// </summary>
public double? GetSwipeDelta() => _swipeDelta;
internal void OnTouchCancel(TouchEventArgs arg)
{
_xDown = _yDown = null;
}
}