@@ -3,7 +3,7 @@ import Point from '../geo/Point';
33import Coordinate from '../geo/Coordinate' ;
44import * as mat4 from '../core/util/mat4' ;
55import { subtract , add , scale , normalize , dot , set , distance } from '../core/util/vec3' ;
6- import { clamp , interpolate , isNumber , isNil , wrap } from '../core/util' ;
6+ import { clamp , interpolate , isNumber , isNil , wrap , toDegree , toRadian } from '../core/util' ;
77import { applyMatrix , matrixToQuaternion , quaternionToMatrix , lookAt , setPosition } from '../core/util/math' ;
88import Browser from '../core/Browser' ;
99
@@ -206,6 +206,149 @@ Map.include(/** @lends Map.prototype */{
206206 return this ;
207207 } ,
208208
209+ /**
210+ * set camera movements
211+ * @param {Array } frameOptions
212+ * [{ center: [114, 32], zoom: 14, pitch: 45, bearing: 90, timestamp: 0 }]
213+ * @param {Object } extraOptions
214+ * { autoRotate: true }
215+ */
216+ setCameraMovements ( frameOptions , extraOptions ) {
217+ if ( ! Array . isArray ( frameOptions ) || ! frameOptions . length ) {
218+ return this ;
219+ }
220+ this . setView ( {
221+ center : frameOptions [ 0 ] . center ,
222+ zoom : frameOptions [ 0 ] . zoom ,
223+ pitch : frameOptions [ 0 ] . pitch ,
224+ bearing : frameOptions [ 0 ] . bearing
225+ } ) ;
226+ if ( frameOptions . length === 1 ) return this ;
227+ let index = 1 ;
228+ let onFrame = frame => {
229+ if ( frame . state . playState === 'finished' ) {
230+ index ++ ;
231+ if ( index === frameOptions . length - 1 ) onFrame = null ;
232+ const frameOption = frameOptions [ index ] ;
233+ frameOption . duration = frameOption . timestamp - frameOptions [ index - 1 ] . timestamp ;
234+ if ( extraOptions && extraOptions . autoRotate ) {
235+ frameOption . bearing = calculateBearing ( frameOptions [ index - 1 ] . center , frameOption . center ) ;
236+ }
237+ this . _setCameraMovement ( frameOption , onFrame ) ;
238+ }
239+ } ;
240+ if ( frameOptions . length === 2 ) onFrame = null ;
241+ const currentBearing = this . getBearing ( ) ;
242+ this . _setCameraMovement ( {
243+ bearing : currentBearing ,
244+ ...frameOptions [ index ] ,
245+ duration : frameOptions [ index ] . timestamp - frameOptions [ index - 1 ] . timestamp
246+ } , onFrame ) ;
247+ const play = ( ) => {
248+ this . _animPlayer . play ( ) ;
249+ } ;
250+ const pause = ( ) => {
251+ this . _animPlayer . pause ( ) ;
252+ } ;
253+ const cancel = ( ) => {
254+ this . _animPlayer . cancel ( ) ;
255+ } ;
256+ const finish = ( ) => {
257+ this . _animPlayer . finish ( ) ;
258+ } ;
259+ const reverse = ( ) => {
260+ this . _animPlayer . reverse ( ) ;
261+ } ;
262+ return {
263+ play,
264+ pause,
265+ cancel,
266+ finish,
267+ reverse
268+ } ;
269+ } ,
270+
271+ _setCameraMovement ( frameOption , frame ) {
272+ this . animateTo ( {
273+ zoom : frameOption . zoom ,
274+ center : frameOption . center ,
275+ pitch : frameOption . pitch ,
276+ bearing : frameOption . bearing
277+ } , {
278+ duration : frameOption . duration ,
279+ easing : 'out'
280+ } , frame ) ;
281+ } ,
282+
283+ /**
284+ * Set camera position
285+ * @param {Object } params
286+ * @property {Array } position
287+ * @property {Number } pitch
288+ * @property {Number } bearing
289+ */
290+ setCameraPosition ( params ) {
291+ const { position, pitch, bearing } = params ;
292+
293+ const cameraAltitude = position [ 2 ] * this . _meterToGLPoint ;
294+
295+ const centerAltitude = this . centerAltitude || 0 ;
296+ const centerPointZ = centerAltitude * this . _meterToGLPoint ;
297+
298+ const cz = cameraAltitude - centerPointZ ;
299+
300+ const pitchRadian = pitch * RADIAN ;
301+
302+ const cameraToGroundDistance = cz / Math . cos ( pitchRadian ) ;
303+
304+ const dist = Math . sin ( pitchRadian ) * cameraToGroundDistance ;
305+
306+ const cameraToCenterDistance = cameraToGroundDistance + centerPointZ ;
307+
308+ const zoom = this . _getZoomFromCameraToCenterDistance ( cameraToCenterDistance ) ;
309+
310+ const wrapBearing = wrap ( bearing , - 180 , 180 ) ;
311+ const bearingRadian = wrapBearing * RADIAN ;
312+
313+ const glRes = this . getGLRes ( ) ;
314+ const tempCoord = new Coordinate ( position [ 0 ] , position [ 1 ] ) ;
315+ const tempPoint = this . coordToPointAtRes ( tempCoord , glRes ) ;
316+ const point = new Point ( 0 , 0 ) ;
317+ point . x = tempPoint . x + dist * Math . sin ( bearingRadian ) ;
318+ point . y = tempPoint . y + dist * Math . cos ( bearingRadian ) ;
319+
320+ const prjCenter = this . _pointToPrjAtRes ( point , this . getGLRes ( ) ) ;
321+ this . _setPrjCenter ( prjCenter ) ;
322+
323+ this . setView ( {
324+ bearing,
325+ pitch,
326+ zoom
327+ } ) ;
328+
329+ return this ;
330+ } ,
331+
332+ _getZoomFromCameraToCenterDistance ( distance ) {
333+ const ratio = this . _getFovRatio ( ) ;
334+ const scale = distance * ratio * 2 / ( this . height || 1 ) * this . getGLRes ( ) ;
335+ const resolutions = this . _getResolutions ( ) ;
336+ let z = 0 ;
337+ for ( z ; z < resolutions . length - 1 ; z ++ ) {
338+ if ( resolutions [ z ] === scale ) {
339+ return z ;
340+ } else if ( resolutions [ z + 1 ] === scale ) {
341+ return z + 1 ;
342+ } else if ( scale < resolutions [ z ] && scale > resolutions [ z + 1 ] ) {
343+ z = ( scale - resolutions [ z ] ) / ( resolutions [ z + 1 ] - resolutions [ z ] ) + z ;
344+ return z - 1 ;
345+ } else {
346+ continue ;
347+ }
348+ }
349+ return z ;
350+ } ,
351+
209352 /**
210353 * Whether the map is rotating or tilting.
211354 * @return {Boolean }
@@ -754,3 +897,15 @@ Map.include(/** @lends Map.prototype */{
754897function createMat4 ( ) {
755898 return mat4 . identity ( new Array ( 16 ) ) ;
756899}
900+
901+ function calculateBearing ( start , end ) {
902+ const lon1 = toRadian ( start [ 0 ] ) ;
903+ const lon2 = toRadian ( end [ 0 ] ) ;
904+ const lat1 = toRadian ( start [ 1 ] ) ;
905+ const lat2 = toRadian ( end [ 1 ] ) ;
906+ const a = Math . sin ( lon2 - lon1 ) * Math . cos ( lat2 ) ;
907+ const b =
908+ Math . cos ( lat1 ) * Math . sin ( lat2 ) -
909+ Math . sin ( lat1 ) * Math . cos ( lat2 ) * Math . cos ( lon2 - lon1 ) ;
910+ return toDegree ( Math . atan2 ( a , b ) ) ;
911+ }
0 commit comments