Skip to content

Commit

Permalink
Merge pull request #76 from devexperts/add-fast-scroll-touch-event
Browse files Browse the repository at this point in the history
feat: add fast scroll touch event for mobile
  • Loading branch information
Keelaro1 authored Nov 29, 2023
2 parents 09e89b2 + a2eff8a commit 328dbba
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion src/chart/inputlisteners/canvas-input-listener.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class CanvasInputListenerComponent extends ChartBaseElement {
private wheelSubject = new Subject<WheelEvent>();

private touchStartSubject = new Subject<TouchEvent>();
private touchStartTimestamp = 0;
private touchMoveSubject = new Subject<TouchEvent>();
private touchEndSubject = new Subject<TouchEvent>();
private touchCancelSubject = new Subject<TouchEvent>();
Expand All @@ -63,6 +64,7 @@ export class CanvasInputListenerComponent extends ChartBaseElement {

private pinchSubject = new Subject<WheelEvent>();
private scrollGestureSubject = new Subject<WheelEvent>();
private fastTouchScroll = new Subject<TouchEvent>();

mouseLeavesCanvasSubject = new Subject<boolean>();

Expand Down Expand Up @@ -290,6 +292,31 @@ export class CanvasInputListenerComponent extends ChartBaseElement {
this.addSubscription(
subscribeListener(this.element, (e: TouchEvent) => longTouchListeners(e), 'touchstart'),
);

const fastScrollListenerProducer = (e: TouchEvent) => {
e.preventDefault();
// should work only if dragged to the left
if (this.prevDragPoint.x > this.dragStartPoint.x) {
// in percent, perhaps should be changed to just pixels,
// because landscape and portait orientations would give different % results
const minDistance = 35;
// in ms, should be lower to detect as "fast"
const maxTime = 250;

const touchStartTs = this.touchStartTimestamp;
const touchEndTs = Date.now();
const time = touchEndTs - touchStartTs;

const distance = ((this.prevDragPoint.x - this.dragStartPoint.x) / this.canvasBounds.width) * 100;
const isRightDistance = distance > minDistance;
const isRightTime = time <= maxTime;

if (isRightDistance && isRightTime) {
this.fastTouchScroll.next(e);
}
}
};
this.addSubscription(subscribeListener(this.element, fastScrollListenerProducer, 'touchend'));
}

this.addSubscription(
Expand All @@ -301,7 +328,14 @@ export class CanvasInputListenerComponent extends ChartBaseElement {
);

this.addSubscription(
subscribeListener(this.element, (e: TouchEvent) => this.touchStartSubject.next(e), 'touchstart'),
subscribeListener(
this.element,
(e: TouchEvent) => {
this.touchStartSubject.next(e);
this.touchStartTimestamp = Date.now();
},
'touchstart',
),
);
this.addSubscription(
subscribeListener(this.element, (e: TouchEvent) => this.touchMoveSubject.next(e), 'touchmove', true),
Expand Down Expand Up @@ -793,6 +827,18 @@ export class CanvasInputListenerComponent extends ChartBaseElement {
.pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)));
}

/**
* Returns an Observable that emits a Touch whenever a fast scroll is detected.
* Fast scroll happens whenever chart or any other pane were moved faster than usual
* The Observable is created from a Subject that is subscribed to by the component's template.
* @returns {Observable<TouchEvent>} An Observable that emits a TouchEvent whenever a fast scroll is detected.
*/
public observeFastTouchScroll(hitBoundsTest: HitBoundsTest = () => true): Observable<TouchEvent> {
return this.fastTouchScroll
.asObservable()
.pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)));
}

/**
* Returns the current point of the object.
* @returns {Point} The current point of the object.
Expand Down

0 comments on commit 328dbba

Please sign in to comment.