almende / chap-links-library

a web based visualization library for displaying graphs, networks, and timelines
http://almende.github.com/chap-links-library
Apache License 2.0
599 stars 167 forks source link

Adaptive rendering of item labels: level of details vs zoom level #89

Open vlsi opened 11 years ago

vlsi commented 11 years ago

Current implementation forces developers to provide item.content at the very early stage. This results in:

  1. Exessive resource usage: lots of html is prepared, but it is invisible or unused due to the items of interest are out of view
  2. Bad user experience. At best, items should have different level of details at different zoom levels

Do you think it is ok to support item.content=function? Something like function(item, timeline)

josdejong commented 11 years ago

Great idea, though I think your remark on "excessive resource usage" is a little exaggerated. What we typically do is create a data controller, attach the controller via an event listener to the rangechange or rangechanged handler of the Timeline, and only retrieve data from the server which is currently displayed in the Timeline (and not yet cached). Using this lazy loading solution you only have to (a) retrieve data from the server when actually needed and (b) only need to prepare your item.content when actually needed.

Your idea on being able to provide different levels of detail for different zoom levels is nice. We are working on clustering (see #11), where items are automatically aggregated in groups when zooming out. In addition to automatic clustering we need to provide the developer a way to determine its own clustering algorithm for different zoom levels. It is an interesting idea to enable adaptive rendering on a per-item basis as well.

vlsi commented 11 years ago

What I really want is to use Timeline as a UI for the profiler application. The thing is I expect to have ~10K..100K items at client side. profiler_screenshot

Timeline with some clustering: profiler_more_events

I understand humans cannot consume that amount at once, but the result is quite usable (sorting/filtering cuts down the number of rows). I ultimately plan to use http://dygraphs.com for bird eye view and switch to Timeline as the number of visible items drops down to 100 or so. For that kind of implementation "additional resource usage" does not matter. The problem is it takes time to implement hybrid of dygraphs/timeline.

What I do now is quick&dirty "throw 1K heaviest items at Timeline". It is usable, thus I kindly ask if 1K..10K items is a workable approach for Timeline.

rangechange or rangechanged

I guess this only works in case request to server takes zoom level into acoount and results in "clustered" data from the server. For my use case "show me the latest 1 hour of workload" results in ~10K evens. I throw it at slickgrid and it is still usable.

It still would be grateful if Timeline could render clusters without knowing exact content of each item. Currently it just throws away individual contents, but I have no option to .

where items are automatically aggregated in groups when zooming out

I did look into the feature and it is quite fine. Current implementation has some hard code maxItems. I am not sure what is best for me, but I believe it to be the "height" of the resulting groups. Given the Timeline height, there is exact number of levels that can be visible, thus I expect clustering to collapse overlapping items until they fit in height (see the first screenshot).

josdejong commented 11 years ago

I ultimately plan to use http://dygraphs.com for bird eye view and switch to Timeline as the number of visible items drops down to 100 or so.

That makes me curious on what you exactly need from dygraph. I suppose you are aware of the Graph visualization, which shares its source with the Timeline. We ultimately work on fully integrating these two, so you could easily have line graphs, events, ranges, and annotations in a single interactive, moveble and zoomable chart.

We have shared enough ideas on clustering solutions, that's on the drawing board and already partially integrated.

It still would be grateful if Timeline could render clusters without knowing exact content of each item.

Still, nothing stops you from creating your own simple data controller, link it to the Timeline using rangechange or rangechanged, let this data controller decide on your own current "cluster level", and retrieve and cache data in different levels of detail from the server accordingly. The exact mechanism that you would like the Timeline to do for you...

vlsi commented 11 years ago

That makes me curious on what you exactly need from dygraph

Stacked charts. I believe at certain zoom level I need to drop all individual events and even clusters and display just a density as a chart. There are several metrix to aggregate (subsustem A time, subsystem B time, etc), thus it would result in several lines/areas stacked on top of each other.

At very extreme it could result in http://square.github.com/cubism/ , but I beleve this is really extreme for the typical engineers.

Graph visualization could be just fine (just lines, no filling), but I want to start with Timeline, see how it goes, get the feedback, etc.

I suppose you are aware of the Graph visualization,

I admit I am a fan of Timeline/Graph way of labeling time axis.

let this data controller decide on your own current "cluster level", and retrieve and cache data in different levels of detail from the server accordingly

As far as I understand, the problem of "retrieving top N items that intersect given timerange" has no easy solution. hashmap/btee/redblacktree/etc classics do not cover "interval" queries.

My current backend is a dummy file, the frontend is javascipt. So spartial queries are just no option for me. I do not feel confident implementing r-trees or UB-trees.

josdejong commented 11 years ago

Thanks for your feedback. Your use case is interesting, it's kind of what we are aiming for with our visualizations: visualizing large data sets, which involves things like smart rendering, smart clustering, and smart fetching (lazy loading), etc.

If you store your data in a (scalable) NoSQL database like CouchDB or MongoDB, you can do the queries you need perfectly fine (i.e. order items by date, filter the items within an interval - just store your dates as ISOString or as Long, and filter on a min and max value).