Fotorealistische 3D-Kacheln sind im OGC-Standardformat glTF verfügbar. Sie können also jeden Renderer verwenden, der die OGC-3D-Kacheln-Spezifikation unterstützt, um Ihre 3D-Visualisierungen zu erstellen. Cesium ist beispielsweise eine grundlegende Open-Source-Bibliothek zum Rendern von 3D-Visualisierungen.
Mit CesiumJS arbeiten
CesiumJS ist eine Open-Source-JavaScript-Bibliothek für 3D-Visualisierungen im Web. Weitere Informationen zur Verwendung von CesiumJS finden Sie unter CesiumJS kennenlernen.
Nutzersteuerung
Der CesiumJS-Kachel-Renderer bietet eine Reihe von Standard-Steuerelementen.
Aktion | Beschreibung |
---|---|
Schwenkansichten | Linksklicken und ziehen |
Zoomansicht | Mit der rechten Maustaste klicken und ziehen oder Mausrad scrollen |
Ansicht drehen | Strg + Links-/Rechtsklick > Ziehen oder Mittelklick > Ziehen |
Best Practices
Es gibt mehrere Möglichkeiten, die 3D-Ladezeiten von CesiumJS zu verkürzen. Beispiel:
Aktiviere gleichzeitige Anfragen, indem du der gerenderten HTML-Datei die folgende Anweisung hinzufügst:
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = <REQUEST_COUNT>
Je höher
REQUEST_COUNT
ist, desto schneller werden die Kacheln geladen. Wenn Sie die Karte jedoch in einem Chrome-Browser mit einerREQUEST_COUNT
von mehr als 10 und deaktiviertem Cache laden, kann es zu einem bekannten Chrome-Problem kommen. Für die meisten Anwendungsfälle empfehlen wir für eine optimale Leistung eineREQUEST_COUNT
von 18.Detailebenen überspringen Weitere Informationen finden Sie in diesem Cesium-Problem.
Achten Sie darauf, dass Sie Datenangaben korrekt anzeigen. Aktivieren Sie dazu showCreditsOnScreen: true
. Weitere Informationen finden Sie unter Richtlinien.
Messwerte für das Rendering
Die Framerate ergibt sich aus der Häufigkeit, mit der die Methode requestAnimationFrame pro Sekunde aufgerufen wird.
Wie die Frame-Latenz berechnet wird, sehen Sie in der Klasse PerformanceDisplay.
Beispiele für CesiumJS-Renderer
Sie können den CesiumJS-Renderer mit den 3D-Kacheln der Map Tiles API verwenden, indem Sie einfach die URL des Stamm-Kachelsatzes angeben.
Einfaches Beispiel
Im folgenden Beispiel wird der CesiumJS-Renderer initialisiert und dann der Stamm-Tileset geladen.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>CesiumJS 3D Tiles Simple Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer.
const viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: false,
baseLayerPicker: false,
geocoder: false,
globe: false,
// https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/#enabling-request-render-mode
requestRenderMode: true,
});
// Add 3D Tiles tileset.
const tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is needed to appropriately display attributions
// as required.
showCreditsOnScreen: true,
}));
</script>
</body>
Weitere Informationen zu requestRenderMode
finden Sie unter Renderingmodus für Anfragen aktivieren.
Die HTML-Seite wird so gerendert, wie hier dargestellt.
Places API-Integration
Sie können CesiumJS mit der Places API verwenden, um weitere Informationen abzurufen. Mit dem Autocomplete-Widget können Sie zum Darstellungsbereich von Google Maps wechseln. In diesem Beispiel wird die Places Autocomplete API verwendet, die wie hier beschrieben aktiviert werden kann, und die Maps JavaScript API, die wie hier beschrieben aktiviert werden kann.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>CesiumJS 3D Tiles Places API Integration Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<label for="pacViewPlace">Go to a place: </label>
<input
type="text"
id="pacViewPlace"
name="pacViewPlace"
placeholder="Enter a location..."
style="width: 300px"
/>
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer.
const viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: false,
baseLayerPicker: false,
requestRenderMode: true,
geocoder: false,
globe: false,
});
// Add 3D Tiles tileset.
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is required to display attributions as required.
showCreditsOnScreen: true,
})
);
const zoomToViewport = (viewport) => {
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
viewport.getNorthEast().lng(), viewport.getNorthEast().lat(),
viewport.getSouthWest().lng(), viewport.getNorthEast().lat(),
viewport.getSouthWest().lng(), viewport.getSouthWest().lat(),
viewport.getNorthEast().lng(), viewport.getSouthWest().lat(),
viewport.getNorthEast().lng(), viewport.getNorthEast().lat(),
]),
width: 10,
clampToGround: true,
material: Cesium.Color.RED,
},
});
viewer.flyTo(viewer.entities);
};
function initAutocomplete() {
const autocomplete = new google.maps.places.Autocomplete(
document.getElementById("pacViewPlace"),
{
fields: [
"geometry",
"name",
],
}
);
autocomplete.addListener("place_changed", () => {
viewer.entities.removeAll();
const place = autocomplete.getPlace();
if (!place.geometry || !place.geometry.viewport) {
window.alert("No viewport for input: " + place.name);
return;
}
zoomToViewport(place.geometry.viewport);
});
}
</script>
<script
async=""
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initAutocomplete"
></script>
</body>
Drohnenansicht drehen
Sie können die Kamera steuern, um den Raster durchzuanimieren. In Kombination mit der Places API und der Elevation API simuliert diese Animation einen interaktiven Drohnenflug über einen beliebigen POI.
In diesem Codebeispiel wird der Ort, den Sie im Autocomplete-Widget ausgewählt haben, umkreist.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>CesiumJS 3D Tiles Rotating Drone View Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<label for="pacViewPlace">Go to a place: </label>
<input type="text" id="pacViewPlace" name="pacViewPlace" placeholder="Enter a location..." style="width: 300px" />
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer and remove unneeded options.
const viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: false,
baseLayerPicker: false,
homeButton: false,
fullscreenButton: false,
navigationHelpButton: false,
vrButton: false,
sceneModePicker: false,
geocoder: false,
globe: false,
infobox: false,
selectionIndicator: false,
timeline: false,
projectionPicker: false,
clockViewModel: null,
animation: false,
requestRenderMode: true,
});
// Add 3D Tile set.
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is required to display attributions.
showCreditsOnScreen: true,
})
);
// Point the camera at a location and elevation, at a viewport-appropriate distance.
function pointCameraAt(location, viewport, elevation) {
const distance = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(
viewport.getSouthWest().lng(), viewport.getSouthWest().lat(), elevation),
Cesium.Cartesian3.fromDegrees(
viewport.getNorthEast().lng(), viewport.getNorthEast().lat(), elevation)
) / 2;
const target = new Cesium.Cartesian3.fromDegrees(location.lng(), location.lat(), elevation);
const pitch = -Math.PI / 4;
const heading = 0;
viewer.camera.lookAt(target, new Cesium.HeadingPitchRange(heading, pitch, distance));
}
// Rotate the camera around a location and elevation, at a viewport-appropriate distance.
let unsubscribe = null;
function rotateCameraAround(location, viewport, elevation) {
if(unsubscribe) unsubscribe();
pointCameraAt(location, viewport, elevation);
unsubscribe = viewer.clock.onTick.addEventListener(() => {
viewer.camera.rotate(Cesium.Cartesian3.UNIT_Z);
});
}
function initAutocomplete() {
const autocomplete = new google.maps.places.Autocomplete(
document.getElementById("pacViewPlace"), {
fields: [
"geometry",
"name",
],
}
);
autocomplete.addListener("place_changed", async () => {
const place = autocomplete.getPlace();
if (!(place.geometry && place.geometry.viewport && place.geometry.location)) {
window.alert(`Insufficient geometry data for place: ${place.name}`);
return;
}
// Get place elevation using the ElevationService.
const elevatorService = new google.maps.ElevationService();
const elevationResponse = await elevatorService.getElevationForLocations({
locations: [place.geometry.location],
});
if(!(elevationResponse.results && elevationResponse.results.length)){
window.alert(`Insufficient elevation data for place: ${place.name}`);
return;
}
const elevation = elevationResponse.results[0].elevation || 10;
rotateCameraAround(
place.geometry.location,
place.geometry.viewport,
elevation
);
});
}
</script>
<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initAutocomplete"></script>
</body>
Polylinien und Labels zeichnen
In diesem Codebeispiel wird gezeigt, wie Sie einer Karte Polylinien und Labels hinzufügen. Sie können einer Karte Polylinien hinzufügen, um Wegbeschreibungen für Autos und Fußgänger anzuzeigen, Grundstücksgrenzen zu zeigen oder Fahrt- und Fußwege zu berechnen. Sie können Attribute auch abrufen, ohne die Szene zu rendern.
Sie können Nutzer auf eine ausgewählte Tour durch ein Viertel mitnehmen oder benachbarte Unterkünfte zeigen, die derzeit zum Verkauf stehen. Anschließend können Sie der Szene 3D‑Objekte wie Werbetafeln hinzufügen.
Sie könnten eine Reise zusammenfassen, die von Ihnen angesehenen Unterkünfte auflisten und diese Details in virtuellen Objekten anzeigen.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>CesiumJS 3D Tiles Polyline and Label Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link
href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
/>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer.
const viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: false,
baseLayerPicker: false,
requestRenderMode: true,
geocoder: false,
globe: false,
});
// Add 3D Tiles tileset.
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is required to display attributions as required.
showCreditsOnScreen: true,
})
);
// Draws a circle at the position, and a line from the previous position.
const drawPointAndLine = (position, prevPosition) => {
viewer.entities.removeAll();
if (prevPosition) {
viewer.entities.add({
polyline: {
positions: [prevPosition, position],
width: 3,
material: Cesium.Color.WHITE,
clampToGround: true,
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
},
});
}
viewer.entities.add({
position: position,
ellipsoid: {
radii: new Cesium.Cartesian3(1, 1, 1),
material: Cesium.Color.RED,
},
});
};
// Compute, draw, and display the position's height relative to the previous position.
var prevPosition;
const processHeights = (newPosition) => {
drawPointAndLine(newPosition, prevPosition);
const newHeight = Cesium.Cartographic.fromCartesian(newPosition).height;
let labelText = "Current altitude (meters above sea level):\n\t" + newHeight;
if (prevPosition) {
const prevHeight =
Cesium.Cartographic.fromCartesian(prevPosition).height;
labelText += "\nHeight from previous point (meters):\n\t" + Math.abs(newHeight - prevHeight);
}
viewer.entities.add({
position: newPosition,
label: {
text: labelText,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
pixelOffset: new Cesium.Cartesian2(0, -10),
showBackground: true,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
}
});
prevPosition = newPosition;
};
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (event) {
const earthPosition = viewer.scene.pickPosition(event.position);
if (Cesium.defined(earthPosition)) {
processHeights(earthPosition);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
</script>
</body>
Kameraumkreisung
In Cesium können Sie die Kamera um einen interessanten Punkt herum schwenken und Kollisionen mit Gebäuden vermeiden. Alternativ können Sie Gebäude transparent machen, wenn sich die Kamera durch sie bewegt.
Richten Sie die Kamera zuerst auf einen Punkt und erstellen Sie dann einen Kameraschwenk, um Ihr Asset zu präsentieren. Dazu können Sie die Funktion lookAtTransform
der Kamera mit einem Ereignis-Listener verwenden, wie in diesem Codebeispiel gezeigt.
// Lock the camera onto a point.
const center = Cesium.Cartesian3.fromRadians(
2.4213211833389243,
0.6171926869414084,
3626.0426275055174
);
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
viewer.scene.camera.lookAtTransform(
transform,
new Cesium.HeadingPitchRange(0, -Math.PI / 8, 2900)
);
// Orbit around this point.
viewer.clock.onTick.addEventListener(function (clock) {
viewer.scene.camera.rotateRight(0.005);
});
Weitere Informationen zur Kamerasteuerung finden Sie unter Kamera steuern.
Mit Cesium for Unreal arbeiten
So verwenden Sie das Cesium for Unreal-Plug-in mit der 3D Tiles API:
Installieren Sie das Cesium for Unreal-Plug-in.
Erstellen Sie ein neues Unreal-Projekt.
Stellen Sie eine Verbindung zur Photorealistic 3D Tiles API von Google her.
Öffnen Sie das Cesium-Fenster, indem Sie im Menü Cesium > Cesium auswählen.
Wählen Sie Leeres 3D-Kachel-Set aus.
Öffnen Sie im Outliner der Welt den Bereich Details, indem Sie diesen Cesium3D-Kachelsatz auswählen.
Ändern Sie die Quelle von Über Cesium-Ion in Über URL.
Legen Sie die URL als Google 3D Tiles-URL fest.
https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY
- Aktiviere Mitwirkende auf dem Bildschirm anzeigen, damit die Mitwirkenden korrekt angezeigt werden.
Dadurch wird die Welt geladen. Wenn Sie zu einem beliebigen LatLng-Wert wechseln möchten, wählen Sie im Bereich Outliner den Eintrag CesiumGeoreference aus und bearbeiten Sie dann im Bereich Details die Werte Ursprungsbreite/Längengrad/Höhe.
Mit Cesium for Unity arbeiten
So verwenden Sie fotorealistische Kacheln mit Cesium for Unity:
Erstellen Sie ein neues Unity-Projekt.
Fügen Sie im Bereich „Paketmanager“ (über Editor > Projekteinstellungen) eine neue Scoped Registry hinzu.
Name: Cäsium
URL: https://unity.pkg.cesium.com
Bereich(e): com.cesium.unity
Installieren Sie das Cesium for Unity-Paket.
Stellen Sie eine Verbindung zur Google Photorealistic 3D Tiles API her.
Öffnen Sie das Cesium-Fenster, indem Sie im Menü Cesium > Cesium auswählen.
Klicken Sie auf Leeres 3D-Kachel-Set.
Wählen Sie im linken Bereich unter Quelle in der Option Kachelsatzquelle die Option Über URL (anstelle von „Über Cesium Ion“) aus.
Legen Sie die URL auf die Google 3D Tiles-URL fest.
https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY
- Aktiviere Mitwirkende auf dem Bildschirm anzeigen, damit die Mitwirkenden korrekt angezeigt werden.
Dadurch wird die Welt geladen. Wenn Sie zu einer beliebigen LatLng-Position wechseln möchten, wählen Sie in der Szenenhierarchie das Element CesiumGeoreference aus und bearbeiten Sie dann im Inspection Tool die Koordinaten für Ursprungsbreite/-länge/-höhe.
Mit deck.gl arbeiten
deck.gl ist ein WebGL-gestütztes Open-Source-JavaScript-Framework für leistungsstarke, groß angelegte Datenvisualisierungen.
Attribution
Achten Sie darauf, dass Sie Datenangaben korrekt anzeigen. Extrahieren Sie dazu das Feld copyright
aus den glTF-Kacheln asset
und zeigen Sie es dann in der gerenderten Ansicht an. Weitere Informationen finden Sie unter Datenzuordnungen für Displayanzeigen.
Beispiele für deck.gl-Renderer
Einfaches Beispiel
Im folgenden Beispiel wird der deck.gl-Renderer initialisiert und dann ein Ort in 3D geladen. Ersetzen Sie in Ihrem Code YOUR_API_KEY durch Ihren tatsächlichen API-Schlüssel.
<!DOCTYPE html>
<html>
<head>
<title>deck.gl Photorealistic 3D Tiles example</title>
<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
<style>
body { margin: 0; padding: 0;}
#map { position: absolute; top: 0;bottom: 0;width: 100%;}
#credits { position: absolute; bottom: 0; right: 0; padding: 2px; font-size: 15px; color: white;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;}
</style>
</head>
<body>
<div id="map"></div>
<div id="credits"></div>
<script>
const GOOGLE_API_KEY = YOUR_API_KEY;
const TILESET_URL = `https://tile.googleapis.com/v1/3dtiles/root.json`;
const creditsElement = document.getElementById('credits');
new deck.DeckGL({
container: 'map',
initialViewState: {
latitude: 50.0890,
longitude: 14.4196,
zoom: 16,
bearing: 90,
pitch: 60,
height: 200
},
controller: {minZoom: 8},
layers: [
new deck.Tile3DLayer({
id: 'google-3d-tiles',
data: TILESET_URL,
loadOptions: {
fetch: {
headers: {
'X-GOOG-API-KEY': GOOGLE_API_KEY
}
}
},
onTilesetLoad: tileset3d => {
tileset3d.options.onTraversalComplete = selectedTiles => {
const credits = new Set();
selectedTiles.forEach(tile => {
const {copyright} = tile.content.gltf.asset;
copyright.split(';').forEach(credits.add, credits);
creditsElement.innerHTML = [...credits].join('; ');
});
return selectedTiles;
}
}
})
]
});
</script>
</body>
</html>
2D-Ebenen auf fotorealistischen 3D-Kacheln von Google visualisieren
Mit der deck.gl-TerrainExtension werden ansonsten 2D-Daten auf einer 3D-Oberfläche gerendert. Sie können beispielsweise das GeoJSON eines Gebäudegrundrisses über die Geometrie der fotorealistischen 3D-Kacheln legen.
Im folgenden Beispiel wird eine Gebäudeebene mit Polygonen dargestellt, die an die Oberfläche der fotorealistischen 3D-Kacheln angepasst sind.
<!DOCTYPE html>
<html>
<head>
<title>Google 3D tiles example</title>
<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
<style>
body { margin: 0; padding: 0;}
#map { position: absolute; top: 0;bottom: 0;width: 100%;}
#credits { position: absolute; bottom: 0; right: 0; padding: 2px; font-size: 15px; color: white;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;}
</style>
</head>
<body>
<div id="map"></div>
<div id="credits"></div>
<script>
const GOOGLE_API_KEY = YOUR_API_KEY;
const TILESET_URL = `https://tile.googleapis.com/v1/3dtiles/root.json`;
const BUILDINGS_URL = 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/google-3d-tiles/buildings.geojson'
const creditsElement = document.getElementById('credits');
const deckgl = new deck.DeckGL({
container: 'map',
initialViewState: {
latitude: 50.0890,
longitude: 14.4196,
zoom: 16,
bearing: 90,
pitch: 60,
height: 200
},
controller: true,
layers: [
new deck.Tile3DLayer({
id: 'google-3d-tiles',
data: TILESET_URL,
loadOptions: {
fetch: {
headers: {
'X-GOOG-API-KEY': GOOGLE_API_KEY
}
}
},
onTilesetLoad: tileset3d => {
tileset3d.options.onTraversalComplete = selectedTiles => {
const credits = new Set();
selectedTiles.forEach(tile => {
const {copyright} = tile.content.gltf.asset;
copyright.split(';').forEach(credits.add, credits);
creditsElement.innerHTML = [...credits].join('; ');
});
return selectedTiles;
}
},
operation: 'terrain+draw'
}),
new deck.GeoJsonLayer({
id: 'buildings',
// This dataset is created by CARTO, using other Open Datasets available. More info at: https://3dtiles.carto.com/#about.
data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/google-3d-tiles/buildings.geojson',
stroked: false,
filled: true,
getFillColor: ({properties}) => {
const {tpp} = properties;
// quantiles break
if (tpp < 0.6249)
return [254, 246, 181]
else if (tpp < 0.6780)
return [255, 194, 133]
else if (tpp < 0.8594)
return [250, 138, 118]
return [225, 83, 131]
},
opacity: 0.2,
extensions: [new deck._TerrainExtension()]
})
]
});
</script>
</body>
</html>