CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.79k stars 3.46k forks source link

Declarative custom elements for Cesium #10876

Open angrycat9000 opened 1 year ago

angrycat9000 commented 1 year ago

Overview

Use custom element web components to allow cesium to be used declaratively in HTML.

Currently Cesium is an imperative library that requires writing Javascript code with step by step instructions to set up the view. Many newer UI frameworks (like React, Vue, Svlete) are declarative. They allow the developer to declare what they want to display.

Example of current imperative Javascript code

const viewer = new Cesium.Viewer("cesiumContainer", {
  animation: true,
  homeButton: true,
  navigationHelpButton: false,
  shadows: true,
  shouldAnimate: true,
});

viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
  url:  "../SampleData/Cesium3DTiles/Tilesets/Tileset/tileset.json"
}));

viewer.entities.add({
    position: position,
    orientation: orientation,
    model: {
      uri: "../SampleData/models/CesiumAir/Cesium_Air.glb",
      minimumPixelSize: 128,
      maximumScale: 20000,
    },
  });

Example of what a declarative custom element interface could look like

<cesium-view shadows animate>
  <cesium-animation-controls></cesium-animation-controls>
  <cesium-navigation-controls hide-help></cesium-navigation-controls>
  <cesium-tileset src= "../SampleData/Cesium3DTiles/Tilesets/Tileset/tileset.json"></cesium-tileset>. 
  <cesium-model
    src="../SampleData/models/CesiumAir/Cesium_Air.glb"
    minium-pixel-size="128"
    maximum-scale="20000"
  ></cesium-model>
</cesium-view>

Other custom element functionality

Using custom elements would also allow functionality like:

First steps

I think the first steps would be to create a proof of concept cesium-viewer element that mirrors the exposes Viewer interface today. It would not support any sub-elements like the example above (there would still need to be some imperative configuration).

This could be used as a building block to start adding more elements like cesium-tileset.

Long term vision

Longer term I would like to see the viewer element be more modular and extensible for widgets. It provides a generic set of hosting capability for widgets (such as accessing the scene, maybe some basic positioning for widgets). Instead of the current system where the viewer knows about all possible widgets and they all get configured via the viewer object. That puts cesium created widgets on the same level as user created widgets. The cesium created widgets can serve as examples for how to create your own custom widgets.

kring commented 1 year ago

Probably worth taking a look at Resium if you haven't seen it already.

angrycat9000 commented 1 year ago

Probably worth taking a look at Resium if you haven't seen it already.

Thanks for pointing that out. Yes this would be similar to Resium, however it would use custom elements instead of React. The advantage of custom elements is that they are not tied to any particular framework. So they could be used in React, Angular, Vue, or with plain HTML+JS.

ggetz commented 1 year ago

Maybe we look at \<model-viewer>, a web component for simple display of glTFs, for inspiration.

rudifa commented 1 year ago

Hi @angrycat9000

(1) Let me ask for some clarifications:

"Use custom element web components to allow cesium to be used declaratively in HTML."

I would interpret this to mean 'use Lit elements', since these appear to be the most advanced form of web components. Is this correct, or would you also consider alternative web component implementations?

Will the proposed declarative API be aimed at the current community of Cesium users, or should it also facilitate the access to Cesium to a yet wider public? How should this impact and inform the new API development?

IMO, the users of the new API should rely on the corresponding API documentation (to be developed), rather than having to dig into the existing Cesium documentation. Would you agree?

Your sketch of the declarative API suggest a progressively increasing degree of modularity. Are there plans to modularize Cesium (break up into smaller subsystems)? How would this impact the new API?

May I suggest that you should draft a guidance document that would define objectives aimed at and trace the directions to follow towards the new declarative API?

(2) Apropos the "First steps" and "proof of concept cesium-viewer element that mirrors the exposed Viewer interface":

How would you define the scope of the Viewer interface? I suppose that it goes beyond the formal list of properties and methods of the Cesium.Viewer object. Is this correct?

Lit elements expose a set of attributes whose values can

The first group could map directly to the properties of the underlying object (the Viewer), while the second group might map to some method calls on the object or on its child objects. Some attributes could serve both purposes.

I think that you could greatly advance the prototyping work if you could draft a list of <cesium-viewer> attributes that you want to see implemented in the early development rounds.

(3) My prototypes

I recently started experimenting with Cesium-in-Lit, and I hit and reported a problem (cesium/issues/10907). In her responses, @ggetz pointed me to this thread.

Meanwhile, helped by my js-mentor @olange I implemented a workaround, and I deployed my prototype on netlify. I just updated it, based on my thinking since I first saw this discussion.

My questions and suggestions above are a byproduct of my prototyping so far. I would greatly appreciate if you could respond with comments, guidance and possibly with a challenge to implement a more substantial prototype.

@rudifa

angrycat9000 commented 1 year ago

Thanks for your feedback @rudifa

I would interpret this to mean 'use Lit elements', since these appear to be the most advanced form of web components. Is this correct, or would you also consider alternative web component implementations?

It could be Lit since there is experience using that framework at Cesium. However, it might also make sense to just write it as a vanilla custom element with no framework if most of API would be focused on changing properties of the Cesium viewer object and not writing HTML.

Will the proposed declarative API be aimed at the current community of Cesium users, or should it also facilitate the access to Cesium to a yet wider public? How should this impact and inform the new API development?

It would probably start with the existing names and structures and see if there are areas that could be simplified for declarative rendering. That would avoid having two disjointed APIs but also allowing some freedom to make it easier to write declaratively.

If there are areas you think could be improved on the existing API please let us know.

How would you define the scope of the Viewer interface? I suppose that it goes beyond the formal list of properties and methods of the Cesium.Viewer object. Is this correct?

The first pass would probably be focused on the commonly used properties and might leave out some of the less frequently used properties. I would not expect it to be adding anything that isn't already available.

It would also extend beyond just the Viewer object itself. A large part of this will be declaring the data that is shown in the viewer. That brings in things like tilesets and models. It will probably be a whole set of elements needed to represent this complexity, not just a cesium-viewer element.

I recently started experimenting with Cesium-in-Lit, and I hit and reported a problem

Thank you for reporting that issue. That is great to see others in the community interested in having a declaratively rendered cesium viewer.

rudifa commented 1 year ago

Hi @angrycat9000

Thank you for the comments and clarifications.

it might also make sense to just write it as a vanilla custom element with no framework

I think that LitElement places an useful layer of abstractions over the HTMLElement, hiding the drudgery and boilerplate code needed to use the HTMLElement API directly, see for example the codelab From Web Component to Lit Element.