2

my project is a scrollable scheduler, similar to vis-timeline and using Vue.js.
One of my biggest problems is how to scroll infinitely and smoothly in every direction (past and future).

I'll readily admit that I'm not that experienced as a programmer yet, so I'd appreciate it if you'd check and evaluate my approach.

My solution currently looks like this:

JS:

let datelist = [yesterday, today, tomorrow]

HTML:

<div v-for="date of datelist">
    <div width="100%" height="100%">{{date}}</div>
</div>

Because 3 divs take up 300% of the screen, an overflow occurs (scroll bar visible). After rendering, I centre the middle one (today).

Example

While scrolling via drag&drop and 50% of the previous or following day is visible, an event is triggered that modifies the datelist:

Scrolling to the left:

*Generate previous day of yesterday and remove tomorrow *

datelist = [yesterday -1 day, yesterday, today]

Scrolling to the right:

*Generate following day of tomorrow and remove yesterday *

datelist = [today, tomorrow, tomorrow + 1]

However, this also has a few disadvantages:

Every time the list changes, it has to be completely re-rendered. If each day gets a lot of content later (appointments), this could cost performance.

You can actually only scroll linearly, as soon as I want to jump to a date, for example with a date picker, I have to recreate the whole list.

Maybe more ?

How would you solve the problem? I am more concerned with the way to solve the problem than with a solution.

Constraints:

  • No third-party libs
  • high performance
  • easy
kissu
  • 40,416
  • 14
  • 65
  • 133
Dennis Vogel
  • 23
  • 1
  • 3

1 Answers1

0

Using IntersectionObserver is your go-to here. Thanks to it, you will be able to set various behavior, fetch content and allow for interactivity regarding the other "date cells".
The useIntersectionObserver composable is a good candidate for such a purpose.


Only displaying what is currently visible can also be helpful, so that you don't have too much content in the DOM. This may help but can also be done yourself (check the source code there).


I'm not sure why your list needs to be re-rendered but maybe consider not nuking the whole thing and applying some modifications at the given locations.
Or use a memoization approach, depending on what you need to memorize it may be quite quick to implement yourself.
With the given approaches listed above, you may not even need to remove dates from your list, just hide (CSS) or let it off the screen. Aka rather than having let datelist = [yesterday, today, tomorrow], consider having let datelist = [..., x , y, today, z, a, b, ...] each time you reach a boundary.


TLDR: for your constraints, you can pick only 2 from the 3.

kissu
  • 40,416
  • 14
  • 65
  • 133
  • If I understood you correctly, you would also work with a data list to render objects that can be scrolled through ? If I continue with my approach, I always have to include a correction step when scrolling: - scroll to the right -> an object is appended, the first one is removed -> display jumps 100% to the right because scroll-x remains the same but the first object was removed. -> Correction by scroll-x - 100%... The approach with the IntersectionObserver is interesting, I'll have to have a look at that...Thanks for that ! – Dennis Vogel Dec 28 '22 at 16:07
  • I recommend that you don't remove objects but rather keep all of them (when added). Only addition and no removal. Also, having a 2D representation could help (array of arrays). That way, no correction is needed and no worry about offset/finding the proper index. The rest will be able to help you with the optimization part. – kissu Dec 28 '22 at 16:19
  • Thank you for your recommendations! I still feel a little uncomfortable not limiting the date list to a certain amount, but I'll give that a try. I have also experimented with SVG and coupled a date with a coordinate. The limiting factor here is that SVG coordinates are not allowed to be arbitrarily large (browser restriction to 32bit integers) and thus the scrolling range is restricted. – Dennis Vogel Dec 28 '22 at 18:14
  • @DennisVogel not limiting them to a specific amount is not an issue if you don't show them all at the same time. Check [this video](https://youtu.be/4roJKfgPLk4) for a quick explanation of how you achieve that. I don't see the need for an SVG coordinate, a multiplier and an offset are just what you need. Like `200px * 12` (for the 13th element) is enough. – kissu Dec 28 '22 at 20:23