[Tracker] View System Improvements
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 14.6k
- Forks
- 2.3k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 42
Description
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? #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.
- In Infovis, adding synchronized timelines and legend views would benefit from
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,]orposition: [,,10]well. - Such props are more common in the non-geospatial view states.
- Views can be declared with props that override viewState. But this does not handle partial overrides like
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 aLayerGroup:
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
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, andviewPropsByIdbounds overrides. - Exports the compiler and associated types from
@deck.gl/widgetsanddeck.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:
-
No
gapSpacer works, but it is verbose. A
gap: 8prop on row/column would feel natural and map directly to CSS flex/grid. -
No flex weights
Today unspecified children divide remaining space equally. CSS users may expect something like
flex: 2orweight: 2. -
Axis-dependent
minPixels/maxPixelsThis is pragmatic, but CSS would likely spell this as
minWidth/maxWidthandminHeight/maxHeight, orminSize/maxSizefor stack-axis sizing. -
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.
-
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:
ViewLayoutis 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by narrowing the tracker to one proposal, such as the View Layout RFC, and read the existing 9.3 splitter widget syntax alongside buildViewsFromViewLayout and the @deck.gl/widgets exports. A complete contribution would need an agreed scope, implementation, focused compiler tests, and API documentation; this issue does not identify files or a single acceptance criterion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100