@@ -602,6 +602,45 @@ describe('Test relayout on polar subplots:', function() {
602
602
. catch ( failTest )
603
603
. then ( done ) ;
604
604
} ) ;
605
+
606
+ it ( 'should be able to relayout *gridshape*' , function ( done ) {
607
+ var gd = createGraphDiv ( ) ;
608
+
609
+ // check number of arcs ('A') or lines ('L') in svg paths
610
+ function _assert ( msg , exp ) {
611
+ var sp = d3 . select ( gd ) . select ( 'g.polar' ) ;
612
+
613
+ function assertLetterCount ( query ) {
614
+ var d = sp . select ( query ) . attr ( 'd' ) ;
615
+ var re = new RegExp ( exp . letter , 'g' ) ;
616
+ var actual = ( d . match ( re ) || [ ] ) . length ;
617
+ expect ( actual ) . toBe ( exp . cnt , msg + ' - ' + query ) ;
618
+ }
619
+
620
+ assertLetterCount ( '.plotbg > path' ) ;
621
+ assertLetterCount ( '.radial-grid > .x > path' ) ;
622
+ assertLetterCount ( '.angular-line > path' ) ;
623
+ }
624
+
625
+ Plotly . plot ( gd , [ {
626
+ type : 'scatterpolar' ,
627
+ r : [ 1 , 2 , 3 , 2 , 3 , 1 ] ,
628
+ theta : [ 'a' , 'b' , 'c' , 'd' , 'e' , 'a' ]
629
+ } ] )
630
+ . then ( function ( ) {
631
+ _assert ( 'base' , { letter : 'A' , cnt : 2 } ) ;
632
+ return Plotly . relayout ( gd , 'polar.gridshape' , 'linear' ) ;
633
+ } )
634
+ . then ( function ( ) {
635
+ _assert ( 'relayout -> linear' , { letter : 'L' , cnt : 5 } ) ;
636
+ return Plotly . relayout ( gd , 'polar.gridshape' , 'circular' ) ;
637
+ } )
638
+ . then ( function ( ) {
639
+ _assert ( 'relayout -> circular' , { letter : 'A' , cnt : 2 } ) ;
640
+ } )
641
+ . catch ( failTest )
642
+ . then ( done ) ;
643
+ } ) ;
605
644
} ) ;
606
645
607
646
describe ( 'Test polar interactions:' , function ( ) {
@@ -1038,3 +1077,142 @@ describe('Test polar interactions:', function() {
1038
1077
. then ( done ) ;
1039
1078
} ) ;
1040
1079
} ) ;
1080
+
1081
+ describe ( 'Test polar *gridshape linear* interactions' , function ( ) {
1082
+ var gd ;
1083
+
1084
+ beforeEach ( function ( ) {
1085
+ jasmine . DEFAULT_TIMEOUT_INTERVAL = 5000 ;
1086
+ gd = createGraphDiv ( ) ;
1087
+ } ) ;
1088
+
1089
+ afterEach ( destroyGraphDiv ) ;
1090
+
1091
+ it ( 'should snap radial axis rotation to polygon vertex angles' , function ( done ) {
1092
+ var dragPos0 = [ 150 , 25 ] ;
1093
+ var dragPos1 = [ 316 , 82 ] ;
1094
+ var evtCnt = 0 ;
1095
+
1096
+ // use 'special' drag method - as we need two mousemove events
1097
+ // to activate the radial drag mode
1098
+ function _drag ( p0 , dp ) {
1099
+ var node = d3 . select ( '.polar > .draglayer > .radialdrag' ) . node ( ) ;
1100
+ return drag ( node , dp [ 0 ] , dp [ 1 ] , null , p0 [ 0 ] , p0 [ 1 ] , 2 ) ;
1101
+ }
1102
+
1103
+ function _assert ( msg , angle ) {
1104
+ expect ( gd . _fullLayout . polar . radialaxis . angle )
1105
+ . toBeCloseTo ( angle , 1 , msg + ' - angle' ) ;
1106
+ }
1107
+
1108
+ Plotly . plot ( gd , [ {
1109
+ type : 'scatterpolar' ,
1110
+ // octogons have nice angles
1111
+ r : [ 1 , 2 , 3 , 2 , 3 , 1 , 2 , 1 , 2 ] ,
1112
+ theta : [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'a' ]
1113
+ } ] , {
1114
+ polar : {
1115
+ gridshape : 'linear' ,
1116
+ angularaxis : { direction : 'clockwise' } ,
1117
+ radialaxis : { angle : 90 }
1118
+ } ,
1119
+ width : 400 ,
1120
+ height : 400 ,
1121
+ margin : { l : 50 , t : 50 , b : 50 , r : 50 } ,
1122
+ // to avoid dragging on hover labels
1123
+ hovermode : false
1124
+ } )
1125
+ . then ( function ( ) {
1126
+ gd . on ( 'plotly_relayout' , function ( ) { evtCnt ++ ; } ) ;
1127
+ } )
1128
+ . then ( function ( ) { _assert ( 'base' , 90 ) ; } )
1129
+ . then ( function ( ) { return _drag ( dragPos0 , [ 100 , 50 ] ) ; } )
1130
+ . then ( function ( ) { _assert ( 'rotate right' , 45 ) ; } )
1131
+ . then ( function ( ) { return _drag ( dragPos1 , [ 20 , 20 ] ) ; } )
1132
+ . then ( function ( ) { _assert ( 'rotate right, snapped back' , 45 ) ; } )
1133
+ . then ( function ( ) { return _drag ( dragPos1 , [ - 100 , - 50 ] ) ; } )
1134
+ . then ( function ( ) { _assert ( 'rotate left' , 90 ) ; } )
1135
+ . then ( function ( ) { expect ( evtCnt ) . toBe ( 3 ) ; } )
1136
+ . catch ( failTest )
1137
+ . then ( done ) ;
1138
+ } ) ;
1139
+
1140
+ it ( 'should rotate all non-symmetrical layers on angular drag' , function ( done ) {
1141
+ var dragCoverNode ;
1142
+ var p1 ;
1143
+
1144
+ var layersRotateFromZero = [ '.plotbg > path' , '.radial-grid' , '.angular-line > path' ] ;
1145
+ var layersRotateFromRadialAxis = [ '.radial-axis' , '.radial-line > line' ] ;
1146
+
1147
+ function _assertTransformRotate ( msg , query , rot ) {
1148
+ var sp = d3 . select ( gd ) . select ( 'g.polar' ) ;
1149
+ var t = sp . select ( query ) . attr ( 'transform' ) ;
1150
+ var rotate = ( t . split ( 'rotate(' ) [ 1 ] || '' ) . split ( ')' ) [ 0 ] ;
1151
+ if ( rot === null ) {
1152
+ expect ( rotate ) . toBe ( '' , msg + ' - ' + query ) ;
1153
+ } else {
1154
+ expect ( Number ( rotate ) ) . toBeCloseTo ( rot , 1 , msg + ' - ' + query ) ;
1155
+ }
1156
+ }
1157
+
1158
+ function _dragStart ( p0 , dp ) {
1159
+ var node = d3 . select ( '.polar > .draglayer > .angulardrag' ) . node ( ) ;
1160
+ mouseEvent ( 'mousemove' , p0 [ 0 ] , p0 [ 1 ] , { element : node } ) ;
1161
+ mouseEvent ( 'mousedown' , p0 [ 0 ] , p0 [ 1 ] , { element : node } ) ;
1162
+
1163
+ var promise = drag . waitForDragCover ( ) . then ( function ( dcn ) {
1164
+ dragCoverNode = dcn ;
1165
+ p1 = [ p0 [ 0 ] + dp [ 0 ] , p0 [ 1 ] + dp [ 1 ] ] ;
1166
+ mouseEvent ( 'mousemove' , p1 [ 0 ] , p1 [ 1 ] , { element : dragCoverNode } ) ;
1167
+ } ) ;
1168
+ return promise ;
1169
+ }
1170
+
1171
+ function _assertAndDragEnd ( msg , exp ) {
1172
+ layersRotateFromZero . forEach ( function ( q ) {
1173
+ _assertTransformRotate ( msg , q , exp . fromZero ) ;
1174
+ } ) ;
1175
+ layersRotateFromRadialAxis . forEach ( function ( q ) {
1176
+ _assertTransformRotate ( msg , q , exp . fromRadialAxis ) ;
1177
+ } ) ;
1178
+
1179
+ mouseEvent ( 'mouseup' , p1 [ 0 ] , p1 [ 1 ] , { element : dragCoverNode } ) ;
1180
+ return drag . waitForDragCoverRemoval ( ) ;
1181
+ }
1182
+
1183
+ Plotly . plot ( gd , [ {
1184
+ type : 'scatterpolar' ,
1185
+ r : [ 1 , 2 , 3 , 2 , 3 ] ,
1186
+ theta : [ 'a' , 'b' , 'c' , 'd' , 'e' ]
1187
+ } ] , {
1188
+ polar : {
1189
+ gridshape : 'linear' ,
1190
+ angularaxis : { direction : 'clockwise' } ,
1191
+ radialaxis : { angle : 90 }
1192
+ } ,
1193
+ width : 400 ,
1194
+ height : 400 ,
1195
+ margin : { l : 50 , t : 50 , b : 50 , r : 50 }
1196
+ } )
1197
+ . then ( function ( ) {
1198
+ layersRotateFromZero . forEach ( function ( q ) {
1199
+ _assertTransformRotate ( 'base' , q , null ) ;
1200
+ } ) ;
1201
+ layersRotateFromRadialAxis . forEach ( function ( q ) {
1202
+ _assertTransformRotate ( 'base' , q , - 90 ) ;
1203
+ } ) ;
1204
+ } )
1205
+ . then ( function ( ) { return _dragStart ( [ 150 , 20 ] , [ 30 , 30 ] ) ; } )
1206
+ . then ( function ( ) {
1207
+ return _assertAndDragEnd ( 'rotate clockwise' , {
1208
+ fromZero : 7.2 ,
1209
+ fromRadialAxis : - 82.8
1210
+ } ) ;
1211
+ } )
1212
+ . catch ( failTest )
1213
+ . then ( done ) ;
1214
+ } ) ;
1215
+
1216
+ // - test handle position an
1217
+
1218
+ } ) ;
0 commit comments