UNPKG

panolens

Version:
249 lines (185 loc) 5.98 kB
import { TextureLoader } from './TextureLoader'; /** * @classdesc Google Street View Loader * @constructor * @param {object} parameters */ function GoogleStreetviewLoader ( parameters = {} ) { this._parameters = parameters; this._zoom = null; this._panoId = null; this._panoClient = new google.maps.StreetViewService(); this._count = 0; this._total = 0; this._canvas = []; this._ctx = []; this._wc = 0; this._hc = 0; this.result = null; this.rotation = 0; this.copyright = ''; this.onSizeChange = null; this.onPanoramaLoad = null; this.levelsW = [ 1, 2, 4, 7, 13, 26 ]; this.levelsH = [ 1, 1, 2, 4, 7, 13 ]; this.widths = [ 416, 832, 1664, 3328, 6656, 13312 ]; this.heights = [ 416, 416, 832, 1664, 3328, 6656 ]; this.maxW = 6656; this.maxH = 6656; let gl; try { const canvas = document.createElement( 'canvas' ); gl = canvas.getContext( 'experimental-webgl' ); if( !gl ) { gl = canvas.getContext( 'webgl' ); } } catch ( error ) { } this.maxW = Math.max( gl.getParameter( gl.MAX_TEXTURE_SIZE ), this.maxW ); this.maxH = Math.max( gl.getParameter( gl.MAX_TEXTURE_SIZE ), this.maxH ); } Object.assign( GoogleStreetviewLoader.prototype, { constructor: GoogleStreetviewLoader, /** * Set progress * @param {number} loaded * @param {number} total * @memberOf GoogleStreetviewLoader * @instance */ setProgress: function ( loaded, total ) { if ( this.onProgress ) { this.onProgress( { loaded: loaded, total: total } ); } }, /** * Adapt texture to zoom * @memberOf GoogleStreetviewLoader * @instance */ adaptTextureToZoom: function () { const w = this.widths [ this._zoom ]; const h = this.heights[ this._zoom ]; const maxW = this.maxW; const maxH = this.maxH; this._wc = Math.ceil( w / maxW ); this._hc = Math.ceil( h / maxH ); for( let y = 0; y < this._hc; y++ ) { for( let x = 0; x < this._wc; x++ ) { const c = document.createElement( 'canvas' ); if( x < ( this._wc - 1 ) ) c.width = maxW; else c.width = w - ( maxW * x ); if( y < ( this._hc - 1 ) ) c.height = maxH; else c.height = h - ( maxH * y ); this._canvas.push( c ); this._ctx.push( c.getContext( '2d' ) ); } } }, /** * Compose from tile * @param {number} x * @param {number} y * @param {*} texture * @memberOf GoogleStreetviewLoader * @instance */ composeFromTile: function ( x, y, texture ) { const maxW = this.maxW; const maxH = this.maxH; x *= 512; y *= 512; const px = Math.floor( x / maxW ); const py = Math.floor( y / maxH ); x -= px * maxW; y -= py * maxH; this._ctx[ py * this._wc + px ].drawImage( texture, 0, 0, texture.width, texture.height, x, y, 512, 512 ); this.progress(); }, /** * Progress * @memberOf GoogleStreetviewLoader * @instance */ progress: function() { this._count++; this.setProgress( this._count, this._total ); if ( this._count === this._total) { this.canvas = this._canvas; this.panoId = this._panoId; this.zoom = this._zoom; if ( this.onPanoramaLoad ) { this.onPanoramaLoad( this._canvas[ 0 ] ); } } }, /** * Compose panorama * @memberOf GoogleStreetviewLoader * @instance */ composePanorama: function () { this.setProgress( 0, 1 ); const w = this.levelsW[ this._zoom ]; const h = this.levelsH[ this._zoom ]; const self = this; this._count = 0; this._total = w * h; const { useWebGL } = this._parameters; for( let y = 0; y < h; y++ ) { for( let x = 0; x < w; x++ ) { const url = 'https://geo0.ggpht.com/cbk?cb_client=maps_sv.tactile&authuser=0&hl=en&output=tile&zoom=' + this._zoom + '&x=' + x + '&y=' + y + '&panoid=' + this._panoId + '&nbt&fover=2'; ( function( x, y ) { if( useWebGL ) { const texture = TextureLoader.load( url, null, function() { self.composeFromTile( x, y, texture ); } ); } else { const img = new Image(); img.addEventListener( 'load', function() { self.composeFromTile( x, y, this ); } ); img.crossOrigin = ''; img.src = url; } } )( x, y ); } } }, /** * Load * @param {string} panoid * @memberOf GoogleStreetviewLoader * @instance */ load: function ( panoid ) { this.loadPano( panoid ); }, /** * Load panorama * @param {string} id * @memberOf GoogleStreetviewLoader * @instance */ loadPano: function( id ) { const self = this; this._panoClient.getPanoramaById( id, function (result, status) { if (status === google.maps.StreetViewStatus.OK) { self.result = result; self.copyright = result.copyright; self._panoId = result.location.pano; self.composePanorama(); } }); }, /** * Set zoom level * @param {number} z * @memberOf GoogleStreetviewLoader * @instance */ setZoom: function( z ) { this._zoom = z; this.adaptTextureToZoom(); } } ); export { GoogleStreetviewLoader };