import { GeoCoordinates } from "@here/harp-geoutils" ; import { CopyrightElementHandler , MapView , MapViewEventNames } from "@here/harp-mapview" ; import { APIFormat , AuthenticationMethod , VectorTileDataSource } from "@here/harp-vectortile-datasource" ; import THREE = require ( "three" ) ; import { apikey , copyrightInfo } from "../config" ; /**
 * The example shows how to render map synchronously within your own render loop.
 * By default, when map is updated, changes will be rendered in the next animation frame.
 *
 * Setting `synchronousRendering` to `true` allows to control rendering process
 * and by calling `mapView.renderSync()`.
 *
 * ```typescript
 * [[include:harp_gl_rendering_synchronous_1.ts]]
 * ```
 *
 * `MapViewEventNames.Update` event fired when [[MapView]] requests for a redraw.
 * E.g.: Tiles asynchronously decoded and ready for rendering, labels animation, etc...
 *
 * Subscribe to this event, and call your `update` method.
 *
 * ```typescript
 * [[include:harp_gl_rendering_synchronous_2.ts]]
 * ```
 *
 * Implement your own render loop like in the example below.
 * With `mapView.renderSync()` you will immediately redraw the map scene.
 *
 * Make checks to avoid multiple redrawing at one frame.
 *
 * ```typescript
 * [[include:harp_gl_rendering_synchronous_3.ts]]
 * ```
 *
 */ export namespace SynchronousRendering { function initializeMapView ( id ) { const canvas = document . getElementById ( id ) as HTMLCanvasElement ; const map = new MapView ( { canvas , theme : "resources/berlin_tilezen_base.json" , synchronousRendering : true } ) ; map . renderLabels = false ; CopyrightElementHandler . install ( "copyrightNotice" , map ) ; map . resize ( window . innerWidth , window . innerHeight ) ; window . addEventListener ( "resize" , ( ) => { map . resize ( window . innerWidth , window . innerHeight ) ; } ) ; const omvDataSource = new VectorTileDataSource ( { baseUrl : "https://vector.hereapi.com/v2/vectortiles/base/mc" , apiFormat : APIFormat . XYZOMV , styleSetName : "tilezen" , authenticationCode : apikey , authenticationMethod : { method : AuthenticationMethod . QueryString , name : "apikey" } , copyrightInfo } ) ; map . addDataSource ( omvDataSource ) ; return map ; } class Popup { private canvas : HTMLCanvasElement ; private context : CanvasRenderingContext2D ; constructor ( text , private readonly coordinates ) { this . addHTMLElements ( text ) ; this . canvas = document . getElementById ( "popupLine" ) as HTMLCanvasElement ; this . context = this . canvas . getContext ( "2d" ) as CanvasRenderingContext2D ; this . canvas . width = window . innerWidth ; this . canvas . height = window . innerHeight ; window . addEventListener ( "resize" , ( ) => { this . canvas . width = window . innerWidth ; this . canvas . height = window . innerHeight ; } ) ; } addHTMLElements ( text ) { document . body . innerHTML += `
                <style>
                    #popupLine {
                        position: absolute;
                        border: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                        top: 0;
                        overflow: hidden;
                        z-index: 1;
                    }
                    .popup {
                        background: #000;
                        position: absolute;
                        right: 75%;
                        bottom: 75%;
                        color: #cceeff;
                        margin: 0 -1px -1px 0;
                        padding: 3px 10px;
                    }
                </style>
                <canvas id="popupLine"></canvas>
                <div class="popup">${ text }</div>
            ` ; } drawConnectionLine ( ) { if ( this . context ) { const width = this . canvas . width ; const height = this . canvas . height ; const position = mapView . projection . projectPoint ( this . coordinates , new THREE . Vector3 ( ) ) ; const vector = position . project ( mapView . camera ) ; vector . x = ( ( vector . x + 1 ) / 2 ) * width ; vector . y = ( - ( vector . y - 1 ) / 2 ) * height ; this . context . lineWidth = 2 ; this . context . clearRect ( 0 , 0 , width , height ) ; this . context . beginPath ( ) ; this . context . moveTo ( width / 4 , height / 4 ) ; this . context . lineTo ( vector . x , vector . y ) ; this . context . stroke ( ) ; } } } const popup = new Popup ( "One World Trade Center" , new GeoCoordinates ( 40.713 , - 74.013 , 541.3 ) ) ; const state = { target : new GeoCoordinates ( 40.707 , - 74.01 , 0 ) , zoomLevel : 16 , tilt : 35 , heading : 0 } ; const mapView = initializeMapView ( "mapCanvas" ) ; mapView . addEventListener ( MapViewEventNames . Update , requestDraw ) ; let requestDrawPending = false ; let drawing = false ; function requestDraw ( ) { if ( requestDrawPending ) { return ; } requestDrawPending = true ; requestAnimationFrame ( draw ) ; } function draw ( frameStartTime ) { if ( drawing ) { return ; } requestDrawPending = false ; drawing = true ; popup . drawConnectionLine ( ) ; state . heading += 0.1 ; mapView . lookAt ( state ) ; mapView . renderSync ( frameStartTime ) ; drawing = false ; } }