Название: Исправление тряски и прыжков в пользовательской LoopPanel с помощью инерционной прокрутки и привязки к элементC#

Место общения программистов C#
Ответить
Anonymous
 Название: Исправление тряски и прыжков в пользовательской LoopPanel с помощью инерционной прокрутки и привязки к элемент

Сообщение Anonymous »

I have a custom LoopPanel in WinUI, and I’m trying to implement inertia smooth scrolling and a snap-to-item feature.
I implemented both features, but I’m seeing some weird behavior: the panel shakes and jumps when scrolling finishes. This is not the smooth experience I want.
I’ve uploaded a sample app that contains the full source code for the panel.
https://github.com/ghost1372/App10
How can I fix the shaking and jumping behavior while keeping inertia scrolling and snapping to items functional?
Изображение

Here’s a snippet of what I currently have:

Код: Выделить всё

public class LoopPanel : Panel
{
private const Double DECELERATION          = 0.95;
private const Double MIN_INERTIA_THRESHOLD = 0.05;

private Double   inertiaVelocity = 0;
private Boolean  isInertiaActive = false;
private Double   dragVelocity    = 0;
private DateTime lastDragTime;
private Boolean  isDragging      = false;
private Point    lastDragPos;

public LoopPanel()
{
this.PointerWheelChanged += this.OnPointerWheelChanged;
this.PointerPressed      += this.OnPointerPressed;
this.PointerMoved        += this.OnPointerMoved;
this.PointerReleased     += this.OnPointerReleased;
this.PointerCanceled     += this.OnPointerCanceled;
}

#region Pointer Events

private void OnPointerWheelChanged( Object sender, PointerRoutedEventArgs e )
{
var delta = e.GetCurrentPoint(this).Properties.MouseWheelDelta;
Double scrollAmount = -delta * MouseWheelScrollFactor;

this.Scroll( scrollAmount );
this.InvalidateArrange();

if( IsInertiaEnabled )
{
this.inertiaVelocity = scrollAmount;
this.StartInertia();
}

e.Handled = true;
}

private void OnPointerPressed( Object sender, PointerRoutedEventArgs e )
{
this.isDragging   = true;
this.lastDragTime = DateTime.Now;

this.lastDragPos = e.GetCurrentPoint( this ).Position;
this.CapturePointer( e.Pointer );
e.Handled = true;
}

private void OnPointerMoved( Object sender, PointerRoutedEventArgs e )
{
if( !this.isDragging ) return;

Point current = e.GetCurrentPoint( this ).Position;
Double delta = ( this.Orientation == this.Orientation.Horizontal ) ? ( this.lastDragPos.X - current.X ) : ( this.lastDragPos.Y - current.Y );

this.Scroll( delta * this.DragScrollFactor );
this.InvalidateArrange();

DateTime now = DateTime.Now;
Double milliseconds = ( now - this.lastDragTime ).TotalMilliseconds;
if( milliseconds > 0 )
{
Double v = delta / milliseconds * 16.6667;
this.dragVelocity = this.dragVelocity * 0.35 + v * 0.65;
}

this.lastDragPos = current;
this.lastDragTime = now;
e.Handled = true;
}

private void OnPointerReleased( Object sender, PointerRoutedEventArgs e )
{
if( !this.isDragging ) return;

this.isDragging = false;
this.ReleasePointerCapture( e.Pointer );
e.Handled = true;

if( IsInertiaEnabled && Math.Abs( this.dragVelocity ) > MIN_INERTIA_THRESHOLD )
{
this.inertiaVelocity = this.dragVelocity;
this.StartInertia();
}
}

private void OnPointerCanceled( Object sender, PointerRoutedEventArgs e )
{
if( !this.isDragging ) return;

this.isDragging = false;
this.ReleasePointerCapture( e.Pointer );
e.Handled = true;
}

#endregio

private void StartInertia()
{
if( this.isInertiaActive ) return;

this.isInertiaActive = true;
this.CompositionTarget.Rendering += this.OnInertiaRendering;
}

private void StopInertia()
{
if( !this.isInertiaActive ) return;

this.isInertiaActive = false;
this.CompositionTarget.Rendering -= this.OnInertiaRendering;
}

private void OnInertiaRendering( Object sender, Object e )
{
if( Math.Abs( this.inertiaVelocity ) <  MIN_INERTIA_THRESHOLD )
{
this.inertiaVelocity = 0;

this.DispatcherQueue.TryEnqueue( () =>
{
this.SnapToNearestChild();
} );

this.StopInertia();
return;
}

this.Scroll( this.inertiaVelocity );
this.InvalidateArrange();

this.inertiaVelocity *= DECELERATION;
}

private void SnapToNearestChild()
{
if( Children.Count == 0 ) return;

Int32 nearest = (Int32)Math.Round(Offset);
this.Offset = nearest;
this.InvalidateArrange();
}
}
Мы будем очень признательны за любые рекомендации или советы о том, как правильно реализовать плавную инерцию и привязку в пользовательской LoopPanel.


Подробнее здесь: https://stackoverflow.com/questions/798 ... olling-and
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»