Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DTRA-V2]Ahmad/Chart Scroll Behavior #1635

Merged
merged 18 commits into from
Nov 4, 2024
77 changes: 50 additions & 27 deletions src/store/ChartAdapterStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ export default class ChartAdapterStore {
onTouch(e: TouchEvent) {
// Prevent vertical scroll on the chart for touch devices by forcing scroll on a scrollable parent of the chart:
const chartNode = this.mainStore.chart.chartNode;
const flutterChart = document.getElementsByClassName('flutter-chart')[0] as HTMLElement;
ahmadtaimoor-deriv marked this conversation as resolved.
Show resolved Hide resolved

if (chartNode && this.scrollableChartParent && !this.mainStore.state.isVerticalScrollEnabled) {
if (this.touchValues.multiTouch) {
if (e.type === 'touchend') {
Expand All @@ -275,6 +277,7 @@ export default class ChartAdapterStore {
if (['touchmove', 'touchend'].includes(e.type)) {
const forcedScrollAreaWidth = chartNode.offsetWidth - this.mainStore.chart.yAxisWidth;
const forcedScrollAreaHeight = chartNode.offsetHeight - this.mainStore.chart.xAxisHeight;

const { top, left } = chartNode.getBoundingClientRect();
const xCoord = pageX - left;
const yCoord = pageY - top;
Expand All @@ -291,31 +294,9 @@ export default class ChartAdapterStore {
this.touchValues = { ...this.touchValues, deltaXTotal, deltaYTotal };

if (isForcedScrollArea && isVerticalScroll) {
const shouldForceMaxScroll =
Math.abs(Number(this.touchValues.deltaYTotal)) > 10 && e.type === 'touchend';
if (!this.isXScrollBlocked) this.toggleXScrollBlock();
if (shouldForceMaxScroll) {
// handling max scroll on quick swipe
this.scrollableChartParent?.scrollTo({
top:
Number(this.touchValues.deltaYTotal) < 0
? 0
: this.scrollableChartParent.scrollHeight,
behavior: 'smooth',
});
} else if (e.type === 'touchmove') {
// handling slow scroll
this.scrollableChartParent?.scrollBy({
top: yDiff,
});
if (!this.clearTouchDeltasTimer) {
this.clearTouchDeltasTimer = setTimeout(() => {
// clearing total deltas to avoid triggering max scroll after the slow scroll
this.touchValues = { ...this.touchValues, deltaYTotal: 0, deltaXTotal: 0 };
this.clearTouchDeltasTimer = undefined;
}, 100);
}
}
} else if (!this.isXScrollBlocked) {
this.stopScroll(flutterChart);
}
}
this.touchValues = { ...this.touchValues, x: pageX, y: pageY };
Expand All @@ -336,6 +317,7 @@ export default class ChartAdapterStore {

onWheel = (e: WheelEvent) => {
e.preventDefault();
e.stopPropagation();

// Prevent vertical scroll on the chart on wheel devices by disabling pointer events to make chart parent scrollable:
const chartNode = this.mainStore.chart.chartNode;
Expand Down Expand Up @@ -537,7 +519,48 @@ export default class ChartAdapterStore {

toggleXScrollBlock = (isBlocked = true) => {
this.isXScrollBlocked = isBlocked;
window.flutterChart?.app.toggleXScrollBlock(isBlocked);
const flutterChart = document.getElementsByClassName('flutter-chart')[0] as HTMLElement;

if (flutterChart) {
if (isBlocked) {
flutterChart.style.overflowY = 'scroll';
flutterChart.style.overflowX = 'hidden';
flutterChart.style.overscrollBehavior = 'contain';
flutterChart.style.touchAction = 'pan-y';
} else {
this.allowScroll(flutterChart);
}
}
};

allowScroll = (element: HTMLElement) => {
let lastScrollTop = element.scrollTop;
let isScrolling = false;
let scrollTimeout: ReturnType<typeof setTimeout>;

const monitorScroll = () => {
ahmadtaimoor-deriv marked this conversation as resolved.
Show resolved Hide resolved
if (element.scrollTop !== lastScrollTop) {
isScrolling = true;
lastScrollTop = element.scrollTop;

clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
this.stopScroll(element);
}, 200);
} else {
isScrolling = false;
}

if (isScrolling) {
requestAnimationFrame(monitorScroll);
}
};
};

stopScroll = (element: HTMLElement) => {
element.style.removeProperty('overflow-y');
element.style.removeProperty('overflow-x');
element.style.removeProperty('touch-action');
};

toggleDataFitMode = () => {
Expand Down Expand Up @@ -588,15 +611,15 @@ export default class ChartAdapterStore {
delta_x = this.getXFromEpoch((barNext.DT as Date).getTime()) - x;

ratio =
((date as unknown as number) - (bar.DT as Date).getTime()) /
(((date as unknown) as number) - (bar.DT as Date).getTime()) /
((barNext.DT as Date).getTime() - (bar.DT as Date).getTime());

if (price) delta_y = barNext.Close - price;
} else if (barPrev && barPrev.Close) {
delta_x = x - this.getXFromEpoch((barPrev.DT as Date).getTime());

ratio =
((date as unknown as number) - (bar.DT as Date).getTime()) /
(((date as unknown) as number) - (bar.DT as Date).getTime()) /
((bar.DT as Date).getTime() - (barPrev.DT as Date).getTime());

if (price) delta_y = price - barPrev.Close;
Expand Down
Loading