UNPKG

@here/harp-examples

Version:
153 lines (136 loc) 4.93 kB
/* * Copyright (C) 2019-2021 HERE Europe B.V. * Licensed under Apache 2.0, see full license in LICENSE * SPDX-License-Identifier: Apache-2.0 */ import { GeoCoordinates } from "@here/harp-geoutils"; import { MapView, MapViewEventNames, MapViewUtils } from "@here/harp-mapview"; import * as THREE from "three"; import { HelloWorldExample } from "./getting-started_hello-world_npm"; /** * This example builds on top of the [[HelloWorldExample]], so please consult that first for * any questions regarding basic setup of the map. * * This example shows how to use [[MapViewUtils]] to compute camera positions and orientations * and use them to animate them with [THREE.js](https://threejs.org/). * * [CatmulRomCurve3](https://threejs.org/docs/index.html#api/en/extras/curves/CatmullRomCurve3) is * used to interpolate between two camera positions and * [Quaternion](https://threejs.org/docs/index.html#api/en/math/Quaternion.slerp) is used to * interpolate between two camera orientations. */ export namespace ThreejsCameraAnimation { interface Location { target: GeoCoordinates; tilt: number; heading: number; distance: number; } let currentLocation = 0; const locations: Location[] = [ { // HERE Berlin target: new GeoCoordinates(52.5308419, 13.3850719), tilt: 0, heading: 0, distance: 1000 }, { // Museumsinsel Berlin target: new GeoCoordinates(52.5169285, 13.4010829), tilt: 45, heading: 45, distance: 300 }, { // TV-Tower Berlin target: new GeoCoordinates(52.520836, 13.409401, 300), tilt: 45, heading: 180, distance: 500 } ]; const message = document.createElement("div"); const threejsLink = "https://threejs.org"; message.innerHTML = `Example showing camera animations using <a href="${threejsLink}">three.js</a> <br> Tap our use left/right keys to change location`; message.style.cssText = ` color: #000; width: 80%; left: 50%; position: relative; margin-left: -40%; font-size: 15px; `; document.body.appendChild(message); function startTransition(mapView: MapView, location: Location) { const startPosition = mapView.camera.position.clone(); const startQuaternion = mapView.camera.quaternion.clone(); const targetPosition = MapViewUtils.getCameraPositionFromTargetCoordinates( location.target, location.distance, location.heading, location.tilt, mapView.projection ); const targetQuaternion = MapViewUtils.getCameraRotationAtTarget( mapView.projection, location.target, location.heading, location.tilt ); const startTime = Date.now(); const curve = new THREE.CatmullRomCurve3([startPosition, targetPosition]); const updateListener = () => { const time = Date.now(); let t = (time - startTime) / 1000; if (t >= 1) { t = 1; mapView.endAnimation(); mapView.removeEventListener(MapViewEventNames.Render, updateListener); } mapView.camera.position.copy(curve.getPoint(t)); const rotation = startQuaternion.clone().slerp(targetQuaternion, t); mapView.camera.quaternion.copy(rotation); mapView.camera.updateMatrixWorld(true); }; mapView.addEventListener(MapViewEventNames.Render, updateListener); mapView.beginAnimation(); } startTransition(HelloWorldExample.mapView, locations[0]); window.ontouchend = (ev: TouchEvent) => { const oldLocation = locations[currentLocation]; currentLocation++; if (currentLocation >= locations.length) { currentLocation = 0; } const newLocation = locations[currentLocation]; if (oldLocation === newLocation) { return; } startTransition(HelloWorldExample.mapView, newLocation); }; window.onkeydown = (ev: KeyboardEvent) => { const oldLocation = locations[currentLocation]; switch (ev.code) { case "ArrowLeft": currentLocation--; break; case "ArrowRight": currentLocation++; break; } if (currentLocation < 0) { currentLocation = locations.length - 1; } else if (currentLocation >= locations.length) { currentLocation = 0; } const newLocation = locations[currentLocation]; if (oldLocation === newLocation) { return; } startTransition(HelloWorldExample.mapView, newLocation); }; }