@@ -31,7 +31,7 @@ const Evented = require('../util/evented');
31
31
* @property {number } duration The animation's duration, measured in milliseconds.
32
32
* @property {Function } easing A function taking a time in the range 0..1 and returning a number where 0 is
33
33
* the initial state and 1 is the final state.
34
- * @property {PointLike } offset `x` and `y` coordinates representing the animation's origin of movement relative to the map's center .
34
+ * @property {PointLike } offset of the target center relative to real map container center at the end of animation .
35
35
* @property {boolean } animate If `false`, no animation will occur.
36
36
*/
37
37
@@ -77,8 +77,7 @@ class Camera extends Evented {
77
77
* @see [Move symbol with the keyboard](https://www.mapbox.com/mapbox-gl-js/example/rotating-controllable-marker/)
78
78
*/
79
79
setCenter ( center , eventData ) {
80
- this . jumpTo ( { center : center } , eventData ) ;
81
- return this ;
80
+ return this . jumpTo ( { center : center } , eventData ) ;
82
81
}
83
82
84
83
/**
@@ -94,9 +93,8 @@ class Camera extends Evented {
94
93
* @see [Navigate the map with game-like controls](https://www.mapbox.com/mapbox-gl-js/example/game-controls/)
95
94
*/
96
95
panBy ( offset , options , eventData ) {
97
- this . panTo ( this . transform . center ,
98
- util . extend ( { offset : Point . convert ( offset ) . mult ( - 1 ) } , options ) , eventData ) ;
99
- return this ;
96
+ offset = Point . convert ( offset ) . mult ( - 1 ) ;
97
+ return this . panTo ( this . transform . center , util . extend ( { offset} , options ) , eventData ) ;
100
98
}
101
99
102
100
/**
@@ -496,8 +494,13 @@ class Camera extends Evented {
496
494
easing : util . ease
497
495
} , options ) ;
498
496
497
+ if ( options . animate === false ) options . duration = 0 ;
498
+
499
+ if ( options . smoothEasing && options . duration !== 0 ) {
500
+ options . easing = this . _smoothOutEasing ( options . duration ) ;
501
+ }
502
+
499
503
const tr = this . transform ,
500
- offset = Point . convert ( options . offset ) ,
501
504
startZoom = this . getZoom ( ) ,
502
505
startBearing = this . getBearing ( ) ,
503
506
startPitch = this . getPitch ( ) ,
@@ -506,73 +509,56 @@ class Camera extends Evented {
506
509
bearing = 'bearing' in options ? this . _normalizeBearing ( options . bearing , startBearing ) : startBearing ,
507
510
pitch = 'pitch' in options ? + options . pitch : startPitch ;
508
511
509
- let toLngLat ,
510
- toPoint ;
512
+ const pointAtOffset = tr . centerPoint . add ( Point . convert ( options . offset ) ) ;
513
+ const locationAtOffset = tr . pointLocation ( pointAtOffset ) ;
514
+ const center = LngLat . convert ( options . center || locationAtOffset ) ;
515
+ const from = tr . project ( locationAtOffset ) ;
516
+ const delta = tr . project ( center ) . sub ( from ) ;
517
+ const finalScale = tr . zoomScale ( zoom - startZoom ) ;
511
518
512
- if ( 'center' in options ) {
513
- toLngLat = LngLat . convert ( options . center ) ;
514
- toPoint = tr . centerPoint . add ( offset ) ;
515
- } else if ( 'around' in options ) {
516
- toLngLat = LngLat . convert ( options . around ) ;
517
- toPoint = tr . locationPoint ( toLngLat ) ;
518
- } else {
519
- toPoint = tr . centerPoint . add ( offset ) ;
520
- toLngLat = tr . pointLocation ( toPoint ) ;
521
- }
522
-
523
- const fromPoint = tr . locationPoint ( toLngLat ) ;
519
+ let around , aroundPoint ;
524
520
525
- if ( options . animate === false ) options . duration = 0 ;
521
+ if ( options . around ) {
522
+ around = LngLat . convert ( options . around ) ;
523
+ aroundPoint = tr . locationPoint ( around ) ;
524
+ }
526
525
527
526
this . zooming = ( zoom !== startZoom ) ;
528
527
this . rotating = ( startBearing !== bearing ) ;
529
528
this . pitching = ( pitch !== startPitch ) ;
530
529
531
- if ( options . smoothEasing && options . duration !== 0 ) {
532
- options . easing = this . _smoothOutEasing ( options . duration ) ;
533
- }
534
-
535
- if ( ! options . noMoveStart ) {
536
- this . moving = true ;
537
- this . fire ( 'movestart' , eventData ) ;
538
- }
539
- if ( this . zooming ) {
540
- this . fire ( 'zoomstart' , eventData ) ;
541
- }
542
- if ( this . pitching ) {
543
- this . fire ( 'pitchstart' , eventData ) ;
544
- }
530
+ this . _prepareEase ( eventData , options . noMoveStart ) ;
545
531
546
532
clearTimeout ( this . _onEaseEnd ) ;
547
533
548
534
this . _ease ( function ( k ) {
549
535
if ( this . zooming ) {
550
536
tr . zoom = interpolate ( startZoom , zoom , k ) ;
551
537
}
552
-
553
538
if ( this . rotating ) {
554
539
tr . bearing = interpolate ( startBearing , bearing , k ) ;
555
540
}
556
-
557
541
if ( this . pitching ) {
558
542
tr . pitch = interpolate ( startPitch , pitch , k ) ;
559
543
}
560
544
561
- tr . setLocationAtPoint ( toLngLat , fromPoint . add ( toPoint . sub ( fromPoint ) . _mult ( k ) ) ) ;
562
-
563
- this . fire ( 'move' , eventData ) ;
564
- if ( this . zooming ) {
565
- this . fire ( 'zoom' , eventData ) ;
566
- }
567
- if ( this . rotating ) {
568
- this . fire ( 'rotate' , eventData ) ;
569
- }
570
- if ( this . pitching ) {
571
- this . fire ( 'pitch' , eventData ) ;
545
+ if ( around ) {
546
+ tr . setLocationAtPoint ( around , aroundPoint ) ;
547
+ } else {
548
+ const scale = tr . zoomScale ( tr . zoom - startZoom ) ;
549
+ const base = zoom > startZoom ?
550
+ Math . min ( 2 , finalScale ) :
551
+ Math . max ( 0.5 , finalScale ) ;
552
+ const speedup = Math . pow ( base , 1 - k ) ;
553
+ const newCenter = tr . unproject ( from . add ( delta . mult ( k * speedup ) ) . mult ( scale ) ) ;
554
+ tr . setLocationAtPoint ( tr . renderWorldCopies ? newCenter . wrap ( ) : newCenter , pointAtOffset ) ;
572
555
}
556
+
557
+ this . _fireMoveEvents ( eventData ) ;
558
+
573
559
} , ( ) => {
574
560
if ( options . delayEndEvents ) {
575
- this . _onEaseEnd = setTimeout ( this . _easeToEnd . bind ( this , eventData ) , options . delayEndEvents ) ;
561
+ this . _onEaseEnd = setTimeout ( ( ) => this . _easeToEnd ( eventData ) , options . delayEndEvents ) ;
576
562
} else {
577
563
this . _easeToEnd ( eventData ) ;
578
564
}
@@ -581,6 +567,33 @@ class Camera extends Evented {
581
567
return this ;
582
568
}
583
569
570
+ _prepareEase ( eventData , noMoveStart ) {
571
+ this . moving = true ;
572
+
573
+ if ( ! noMoveStart ) {
574
+ this . fire ( 'movestart' , eventData ) ;
575
+ }
576
+ if ( this . zooming ) {
577
+ this . fire ( 'zoomstart' , eventData ) ;
578
+ }
579
+ if ( this . pitching ) {
580
+ this . fire ( 'pitchstart' , eventData ) ;
581
+ }
582
+ }
583
+
584
+ _fireMoveEvents ( eventData ) {
585
+ this . fire ( 'move' , eventData ) ;
586
+ if ( this . zooming ) {
587
+ this . fire ( 'zoom' , eventData ) ;
588
+ }
589
+ if ( this . rotating ) {
590
+ this . fire ( 'rotate' , eventData ) ;
591
+ }
592
+ if ( this . pitching ) {
593
+ this . fire ( 'pitch' , eventData ) ;
594
+ }
595
+ }
596
+
584
597
_easeToEnd ( eventData ) {
585
598
const wasZooming = this . zooming ;
586
599
const wasPitching = this . pitching ;
@@ -596,7 +609,6 @@ class Camera extends Evented {
596
609
this . fire ( 'pitchend' , eventData ) ;
597
610
}
598
611
this . fire ( 'moveend' , eventData ) ;
599
-
600
612
}
601
613
602
614
/**
@@ -671,16 +683,19 @@ class Camera extends Evented {
671
683
} , options ) ;
672
684
673
685
const tr = this . transform ,
674
- offset = Point . convert ( options . offset ) ,
675
686
startZoom = this . getZoom ( ) ,
676
687
startBearing = this . getBearing ( ) ,
677
688
startPitch = this . getPitch ( ) ;
678
689
679
- const center = 'center' in options ? LngLat . convert ( options . center ) : this . getCenter ( ) ;
680
690
const zoom = 'zoom' in options ? + options . zoom : startZoom ;
681
691
const bearing = 'bearing' in options ? this . _normalizeBearing ( options . bearing , startBearing ) : startBearing ;
682
692
const pitch = 'pitch' in options ? + options . pitch : startPitch ;
683
693
694
+ const scale = tr . zoomScale ( zoom - startZoom ) ;
695
+ const pointAtOffset = tr . centerPoint . add ( Point . convert ( options . offset ) ) ;
696
+ const locationAtOffset = tr . pointLocation ( pointAtOffset ) ;
697
+ const center = LngLat . convert ( options . center || locationAtOffset ) ;
698
+
684
699
// If a path crossing the antimeridian would be shorter, extend the final coordinate so that
685
700
// interpolating between the two endpoints will cross it.
686
701
if ( tr . renderWorldCopies && Math . abs ( tr . center . lng ) + Math . abs ( center . lng ) > 180 ) {
@@ -691,9 +706,8 @@ class Camera extends Evented {
691
706
}
692
707
}
693
708
694
- const scale = tr . zoomScale ( zoom - startZoom ) ,
695
- from = tr . point ,
696
- to = 'center' in options ? tr . project ( center ) . sub ( offset . div ( scale ) ) : from ;
709
+ const from = tr . project ( locationAtOffset ) ;
710
+ const delta = tr . project ( center ) . sub ( from ) ;
697
711
698
712
let rho = options . curve ;
699
713
@@ -703,7 +717,7 @@ class Camera extends Evented {
703
717
w1 = w0 / scale ,
704
718
// Length of the flight path as projected onto the ground plane, measured in pixels from
705
719
// the world image origin at the initial scale.
706
- u1 = to . sub ( from ) . mag ( ) ;
720
+ u1 = delta . mag ( ) ;
707
721
708
722
if ( 'minZoom' in options ) {
709
723
const minZoom = util . clamp ( Math . min ( options . minZoom , startZoom , zoom ) , tr . minZoom , tr . maxZoom ) ;
@@ -769,26 +783,17 @@ class Camera extends Evented {
769
783
options . duration = 1000 * S / V ;
770
784
}
771
785
772
- this . moving = true ;
773
786
this . zooming = true ;
774
- if ( startBearing !== bearing ) this . rotating = true ;
775
- if ( startPitch !== pitch ) this . pitching = true ;
787
+ this . rotating = ( startBearing !== bearing ) ;
788
+ this . pitching = ( pitch !== startPitch ) ;
776
789
777
- this . fire ( 'movestart' , eventData ) ;
778
- this . fire ( 'zoomstart' , eventData ) ;
779
- if ( this . pitching ) this . fire ( 'pitchstart' , eventData ) ;
790
+ this . _prepareEase ( eventData , false ) ;
780
791
781
792
this . _ease ( function ( k ) {
782
793
// s: The distance traveled along the flight path, measured in ρ-screenfuls.
783
- const s = k * S ,
784
- us = u ( s ) ;
785
-
794
+ const s = k * S ;
786
795
const scale = 1 / w ( s ) ;
787
796
tr . zoom = startZoom + tr . scaleZoom ( scale ) ;
788
- tr . center = tr . unproject ( from . add ( to . sub ( from ) . mult ( us ) ) . mult ( scale ) ) ;
789
- if ( tr . renderWorldCopies ) {
790
- tr . center = tr . center . wrap ( ) ;
791
- }
792
797
793
798
if ( this . rotating ) {
794
799
tr . bearing = interpolate ( startBearing , bearing , k ) ;
@@ -797,25 +802,12 @@ class Camera extends Evented {
797
802
tr . pitch = interpolate ( startPitch , pitch , k ) ;
798
803
}
799
804
800
- this . fire ( 'move' , eventData ) ;
801
- this . fire ( 'zoom' , eventData ) ;
802
- if ( this . rotating ) {
803
- this . fire ( 'rotate' , eventData ) ;
804
- }
805
- if ( this . pitching ) {
806
- this . fire ( 'pitch' , eventData ) ;
807
- }
808
- } , function ( ) {
809
- const wasPitching = this . pitching ;
810
- this . moving = false ;
811
- this . zooming = false ;
812
- this . rotating = false ;
813
- this . pitching = false ;
814
-
815
- if ( wasPitching ) this . fire ( 'pitchend' , eventData ) ;
816
- this . fire ( 'zoomend' , eventData ) ;
817
- this . fire ( 'moveend' , eventData ) ;
818
- } , options ) ;
805
+ const newCenter = tr . unproject ( from . add ( delta . mult ( u ( s ) ) ) . mult ( scale ) ) ;
806
+ tr . setLocationAtPoint ( tr . renderWorldCopies ? newCenter . wrap ( ) : newCenter , pointAtOffset ) ;
807
+
808
+ this . _fireMoveEvents ( eventData ) ;
809
+
810
+ } , ( ) => this . _easeToEnd ( eventData ) , options ) ;
819
811
820
812
return this ;
821
813
}
0 commit comments