almende / vis

⚠️ This project is not maintained anymore! Please go to https://github.com/visjs
7.85k stars 1.48k forks source link

Howto control the vertical space reserved on the timeline #1179

Open wjvriend opened 9 years ago

wjvriend commented 9 years ago

I'm investigating if we can use visjs Timeline to plot our calibration data.

One issue I encounter is that on the Timeline vertical spaced is reserved for items that are not in view. For a few items this is ok, but when vertical space is reserved for 100 items outside the view then the view shows mostly empty space.

Here is an example with ~350 items :

http://calts.test.astro-wise.org/test/test_visjs.html

(and scroll to the left)

Is it possible to not reserve vertical space for items outside the view ?

Pointers in vis.js where this is relevant are also welcome.

A bit of background on the data. The items are calibration objects, which a start and end date (for usage). They can have overlapping date ranges, in this case the latest created should be used. The later an object is created, the lower it is within the group. So the grey background above the items shows that any object above is eclipsed.

josdejong commented 9 years ago

The Timeline draws all items inside the range from the left of the timeline window minus 1/4th of the screen with to the right of the window plus 1/4th of the screen width. The related code is here:

https://github.com/almende/vis/blob/master/lib/timeline/component/Group.js#L461-L463

This quarter of the screen width extra margin is hard-coded, but you could override this method if needed.

daniel-pfeiffer commented 9 years ago

Good, but is this really useful for anything? If I scroll a little, that 1/4 will also scroll and include new events with the same likelihood, as if you considered only the visible part. So you need to relayout anyway.

I don't see how to override this, since Group ends up being private to anonymous function 32. But even if I could, cloning such a sizable function doesn't seem like a good practice.

If you want to keep this behaviour, how about an option? It would probably be clearer to turn it into a factor: 0 for none, 0.25 or 25% for the current behaviour.

josdejong commented 9 years ago

Good, but is this really useful for anything?

This is not relevant when you use range items, but it is for other types of items. The Timeline only knows the width of items after rendering them, but rendering all items in order to determine their width is kind of catastrophic for the performance. Therefore, the Timeline simply assumes that items will not be wider than 1/4 of the viewport and marks all items with a start and/or end date within the viewport plus 1/4 width as visible without the need to render them.

We can improve this simple rule of thumb quite easily, for example by taking into account the item type and the actual width for items which have been rendered already.

I would rather not like to create an option for this - there should be no need to tweak these sort of things, it should just work.

daniel-pfeiffer commented 9 years ago

Even so the ¼ heuristic isn't really reliable either. If I have (I don't but just tried while thinking about the problem) a centered item as wide as the timeline, it will suddenly disappear when a ¼ of it was visible one scroll pixel ago. The same bug the other way round.

I think for any centered items you would need an estimation of the width, and render the ones that might jut into view. You can cache the rendered width to avoid repeating it.

wjvriend commented 9 years ago

Thanks for the quick answers and discussion !

I was completely taken by a different project, sorry for the late response. I certainly will have a closer look at using visjs in the hopeful near future.

mpilone commented 9 years ago

I just ran into this issue today. I'd consider it more of a bug than an enhancement.

I use the timeline to display a TV like programming schedule using range items. The user has the option to view a 24, 12, 6, or 4 hour range of the schedule. I have a couple of 24 hour programs on the schedule (think emergency broadcast or an advertising loop) that always start and end at midnight. If the user selects a 6 hour view and moves away from midnight the 24 hour long range items disappear from the timeline until the user gets closer to midnight. So in the middle of the day the group looks empty (no item) but near midnight the group looks completely full (the 24 hour item reappears).

This seems like a major limitation with range items given that the user could zoom to the point that items completely overlapping the visible range could disappear.

josdejong commented 9 years ago

@mpilone not sure but this sounds like a different issue, if I understand you correctly range items that are visible are not rendered? This issue is about the Timeline still "reserving" space for items which are already outside the viewport.

mpilone commented 9 years ago

@josdejong Ah, my mistake. I misunderstood the 1/4 heuristic to apply to the start/end time of the range item being in the range. I'll double check my code and open a new issue if I can reproduce the problem. Ignore my previous comment. Thanks for the quick reply.

daniel-pfeiffer commented 8 years ago

Hi @josdejong, as you said on Aug 14 2015: it is for other types of items. So I figured we can reduce the problem by only applying the ¼ heuristic to items withouth end:

  BoxItem.prototype.isVisible = function (range) {
    // determine visibility
    if (this.data.hasOwnProperty('end')) {
      return this.data.start < range.end && this.data.end > range.start;
    } else {
      // TODO: account for the real width of the item. Right now we just add 1/4 to the window
      var interval = (range.end - range.start) / 4;
      return this.data.start > range.start - interval && this.data.start < range.end + interval;
    }
  };
  PointItem.prototype.isVisible = same as above
yotamberk commented 7 years ago

@wjvriend In v4.17.0 the items are calculated correctly for there visibility in the viewport.

mojoaxel commented 7 years ago

@yotamberk It may be interesting to adopt the proposal from @daniel-pfeiffer We should try it out for v5.0.

yotamberk commented 7 years ago

@mojoaxel Ummm well, it seems like an additional option (like the margin.axis/margin.items). Can be done indeed. (For vertical too!)