-
Notifications
You must be signed in to change notification settings - Fork 118
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] Maryia/feat: vertical scroll behavior updates for isVerticalScrollEnabled functionality when disabled #1628
Changes from 7 commits
d8f5b67
a8bf8e3
867499f
fdc2b37
b5d0b77
3db2079
fe673eb
7c4f81f
f37f9ec
9c1cb54
f961e44
b71065d
10a2c7f
bdbb23f
075a104
28a1389
8a8315a
3eca94c
27cbc34
22b8cfb
bac2e9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,10 +41,14 @@ export default class ChartAdapterStore { | |
bottomIndex: 0, | ||
}; | ||
touchValues: { | ||
deltaYTotal?: number; | ||
x?: number; | ||
y?: number; | ||
yOnTouchEnd?: number; | ||
} = {}; | ||
} = { | ||
deltaYTotal: 0, | ||
x: 0, | ||
y: 0, | ||
}; | ||
|
||
isOverFlutterCharts = false; | ||
enableVerticalScrollTimer?: ReturnType<typeof setTimeout>; | ||
|
@@ -237,38 +241,58 @@ export default class ChartAdapterStore { | |
} | ||
|
||
onTouch(e: TouchEvent) { | ||
const chartNode = this.mainStore.chart.chartNode; | ||
// 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; | ||
if ( | ||
chartNode && | ||
this.scrollableChartParent && | ||
!this.mainStore.state.isVerticalScrollEnabled && | ||
e.touches.length === 1 | ||
e.changedTouches.length === 1 | ||
) { | ||
const { pageX, screenX, screenY } = e.touches[0]; | ||
if (['touchstart', 'touchend'].includes(e.type)) { | ||
this.touchValues = e.type === 'touchstart' ? { x: screenX, y: screenY } : { yOnTouchEnd: screenY }; | ||
} else if (e.type === 'touchmove') { | ||
const { pageX, pageY } = e.changedTouches[0]; | ||
|
||
if (['touchmove', 'touchend'].includes(e.type)) { | ||
const nonScrollableAreaWidth = chartNode.offsetWidth - this.mainStore.chart.yAxisWidth; | ||
const { left } = chartNode.getBoundingClientRect(); | ||
|
||
if (this.touchValues.x && this.touchValues.y) { | ||
const deltaX = Math.abs(screenX - this.touchValues.x); | ||
const deltaY = Math.abs(screenY - this.touchValues.y); | ||
const deltaX = Math.abs(pageX - this.touchValues.x); | ||
const deltaY = Math.abs(pageY - this.touchValues.y); | ||
this.touchValues.deltaYTotal = (this.touchValues.deltaYTotal ?? 0) + (this.touchValues.y - pageY); | ||
const isVerticalScroll = deltaY > deltaX; | ||
const x = pageX - left; | ||
if (x < nonScrollableAreaWidth && isVerticalScroll && !this.scrollChartParentOnTouchTimer) { | ||
this.touchValues.yOnTouchEnd = undefined; | ||
this.scrollChartParentOnTouchTimer = setTimeout(() => { | ||
this.scrollableChartParent?.scrollBy({ | ||
top: screenY - Number(this.touchValues.yOnTouchEnd ?? this.touchValues.y), | ||
const isForcedScrollArea = x < nonScrollableAreaWidth; | ||
const shouldForceMaxScroll = | ||
Math.abs(Number(this.touchValues.deltaYTotal)) > 10 && e.type === 'touchend'; | ||
if (isForcedScrollArea) { | ||
if (shouldForceMaxScroll) { | ||
clearTimeout(this.scrollChartParentOnTouchTimer); | ||
this.scrollableChartParent?.scrollTo({ | ||
top: | ||
Number(this.touchValues.deltaYTotal) < 0 | ||
? 0 | ||
: this.scrollableChartParent.scrollHeight, | ||
behavior: 'smooth', | ||
}); | ||
this.scrollChartParentOnTouchTimer = undefined; | ||
}, 300); | ||
this.touchValues = { ...this.touchValues, deltaYTotal: 0 }; | ||
} else if (isVerticalScroll && !this.scrollChartParentOnTouchTimer) { | ||
this.scrollChartParentOnTouchTimer = setTimeout(() => { | ||
this.scrollableChartParent?.scrollBy({ | ||
top: this.touchValues.deltaYTotal, | ||
behavior: 'smooth', | ||
}); | ||
this.scrollChartParentOnTouchTimer = undefined; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inside of timeout timer can be cleared only by undefined assignment or this will work too: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't want to clear the timer inside it because it has already been executed, it won't be needed. |
||
this.touchValues = { ...this.touchValues, deltaYTotal: 0 }; | ||
}, 100); | ||
} | ||
} | ||
} | ||
this.touchValues = { x: screenX, y: screenY }; | ||
this.touchValues = { ...this.touchValues, x: pageX, y: pageY }; | ||
} | ||
if (['touchstart', 'touchend'].includes(e.type)) { | ||
this.touchValues = | ||
e.type === 'touchstart' ? { x: pageX, y: pageY } : { deltaYTotal: this.touchValues.deltaYTotal }; | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes we get
touchcancel
instead oftouchend
, do we need to handle this case too?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, we don't need to do that. also, we won't get
touchcancel
here ever because we don't triggeronTouch
action for this event type.