visgl / deck.gl

WebGL2 powered visualization framework
https://deck.gl
MIT License
12.13k stars 2.08k forks source link

[Feat] Advanced expressions for view positioning #6865

Open Pessimistress opened 2 years ago

Pessimistress commented 2 years ago

Target Use Case

As of v8.7, a View constructor can specify its position (x, y, width and height) as either an absolute value (number of pixels) or a relative value (percentage of with/height). With the current system, it is not possible to achieve the following without constructing new View instances on each resize:

Proposal

Solution 1: Accept callback functions

We can allow callback functions to be passed to a View's x, y, width and height. The callback may receive the canvas width and height as arguments at the time of evaluation. This will be very easy to implement and gives users the maximum flexibility when it comes to dynamic positioning.

I have experimented with this approach in a custom View class. My observation is that when trying to create sophisticated layouts, an application ends up having to pass separate functions to all four props, in which it repeats the same branching logic, then returns the respective values. The definition of a view can therefore be quite verbose. Moreover, callbacks in general are not as readable as CSS-like strings, and becomes harder to maintain over time.

@ibgreen has also brought up the use case of declarative/pydeck/JSON transport, where callbacks are not an option.

Solution 2: Extended syntax for expressions

This approach allows other string values to be passed to the positioning props. Under the hood, the parser will create a callback function from the expression. Here I'm attempting to start a list of such possible expressions, drawing inspiration from CSS math functions:

felixpalmer commented 2 years ago

Like the idea 👍 and think that solution 2 would be nicer from a user perspective. There is also nothing in principle stopping us allowing callback functions in addition to parsed expressions.

I think the proposed list of expressions is already very powerful and would cover many useful cases. Thinking out loud, an additional idea would be to allow referencing other views. E.g. x: 'view1.x + view1.w' would position a view to the right of view1 without having to worry about how view1 is sized. However I could see this being complex to implement.

ibgreen commented 2 years ago

For #1 I suppose we could add a callback prop that returns all 4 values to avoid the repeated branching.

2 is certainly very nice, but it is a lot of functionality to add to a supposedly small core library. There is a disease called "galloping featuritis" that sometimes affects mature software projects :)

If we really do want expressions, I note that we already have a JS expression parser as part of pydeck and perhaps we should consider moving that to core rather than implement another one?

Of course it will not support the CSS style syntax (% / px ), so maybe we really do need to add a CSS parser in addition to a JS parser...