Add existing to tracked
This commit is contained in:
+103
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
Reference in New Issue
Block a user