Skip to content

Commit

Permalink
feat: add fast scroll touch event for mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
Keelaro1 committed Nov 16, 2023
1 parent 194bd61 commit bb2bb0d
Showing 1 changed file with 45 additions and 1 deletion.
46 changes: 45 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 fastScrollTouch = 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 minTime = 200;

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 isMinDistance = distance > minDistance;
const isMinTime = time <= minTime;

if (isMinDistance && isMinTime) {
this.fastScrollTouch.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,16 @@ 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 gesture is detected.
*/
public observeFastScrollTouch(): Observable<TouchEvent> {
return this.fastScrollTouch.asObservable();
}

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

0 comments on commit bb2bb0d

Please sign in to comment.