Add existing to tracked

This commit is contained in:
Jay
2026-08-11 09:53:42 -04:00
parent afe07f3055
commit ffd6e3d73c
8531 changed files with 4396230 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
.cesium-infoBox {
display: block;
position: absolute;
top: 50px;
right: 0;
width: 40%;
max-width: 480px;
background: rgba(38, 38, 38, 0.95);
color: #edffff;
border: 1px solid #444;
border-right: none;
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
box-shadow: 0 0 10px 1px #000;
transform: translate(100%, 0);
visibility: hidden;
opacity: 0;
transition:
visibility 0s 0.2s,
opacity 0.2s ease-in,
transform 0.2s ease-in;
}
.cesium-infoBox-visible {
transform: translate(0, 0);
visibility: visible;
opacity: 1;
transition:
opacity 0.2s ease-out,
transform 0.2s ease-out;
}
.cesium-infoBox-title {
display: block;
height: 20px;
padding: 5px 30px 5px 25px;
background: rgba(84, 84, 84, 1);
border-top-left-radius: 7px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
box-sizing: content-box;
}
.cesium-infoBox-bodyless .cesium-infoBox-title {
border-bottom-left-radius: 7px;
}
button.cesium-infoBox-camera {
display: block;
position: absolute;
top: 4px;
left: 4px;
width: 22px;
height: 22px;
background: transparent;
border-color: transparent;
border-radius: 3px;
padding: 0 5px;
margin: 0;
}
button.cesium-infoBox-close {
display: block;
position: absolute;
top: 5px;
right: 5px;
height: 20px;
background: transparent;
border: none;
border-radius: 2px;
font-weight: bold;
font-size: 16px;
padding: 0 5px;
margin: 0;
color: #edffff;
}
button.cesium-infoBox-close:focus {
background: rgba(238, 136, 0, 0.44);
outline: none;
}
button.cesium-infoBox-close:hover {
background: #888;
color: #000;
}
button.cesium-infoBox-close:active {
background: #a00;
color: #000;
}
.cesium-infoBox-bodyless .cesium-infoBox-iframe {
display: none;
}
.cesium-infoBox-iframe {
border: none;
width: 100%; /* Fallback */
width: calc(100% - 2px);
}
+209
View File
@@ -0,0 +1,209 @@
import {
buildModuleUrl,
Check,
Color,
defined,
destroyObject,
getElement,
} from "@cesium/engine";
import knockout from "../ThirdParty/knockout.js";
import subscribeAndEvaluate from "../subscribeAndEvaluate.js";
import InfoBoxViewModel from "./InfoBoxViewModel.js";
/**
* A widget for displaying information or a description.
*
* @alias InfoBox
* @constructor
*
* @param {Element|string} container The DOM element or ID that will contain the widget.
*
* @exception {DeveloperError} Element with id "container" does not exist in the document.
*/
function InfoBox(container) {
//>>includeStart('debug', pragmas.debug);
Check.defined("container", container);
//>>includeEnd('debug');
container = getElement(container);
const infoElement = document.createElement("div");
infoElement.className = "cesium-infoBox";
infoElement.setAttribute(
"data-bind",
'\
css: { "cesium-infoBox-visible" : showInfo, "cesium-infoBox-bodyless" : _bodyless }',
);
container.appendChild(infoElement);
const titleElement = document.createElement("div");
titleElement.className = "cesium-infoBox-title";
titleElement.setAttribute("data-bind", "text: titleText");
infoElement.appendChild(titleElement);
const cameraElement = document.createElement("button");
cameraElement.type = "button";
cameraElement.className = "cesium-button cesium-infoBox-camera";
cameraElement.setAttribute(
"data-bind",
'\
attr: { title: "Focus camera on object" },\
click: function () { cameraClicked.raiseEvent(this); },\
enable: enableCamera,\
cesiumSvgPath: { path: cameraIconPath, width: 32, height: 32 }',
);
infoElement.appendChild(cameraElement);
const closeElement = document.createElement("button");
closeElement.type = "button";
closeElement.className = "cesium-infoBox-close";
closeElement.setAttribute(
"data-bind",
"\
click: function () { closeClicked.raiseEvent(this); }",
);
closeElement.innerHTML = "×";
infoElement.appendChild(closeElement);
const frame = document.createElement("iframe");
frame.className = "cesium-infoBox-iframe";
frame.setAttribute("sandbox", "allow-same-origin allow-popups allow-forms"); //allow-pointer-lock allow-scripts allow-top-navigation
frame.setAttribute(
"data-bind",
"style : { maxHeight : maxHeightOffset(40) }",
);
frame.setAttribute("allowfullscreen", true);
infoElement.appendChild(frame);
const viewModel = new InfoBoxViewModel();
knockout.applyBindings(viewModel, infoElement);
this._container = container;
this._element = infoElement;
this._frame = frame;
this._viewModel = viewModel;
this._descriptionSubscription = undefined;
const that = this;
//We can't actually add anything into the frame until the load event is fired
frame.addEventListener("load", function () {
const frameDocument = frame.contentDocument;
//We inject default css into the content iframe,
//end users can remove it or add their own via the exposed frame property.
const cssLink = frameDocument.createElement("link");
cssLink.href = buildModuleUrl("Widgets/InfoBox/InfoBoxDescription.css");
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
//div to use for description content.
const frameContent = frameDocument.createElement("div");
frameContent.className = "cesium-infoBox-description";
frameDocument.head.appendChild(cssLink);
frameDocument.body.appendChild(frameContent);
//We manually subscribe to the description event rather than through a binding for two reasons.
//1. It's an easy way to ensure order of operation so that we can adjust the height.
//2. Knockout does not bind to elements inside of an iFrame, so we would have to apply a second binding
// model anyway.
that._descriptionSubscription = subscribeAndEvaluate(
viewModel,
"description",
function (value) {
// Set the frame to small height, force vertical scroll bar to appear, and text to wrap accordingly.
frame.style.height = "5px";
frameContent.innerHTML = value;
//If the snippet is a single element, then use its background
//color for the body of the InfoBox. This makes the padding match
//the content and produces much nicer results.
let background = null;
const firstElementChild = frameContent.firstElementChild;
if (
firstElementChild !== null &&
frameContent.childNodes.length === 1
) {
const style = window.getComputedStyle(firstElementChild);
if (style !== null) {
const backgroundColor = style["background-color"];
const color = Color.fromCssColorString(backgroundColor);
if (defined(color) && color.alpha !== 0) {
background = style["background-color"];
}
}
}
infoElement.style["background-color"] = background;
// Measure and set the new custom height, based on text wrapped above.
const height = frameContent.getBoundingClientRect().height;
frame.style.height = `${height}px`;
},
);
});
//Chrome does not send the load event unless we explicitly set a src
frame.setAttribute("src", "about:blank");
}
Object.defineProperties(InfoBox.prototype, {
/**
* Gets the parent container.
* @memberof InfoBox.prototype
*
* @type {Element}
*/
container: {
get: function () {
return this._container;
},
},
/**
* Gets the view model.
* @memberof InfoBox.prototype
*
* @type {InfoBoxViewModel}
*/
viewModel: {
get: function () {
return this._viewModel;
},
},
/**
* Gets the iframe used to display the description.
* @memberof InfoBox.prototype
*
* @type {HTMLIFrameElement}
*/
frame: {
get: function () {
return this._frame;
},
},
});
/**
* @returns {boolean} true if the object has been destroyed, false otherwise.
*/
InfoBox.prototype.isDestroyed = function () {
return false;
};
/**
* Destroys the widget. Should be called if permanently
* removing the widget from layout.
*/
InfoBox.prototype.destroy = function () {
const container = this._container;
knockout.cleanNode(this._element);
container.removeChild(this._element);
if (defined(this._descriptionSubscription)) {
this._descriptionSubscription.dispose();
}
return destroyObject(this);
};
export default InfoBox;
+90
View File
@@ -0,0 +1,90 @@
@import url(../shared.css);
body {
margin: 0;
padding: 0;
}
.cesium-infoBox-description {
font-family: sans-serif;
font-size: 13px;
padding: 4px 10px;
margin-right: 4px;
color: #edffff;
}
.cesium-infoBox-description a:link,
.cesium-infoBox-description a:visited,
.cesium-infoBox-description a:hover,
.cesium-infoBox-description a:active {
color: #edffff;
}
.cesium-infoBox-description table {
color: #edffff;
}
.cesium-infoBox-defaultTable {
width: 100%;
color: #edffff;
}
.cesium-infoBox-defaultTable tr:nth-child(odd) {
background-color: rgba(84, 84, 84, 0.8);
}
.cesium-infoBox-defaultTable tr:nth-child(even) {
background-color: rgba(84, 84, 84, 0.25);
}
.cesium-infoBox-defaultTable th {
font-weight: normal;
padding: 3px;
vertical-align: middle;
text-align: center;
}
.cesium-infoBox-defaultTable td {
padding: 3px;
vertical-align: middle;
text-align: left;
}
.cesium-infoBox-description-lighter {
color: #000000;
}
.cesium-infoBox-description-lighter a:link,
.cesium-infoBox-description-lighter a:visited,
.cesium-infoBox-description-lighter a:hover,
.cesium-infoBox-description-lighter a:active {
color: #000000;
}
.cesium-infoBox-description-lighter table {
color: #000000;
}
.cesium-infoBox-defaultTable-lighter {
width: 100%;
color: #000000;
}
.cesium-infoBox-defaultTable-lighter tr:nth-child(odd) {
background-color: rgba(179, 179, 179, 0.8);
}
.cesium-infoBox-defaultTable-lighter tr:nth-child(even) {
background-color: rgba(179, 179, 179, 0.25);
}
.cesium-infoBox-loadingContainer {
margin: 5px;
text-align: center;
}
.cesium-infoBox-loading {
display: inline-block;
background-image: url(../Images/info-loading.gif);
width: 16px;
height: 11px;
}
+117
View File
@@ -0,0 +1,117 @@
import { defined, Event } from "@cesium/engine";
import knockout from "../ThirdParty/knockout.js";
const cameraEnabledPath =
"M 13.84375 7.03125 C 11.412798 7.03125 9.46875 8.975298 9.46875 11.40625 L 9.46875 11.59375 L 2.53125 7.21875 L 2.53125 24.0625 L 9.46875 19.6875 C 9.4853444 22.104033 11.423165 24.0625 13.84375 24.0625 L 25.875 24.0625 C 28.305952 24.0625 30.28125 22.087202 30.28125 19.65625 L 30.28125 11.40625 C 30.28125 8.975298 28.305952 7.03125 25.875 7.03125 L 13.84375 7.03125 z";
const cameraDisabledPath =
"M 27.34375 1.65625 L 5.28125 27.9375 L 8.09375 30.3125 L 30.15625 4.03125 L 27.34375 1.65625 z M 13.84375 7.03125 C 11.412798 7.03125 9.46875 8.975298 9.46875 11.40625 L 9.46875 11.59375 L 2.53125 7.21875 L 2.53125 24.0625 L 9.46875 19.6875 C 9.4724893 20.232036 9.5676108 20.7379 9.75 21.21875 L 21.65625 7.03125 L 13.84375 7.03125 z M 28.21875 7.71875 L 14.53125 24.0625 L 25.875 24.0625 C 28.305952 24.0625 30.28125 22.087202 30.28125 19.65625 L 30.28125 11.40625 C 30.28125 9.8371439 29.456025 8.4902779 28.21875 7.71875 z";
/**
* The view model for {@link InfoBox}.
* @alias InfoBoxViewModel
* @constructor
*/
function InfoBoxViewModel() {
this._cameraClicked = new Event();
this._closeClicked = new Event();
/**
* Gets or sets the maximum height of the info box in pixels. This property is observable.
* @type {number}
*/
this.maxHeight = 500;
/**
* Gets or sets whether the camera tracking icon is enabled.
* @type {boolean}
*/
this.enableCamera = false;
/**
* Gets or sets the status of current camera tracking of the selected object.
* @type {boolean}
*/
this.isCameraTracking = false;
/**
* Gets or sets the visibility of the info box.
* @type {boolean}
*/
this.showInfo = false;
/**
* Gets or sets the title text in the info box.
* @type {string}
*/
this.titleText = "";
/**
* Gets or sets the description HTML for the info box.
* @type {string}
*/
this.description = "";
knockout.track(this, [
"showInfo",
"titleText",
"description",
"maxHeight",
"enableCamera",
"isCameraTracking",
]);
this._loadingIndicatorHtml =
'<div class="cesium-infoBox-loadingContainer"><span class="cesium-infoBox-loading"></span></div>';
/**
* Gets the SVG path of the camera icon, which can change to be "crossed out" or not.
* @type {string}
*/
this.cameraIconPath = undefined;
knockout.defineProperty(this, "cameraIconPath", {
get: function () {
return !this.enableCamera || this.isCameraTracking
? cameraDisabledPath
: cameraEnabledPath;
},
});
knockout.defineProperty(this, "_bodyless", {
get: function () {
return !defined(this.description) || this.description.length === 0;
},
});
}
/**
* Gets the maximum height of sections within the info box, minus an offset, in CSS-ready form.
* @param {number} offset The offset in pixels.
* @returns {string}
*/
InfoBoxViewModel.prototype.maxHeightOffset = function (offset) {
return `${this.maxHeight - offset}px`;
};
Object.defineProperties(InfoBoxViewModel.prototype, {
/**
* Gets an {@link Event} that is fired when the user clicks the camera icon.
* @memberof InfoBoxViewModel.prototype
* @type {Event}
*/
cameraClicked: {
get: function () {
return this._cameraClicked;
},
},
/**
* Gets an {@link Event} that is fired when the user closes the info box.
* @memberof InfoBoxViewModel.prototype
* @type {Event}
*/
closeClicked: {
get: function () {
return this._closeClicked;
},
},
});
export default InfoBoxViewModel;