Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

widget_3d_tiles: the integrated layer manager is now optional. #808

Merged
merged 2 commits into from
Apr 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 90 additions & 60 deletions packages/widget_3d_tiles/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,47 @@ const DEFAULT_OPTIONS = {
position: 'top-right', // should be deprecated https://github.com/iTowns/itowns/issues/2005
};

/**
* Within a list of already existing layers, add a UI entry for a newly
* appended layer (together with a button for its removal).
*
* @param {itowns.View} view - The view to which the layer will be added
* @param {itowns.C3DTilesLayer} layer - layer to be added to dom element
* @param {HTMLDivElement} layersContainer - HTML division holding the listed layers
* @param {string} [layerContainerClassName] - Class name of the layer container
*/
function addLayerToDomElement(
view,
layer,
layersContainer,
layerContainerClassName
) {
const layerContainerDomElement = document.createElement('div');
if (layerContainerClassName)
layerContainerDomElement.classList.add(layerContainerClassName);
layersContainer.appendChild(layerContainerDomElement);

// visibility checkbox
const { input, parent } = createLabelInput(layer.name, 'checkbox');
layerContainerDomElement.appendChild(parent);

input.checked = layer.visible;
input.onchange = () => {
layer.visible = input.checked;
view.notifyChange();
};

// remove button
const removeButton = document.createElement('button');
removeButton.innerText = 'Remove';
layerContainerDomElement.appendChild(removeButton);

removeButton.onclick = () => {
view.removeLayer(layer.id, true); // clear cache
layerContainerDomElement.remove();
};
}

export class C3DTiles extends itownsWidget.Widget {
/**
*
Expand All @@ -17,19 +58,27 @@ export class C3DTiles extends itownsWidget.Widget {
* @param {string} options.layerContainerClassName - class name of the layer container div
* @param {string} options.urlContainerClassName - class name of the layer container div
* @param {string} options.c3DTFeatureInfoContainerClassName - class name of the c3DTFeatureInfo container div
* @param {boolean} options.displayExistingLayers - whether the existing layers should be listed in the UI or not (default is True)
*/
constructor(view, options = {}) {
super(view, options, DEFAULT_OPTIONS);
// Available layers are optionnaly listed in the UI. Inhibiting this display
// allows for an alternative usage of other widgets with a similar purpose
// but different feature e.g. @ud-viz/widget_layer_choice.
if (options.displayExistingLayers == undefined) {
options.displayExistingLayers = true;
}

/** @type {THREE.Box3Helper} */
this.displayedBBFeature = new THREE.Box3Helper(new THREE.Box3());
this.displayedBBFeature.visible = false;
view.scene.add(this.displayedBBFeature);

// cant click through the widget
// Inhibit click selection "through" the widget
this.domElement.onclick = (event) => event.stopImmediatePropagation();

// add C3DTilesLayer from url
// Display a UI section allowing the addition of a C3DTilesLayer out of
// an url and a (local) tagname.
const urlObject = createLabelInput('url', 'text');
if (options.urlContainerClassName)
urlObject.parent.classList.add(options.urlContainerClassName);
Expand All @@ -44,42 +93,6 @@ export class C3DTiles extends itownsWidget.Widget {
requestButton.innerText = 'Add 3DTiles From URL';
urlObject.parent.appendChild(requestButton);

// layers container
const layersContainer = document.createElement('div');
layersContainer.innerText = 'Layers:';
this.domElement.appendChild(layersContainer);

/**
*
* @param {itowns.C3DTilesLayer} layer - layer to add to dom element
*/
const addLayerToDomElement = (layer) => {
const layerContainerDomElement = document.createElement('div');
if (options.layerContainerClassName)
layerContainerDomElement.classList.add(options.layerContainerClassName);
layersContainer.appendChild(layerContainerDomElement);

// visibility checkbox
const { input, parent } = createLabelInput(layer.name, 'checkbox');
layerContainerDomElement.appendChild(parent);

input.checked = layer.visible;
input.onchange = () => {
layer.visible = input.checked;
view.notifyChange();
};

// remove button
const removeButton = document.createElement('button');
removeButton.innerText = 'Remove';
layerContainerDomElement.appendChild(removeButton);

removeButton.onclick = () => {
view.removeLayer(layer.id, true); // clear cache
layerContainerDomElement.remove();
};
};

requestButton.onclick = () => {
// add layer
const url = urlObject.input.value;
Expand All @@ -97,34 +110,51 @@ export class C3DTiles extends itownsWidget.Widget {
view
);
itowns.View.prototype.addLayer.call(view, c3DTilesLayer);
addLayerToDomElement(c3DTilesLayer);
if (options.displayExistingLayers)
addLayerToDomElement(
view,
c3DTilesLayer,
this.layersContainer,
options.layerContainerClassName
);
} catch (error) {
// do not catch error when a wrong url have been entered
alert(error);
}
};

// initialize with current layer
view
.getLayers()
.filter((el) => el.isC3DTilesLayer)
.forEach((layer) => {
addLayerToDomElement(layer);
});

/**
* c3DTfeature display container
*
@type {HTMLDivElement} */
this.c3DTFeatureInfoContainer = document.createElement('div');
if (options.c3DTFeatureInfoContainerClassName)
this.c3DTFeatureInfoContainer.classList.add(
options.c3DTFeatureInfoContainerClassName
);

this.c3DTFeatureInfoContainer.hidden = true; // hidden by default
this.domElement.appendChild(this.c3DTFeatureInfoContainer);
}
if (options.displayExistingLayers) {
this.layersContainer = document.createElement('div');
this.layersContainer.innerText = 'Layers:';
this.domElement.appendChild(this.layersContainer);

// Initialize the list of existing layer
view
.getLayers()
.filter((el) => el.isC3DTilesLayer)
.forEach((layer) => {
addLayerToDomElement(
view,
layer,
this.layersContainer,
options.layerContainerClassName
);
});

/**
* c3DTfeature display container
*
@type {HTMLDivElement} */
this.c3DTFeatureInfoContainer = document.createElement('div');
if (options.c3DTFeatureInfoContainerClassName)
this.c3DTFeatureInfoContainer.classList.add(
options.c3DTFeatureInfoContainerClassName
);

this.c3DTFeatureInfoContainer.hidden = true; // hidden by default
this.domElement.appendChild(this.c3DTFeatureInfoContainer);
} // if (options.displayExistingLayers)
} // Constructor()

/**
*
Expand Down
Loading