Skip to content

[Tracker] View System Improvements #9670

Description

@ibgreen-openai

Target Use Case

deck view system

A more sophisticated view system could be a powerful addition to deck.gl. Since it is starting to look like we have a long list of ideas around view system improvements, it is probably best to collect them and ensure that any changes we make fit into the bigger picture.

Proposal

Views

Improved declarative support

  • Support for calc() expressions? Add layout expressions for view positions #9842
    • In Infovis, adding synchronized timelines and legend views would benefit from width: 'calc(100% - 250px)' type expressions.
    • It is not hard to implement the CSS spec and handle most of the supported units.

View override logic (declarative)

  • Views: ViewState prop override support for object / array values?
    • Views can be declared with props that override viewState. But this does not handle partial overrides like zoom: [2,] or position: [,,10] well.
    • Such props are more common in the non-geospatial view states.

View filtering

  • Currently deck.layerFilter has to be a "global" function.
    • Add support for a declarative version, a list or map of strings to include or exclude, a list of regexps etc.

    • Allow layer filters to be specified on views?

    • Allow view filters to be specified on layers?

    • Intuitiveness of filtering API: Filtering can gets stuck on composite layers, preventing actual layers from rendering, not super intuitive. Maybe multiple ways to address this.

      • Perhaps there is a difference in internal composite layers and primary composite layers?

Nesting Layers in Views.

  • An alternative to view filtering is to allow layers to be nested in views.
views: [new OrthographicView({layers: ....})]
  • LayerGroups? - a problem occurs when wanting to render a group of layers in multiple views. By defining a LayerGroup:
views: [
    new LayerGroup({id: 'group1', layers: [...], 
    new OrthographicView({id: 'view1, layers: 'group1', ....})
]

or

layers: [new LayerGroup({id: 'group1', layers: [...]}),
views: [new OrthographicView({id: 'view1, layers: 'group1', ....})]

View Override logic

  • Widgets that manipulate views are really cool. Being able to create a sophisticated configurable UI by just adding a widget is a powerful feature.
  • If we allow widgets to override views, should we define a system for that independently of widtets.
  • Can we define a view override cycle that is predictable (e.g. Widgets apply their changes in order? can application opt in?, ...)
  • Or do we want Widgets to accept views and layer props? If so ,should should we allow views to accept Widgets as children?

ViewState manipulation logic

A number of widgets are implementing hacky ways to manipulate the view state.

  • Consolidate this, perhaps first on the WidgetManager, and move such logic out of the widgets.

Controllers

  • Boundaries / extents
    • In infovis orhtographic views, defining a world size and preventing the user from panning away from the "world" would be usefl.
  • Inertia pans behave poorly when rendering very large datasets. (Likely a bug, not a feature)
    • The timing uses to calculate the inertia seems to assume that the render cycle doesn't exceed its tick, creates a wobbly effect.

View Layout RFC

image

Changes

  • Adds plain (non-class) discriminated view layout types for row, column, overlay, and spacer layouts.
  • Adds buildViewsFromViewLayout, including view reuse, length parsing, split metadata, and viewPropsById bounds overrides.
  • Exports the compiler and associated types from @deck.gl/widgets and deck.gl.
  • Adds focused compiler tests and API docs with a usage section.

View Layout Syntax Audit

We do have a point of reference in existing 9.3 splitter widget which provides a minimal layout syntax for its views prop

What changes could be made to the new view layout syntax that would make it more similar to the old syntax

The closest change would be to let the new compiler accept a split-container shape that mirrors

SplitterWidget ViewLayout Concerns with aligning
list of views, horizontal or vertical nested hierarchy of layouts and views Scope is different
<item>.orientation <item>.layout ViewLayout supports more layout types, not just orientation
<item>.orientation: horizontal <item>.layout: row Could be aligned <item>.layout: 'horizontal'
<item>: vertical layout: column Could be aligned
SplitterWidgetProps.views <item>.children Could be aligned though children can be layout items not just views

SplitterWidgetViewLayout:

const layout = {
  orientation: 'horizontal',
  splitId: 'sidebar-main',
  initialSplit: 0.25,
  minSplit: 0.15,
  maxSplit: 0.5,
  views: [
    new OrthographicView({id: 'sidebar'}),
    new OrthographicView({id: 'main'})
  ]
};

This would map internally to the proposed:

{
  type: 'row',
  splitId: 'sidebar-main',
  children: [...]
}

How to align?

Use views instead of children for row, column, and overlay.

  • Pro: This reads closer to deck.gl and SplitterWidgetViewLayout.
  • Downside: overlay can contain layout nodes and spacers too, so children is semantically a little more accurate.
  • Use orientation for split layouts, keep type only for non-split nodes

Split containers use orientation.

  • Overlay/spacer keep type: 'overlay' | 'spacer'.
  • This is closest to the old syntax, but the union becomes less uniform.

ViewLayout Compared To CSS

CSS is a useful benchmark for whether the ViewLayout API feels obvious. The current API maps most closely to a constrained subset of Flexbox plus absolute-positioned overlays.

CSS concept Current ViewLayout equivalent Fit
display: flex; flex-direction: row/column `type: 'row' 'column'ororientation`
Flex item fixed basis child width / height Strong
Flex item min/max minPixels / maxPixels Good, but less CSS-like naming
position: absolute inside parent overlay + child x/y/width/height Strong
padding inset Reasonable, but CSS would call this padding
gap manual spacer Weak
flex-grow / fr units flexible unspecified children divide remaining equally Basic only
CSS Grid named areas none Missing
minmax() / clamp() width: '50%' + minPixels/maxPixels Good conceptually
subgrid nested layouts Similar spirit, simpler
container queries caller recompiles with measured size Similar responsibility, not declarative
anchor positioning viewPropsById / overlay offsets Partial
resize/split panes splitId + splittersById Not CSS, but app-layout-specific

The biggest CSS-like gaps are:

  1. No gap

    Spacer works, but it is verbose. A gap: 8 prop on row/column would feel natural and map directly to CSS flex/grid.

  2. No flex weights

    Today unspecified children divide remaining space equally. CSS users may expect something like flex: 2 or weight: 2.

  3. Axis-dependent minPixels / maxPixels

    This is pragmatic, but CSS would likely spell this as minWidth / maxWidth and minHeight / maxHeight, or minSize / maxSize for stack-axis sizing.

  4. No named grid/areas

    If the API wants to compete with CSS Grid, it would need named cells or areas. That may be too much for the current PR.

  5. Generated split ids are less CSS-like than line names

    CSS Grid has named lines. A closer model might be splitIds: ['sidebar-main', 'main-inspector'] for multi-child splits. Generated ids are simpler, but less authored and less semantic.

Suggested docs language:

ViewLayout is closest to a constrained subset of Flexbox plus absolute-positioned overlays. Rows and columns distribute space, children may declare fixed or percentage sizes plus pixel min/max constraints, and overlay children are positioned within their parent rect.

For future CSS-inspired API additions, the highest-value options are gap and flex / weight.

CSS grid

CSS grids could be nice, to make a number of views for different cities etc. For “N city views” the current row/column API gets awkward because you either manually nest rows/columns or generate a tree. A grid layout would be more natural:

const layout = {
  type: 'grid',
  columns: 3,
  gap: 8,
  children: cities.map(city => new MapView({id: city.id}))
};

Stacked PRs

The Follow-up "PoC" PR adds a number experimental widgets, website example, playground JSON sample, and widget docs, this is mainly for exposition at the moment, to show the system working and things that could be built by users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions