Simplify scroller timers

pull/162/head
Varun Patil 2022-10-29 17:11:12 -07:00
parent 80835421a5
commit af5e3ef105
1 changed files with 44 additions and 37 deletions

View File

@ -3,9 +3,10 @@
class="scroller" class="scroller"
ref="scroller" ref="scroller"
v-bind:class="{ v-bind:class="{
'scrolling-recycler': scrollingRecyclerTimer,
'scrolling-recycler-now': scrollingRecyclerNowTimer, 'scrolling-recycler-now': scrollingRecyclerNowTimer,
scrolling: scrolling, 'scrolling-recycler': scrollingRecyclerTimer,
'scrolling-now': scrollingNowTimer,
scrolling: scrollingTimer,
}" }"
@mousemove="mousemove" @mousemove="mousemove"
@touchmove="touchmove" @touchmove="touchmove"
@ -41,7 +42,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Mixins, Prop } from "vue-property-decorator"; import { Component, Mixins, Prop, Watch } from "vue-property-decorator";
import { IRow, IRowType, ITick } from "../types"; import { IRow, IRowType, ITick } from "../types";
import GlobalMixin from "../mixins/GlobalMixin"; import GlobalMixin from "../mixins/GlobalMixin";
import ScrollIcon from "vue-material-design-icons/UnfoldMoreHorizontal.vue"; import ScrollIcon from "vue-material-design-icons/UnfoldMoreHorizontal.vue";
@ -67,6 +68,8 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
private lastAdjustHeight = 0; private lastAdjustHeight = 0;
/** Height of the entire photo view */ /** Height of the entire photo view */
private recyclerHeight: number = 100; private recyclerHeight: number = 100;
/** Rect of scroller */
private scrollerRect: DOMRect = null;
/** Computed ticks */ /** Computed ticks */
private ticks: ITick[] = []; private ticks: ITick[] = [];
/** Computed cursor top */ /** Computed cursor top */
@ -75,13 +78,13 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
private hoverCursorY = -5; private hoverCursorY = -5;
/** Hover cursor text */ /** Hover cursor text */
private hoverCursorText = ""; private hoverCursorText = "";
/** Scrolling currently */ /** Scrolling using the scroller */
private scrolling = false; private scrollingTimer = 0;
/** Scrolling timer */ /** Scrolling now using the scroller */
private scrollingTimer = null as number | null; private scrollingNowTimer = 0;
/** Scrolling recycler timer */ /** Scrolling recycler */
private scrollingRecyclerTimer = 0; private scrollingRecyclerTimer = 0;
/** Scrolling recycler timer */ /** Scrolling recycler now */
private scrollingRecyclerNowTimer = 0; private scrollingRecyclerNowTimer = 0;
/** Recycler scrolling throttle */ /** Recycler scrolling throttle */
private scrollingRecyclerUpdateTimer = 0; private scrollingRecyclerUpdateTimer = 0;
@ -111,18 +114,33 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
this.cursorY = 0; this.cursorY = 0;
this.hoverCursorY = -5; this.hoverCursorY = -5;
this.hoverCursorText = ""; this.hoverCursorText = "";
this.scrolling = false;
this.scrollingTimer = null;
this.reflowRequest = false; this.reflowRequest = false;
// Clear all timers
clearTimeout(this.scrollingTimer);
clearTimeout(this.scrollingNowTimer);
clearTimeout(this.scrollingRecyclerTimer);
clearTimeout(this.scrollingRecyclerNowTimer);
clearTimeout(this.scrollingRecyclerUpdateTimer);
this.scrollingTimer = 0;
this.scrollingNowTimer = 0;
this.scrollingRecyclerTimer = 0;
this.scrollingRecyclerNowTimer = 0;
this.scrollingRecyclerUpdateTimer = 0;
} }
/** Recycler scroll event, must be called by timeline */ /** Recycler scroll event, must be called by timeline */
public recyclerScrolled() { public recyclerScrolled() {
// This isn't a renewing timer, it's a scheduled task
if (this.scrollingRecyclerUpdateTimer) return; if (this.scrollingRecyclerUpdateTimer) return;
this.scrollingRecyclerUpdateTimer = window.setTimeout(() => { this.scrollingRecyclerUpdateTimer = window.setTimeout(() => {
this.scrollingRecyclerUpdateTimer = 0; this.scrollingRecyclerUpdateTimer = 0;
requestAnimationFrame(this.updateFromRecyclerScroll); requestAnimationFrame(this.updateFromRecyclerScroll);
}, 100); }, 100);
// Update that we're scrolling with the recycler
utils.setRenewingTimeout(this, "scrollingRecyclerNowTimer", null, 200);
utils.setRenewingTimeout(this, "scrollingRecyclerTimer", null, 1500);
} }
/** Update cursor position from recycler scroll position */ /** Update cursor position from recycler scroll position */
@ -148,20 +166,6 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
} else { } else {
this.moveHoverCursor(rtop); this.moveHoverCursor(rtop);
} }
// Animate the cursor
if (this.scrollingRecyclerNowTimer)
window.clearTimeout(this.scrollingRecyclerNowTimer);
this.scrollingRecyclerNowTimer = window.setTimeout(() => {
this.scrollingRecyclerNowTimer = 0;
}, 200);
// Show the scroller for some time
if (this.scrollingRecyclerTimer)
window.clearTimeout(this.scrollingRecyclerTimer);
this.scrollingRecyclerTimer = window.setTimeout(() => {
this.scrollingRecyclerTimer = 0;
}, 1500);
} }
/** Re-create tick data in the next frame */ /** Re-create tick data in the next frame */
@ -307,6 +311,11 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
/** Mark ticks as visible or invisible */ /** Mark ticks as visible or invisible */
private computeVisibleTicks() { private computeVisibleTicks() {
// Kind of unrelated here, but refresh rect
this.scrollerRect = (
this.$refs.scroller as HTMLElement
).getBoundingClientRect();
// Do another pass to figure out which points are visible // Do another pass to figure out which points are visible
// This is not as bad as it looks, it's actually 12*O(n) // This is not as bad as it looks, it's actually 12*O(n)
// because there are only 12 months in a year // because there are only 12 months in a year
@ -444,6 +453,10 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
/** Move to given scroller Y */ /** Move to given scroller Y */
private moveto(y: number) { private moveto(y: number) {
// Move cursor immediately to prevent jank
this.cursorY = y;
this.hoverCursorY = y;
const { top1, top2, y1, y2 } = this.getCoords(y, "topF"); const { top1, top2, y1, y2 } = this.getCoords(y, "topF");
const yfrac = (y - top1) / (top2 - top1); const yfrac = (y - top1) / (top2 - top1);
const ry = y1 + (y2 - y1) * yfrac; const ry = y1 + (y2 - y1) * yfrac;
@ -459,21 +472,15 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
/** Handle touch */ /** Handle touch */
private touchmove(event: any) { private touchmove(event: any) {
const rect = (this.$refs.scroller as HTMLElement).getBoundingClientRect(); const y = event.targetTouches[0].pageY - this.scrollerRect.top;
const y = event.targetTouches[0].pageY - rect.top;
event.preventDefault();
event.stopPropagation(); event.stopPropagation();
this.moveto(y); this.moveto(y);
} }
/** Update this is being used to scroll recycler */ /** Update scroller is being used to scroll recycler */
private handleScroll() { private handleScroll() {
if (this.scrollingTimer) window.clearTimeout(this.scrollingTimer); utils.setRenewingTimeout(this, "scrollingNowTimer", null, 200);
this.scrolling = true; utils.setRenewingTimeout(this, "scrollingTimer", null, 1500);
this.scrollingTimer = window.setTimeout(() => {
this.scrolling = false;
this.scrollingTimer = null;
}, 1500);
} }
} }
</script> </script>
@ -596,11 +603,11 @@ export default class ScrollerManager extends Mixins(GlobalMixin) {
} }
} }
} }
&.scrolling-recycler-now > .cursor { &.scrolling-recycler-now:not(.scrolling-now) > .cursor {
transition: transform 0.1s linear; transition: transform 0.1s linear;
} }
&:hover > .cursor { &:hover > .cursor {
transition: none; transition: none !important;
&.st { &.st {
opacity: 1; opacity: 1;
} }