cesium/Apps/Sandcastle/gallery/3D Tiles Feature Styling.html

214 lines
8.0 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<meta
name="description"
content="Use 3D Tiles Styling to assign colors based on material or find all office buildings."
/>
<meta name="cesium-sandcastle-labels" content="Beginner, 3D Tiles" />
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script
type="text/javascript"
src="../../../Build/CesiumUnminified/Cesium.js"
nomodule
></script>
<script type="module" src="../load-cesium-es6.js"></script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay">
<h1>Loading...</h1>
</div>
<div id="toolbar">
<select class="cesium-button" id="dropdown">
<option value="0">Color By Building Material</option>
<option value="1">Color By Distance To Selected Location</option>
<option value="2">Highlight Residential Buildings</option>
<option value="3">Show Office Buildings Only</option>
<option value="4">Show Apartment Buildings Only</option>
</select>
<table class="infoPanel">
<tbody>
<tr>
<td>Click on a building to select as the central location</td>
</tr>
</tbody>
</table>
</div>
<script id="cesium_sandcastle_script">
window.startup = async function (Cesium) {
"use strict";
//Sandcastle_Begin
// How to use the 3D Tiles Styling language to style individual features, like buildings.
// Styling language specification: https://github.com/CesiumGS/3d-tiles/tree/main/specification/Styling
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// Add Cesium OSM buildings to the scene as our example 3D Tileset.
const osmBuildingsTileset = await Cesium.createOsmBuildingsAsync();
viewer.scene.primitives.add(osmBuildingsTileset);
// Set the initial camera to look at Seattle
viewer.scene.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-122.3472, 47.598, 370),
orientation: {
heading: Cesium.Math.toRadians(10),
pitch: Cesium.Math.toRadians(-10),
},
});
// Styling functions
// Color by material checks for null values since not all
// buildings have the material property.
function colorByMaterial() {
osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
defines: {
material: "${feature['building:material']}",
},
color: {
conditions: [
["${material} === null", "color('white')"],
["${material} === 'glass'", "color('skyblue', 0.5)"],
["${material} === 'concrete'", "color('grey')"],
["${material} === 'brick'", "color('indianred')"],
["${material} === 'stone'", "color('lightslategrey')"],
["${material} === 'metal'", "color('lightgrey')"],
["${material} === 'steel'", "color('lightsteelblue')"],
["true", "color('white')"], // This is the else case
],
},
});
}
function highlightAllResidentialBuildings() {
osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
[
"${feature['building']} === 'apartments' || ${feature['building']} === 'residential'",
"color('cyan', 0.9)",
],
[true, "color('white')"],
],
},
});
}
function showByBuildingType(buildingType) {
switch (buildingType) {
case "office":
osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
show: "${feature['building']} === 'office'",
});
break;
case "apartments":
osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
show: "${feature['building']} === 'apartments'",
});
break;
default:
break;
}
}
// Color the buildings based on their distance from a selected central location
function colorByDistanceToCoordinate(pickedLatitude, pickedLongitude) {
osmBuildingsTileset.style = new Cesium.Cesium3DTileStyle({
defines: {
distance: `distance(vec2(\${feature['cesium#longitude']}, \${feature['cesium#latitude']}), vec2(${pickedLongitude},${pickedLatitude}))`,
},
color: {
conditions: [
["${distance} > 0.014", "color('blue')"],
["${distance} > 0.010", "color('green')"],
["${distance} > 0.006", "color('yellow')"],
["${distance} > 0.0001", "color('red')"],
["true", "color('white')"],
],
},
});
}
// When dropdown option is not "Color By Distance To Selected Location",
// remove the left click input event for selecting a central location
function removeCoordinatePickingOnLeftClick() {
document.querySelector(".infoPanel").style.visibility = "hidden";
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
// Add event listeners to dropdown menu options
document.querySelector(".infoPanel").style.visibility = "hidden";
const menu = document.getElementById("dropdown");
menu.options[0].onselect = function () {
removeCoordinatePickingOnLeftClick();
colorByMaterial();
};
menu.options[1].onselect = function () {
// Default to Space Needle as the central location
colorByDistanceToCoordinate(47.62051, -122.34931);
document.querySelector(".infoPanel").style.visibility = "visible";
// Add left click input to select a building to and extract its coordinates
handler.setInputAction(function (movement) {
viewer.selectedEntity = undefined;
const pickedBuilding = viewer.scene.pick(movement.position);
if (pickedBuilding) {
const pickedLatitude = pickedBuilding.getProperty("cesium#latitude");
const pickedLongitude = pickedBuilding.getProperty("cesium#longitude");
colorByDistanceToCoordinate(pickedLatitude, pickedLongitude);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};
menu.options[2].onselect = function () {
removeCoordinatePickingOnLeftClick();
highlightAllResidentialBuildings();
};
menu.options[3].onselect = function () {
removeCoordinatePickingOnLeftClick();
showByBuildingType("office");
};
menu.options[4].onselect = function () {
removeCoordinatePickingOnLeftClick();
showByBuildingType("apartments");
};
menu.onchange = function () {
Sandcastle.reset();
const item = menu.options[menu.selectedIndex];
if (item && typeof item.onselect === "function") {
item.onselect();
}
};
colorByMaterial(); //Sandcastle_End
};
if (typeof Cesium !== "undefined") {
window.startupCalled = true;
window.startup(Cesium).catch((error) => {
"use strict";
console.error(error);
});
Sandcastle.finishedLoading();
}
</script>
</body>
</html>