@@ -2738,9 +2738,11 @@ exports.react = function(gd, data, layout, config) {
2738
2738
var newFullData = gd . _fullData ;
2739
2739
var newFullLayout = gd . _fullLayout ;
2740
2740
var immutable = newFullLayout . datarevision === undefined ;
2741
+ var transition = newFullLayout . transition ;
2741
2742
2742
- var restyleFlags = diffData ( gd , oldFullData , newFullData , immutable ) ;
2743
- var relayoutFlags = diffLayout ( gd , oldFullLayout , newFullLayout , immutable ) ;
2743
+ var relayoutFlags = diffLayout ( gd , oldFullLayout , newFullLayout , immutable , transition ) ;
2744
+ var newDataRevision = relayoutFlags . newDataRevision ;
2745
+ var restyleFlags = diffData ( gd , oldFullData , newFullData , immutable , transition , newDataRevision ) ;
2744
2746
2745
2747
// TODO: how to translate this part of relayout to Plotly.react?
2746
2748
// // Setting width or height to null must reset the graph's width / height
@@ -2770,7 +2772,19 @@ exports.react = function(gd, data, layout, config) {
2770
2772
seq . push ( addFrames ) ;
2771
2773
}
2772
2774
2773
- if ( restyleFlags . fullReplot || relayoutFlags . layoutReplot || configChanged ) {
2775
+ // Transition pathway,
2776
+ // only used when 'transition' is set by user and
2777
+ // when at least one animatable attribute has changed,
2778
+ // N.B. config changed aren't animatable
2779
+ if ( newFullLayout . transition && ! configChanged && ( restyleFlags . anim || relayoutFlags . anim ) ) {
2780
+ Plots . doCalcdata ( gd ) ;
2781
+ subroutines . doAutoRangeAndConstraints ( gd ) ;
2782
+
2783
+ seq . push ( function ( ) {
2784
+ return Plots . transitionFromReact ( gd , restyleFlags , relayoutFlags , oldFullLayout ) ;
2785
+ } ) ;
2786
+ }
2787
+ else if ( restyleFlags . fullReplot || relayoutFlags . layoutReplot || configChanged ) {
2774
2788
gd . _fullLayout . _skipDefaults = true ;
2775
2789
seq . push ( exports . plot ) ;
2776
2790
}
@@ -2823,8 +2837,10 @@ exports.react = function(gd, data, layout, config) {
2823
2837
2824
2838
} ;
2825
2839
2826
- function diffData ( gd , oldFullData , newFullData , immutable ) {
2827
- if ( oldFullData . length !== newFullData . length ) {
2840
+ function diffData ( gd , oldFullData , newFullData , immutable , transition , newDataRevision ) {
2841
+ var sameTraceLength = oldFullData . length === newFullData . length ;
2842
+
2843
+ if ( ! transition && ! sameTraceLength ) {
2828
2844
return {
2829
2845
fullReplot : true ,
2830
2846
calc : true
@@ -2833,6 +2849,9 @@ function diffData(gd, oldFullData, newFullData, immutable) {
2833
2849
2834
2850
var flags = editTypes . traceFlags ( ) ;
2835
2851
flags . arrays = { } ;
2852
+ flags . nChanges = 0 ;
2853
+ flags . nChangesAnim = 0 ;
2854
+
2836
2855
var i , trace ;
2837
2856
2838
2857
function getTraceValObject ( parts ) {
@@ -2843,31 +2862,41 @@ function diffData(gd, oldFullData, newFullData, immutable) {
2843
2862
getValObject : getTraceValObject ,
2844
2863
flags : flags ,
2845
2864
immutable : immutable ,
2865
+ transition : transition ,
2866
+ newDataRevision : newDataRevision ,
2846
2867
gd : gd
2847
2868
} ;
2848
2869
2849
-
2850
2870
var seenUIDs = { } ;
2851
2871
2852
2872
for ( i = 0 ; i < oldFullData . length ; i ++ ) {
2853
- trace = newFullData [ i ] . _fullInput ;
2854
- if ( Plots . hasMakesDataTransform ( trace ) ) trace = newFullData [ i ] ;
2855
- if ( seenUIDs [ trace . uid ] ) continue ;
2856
- seenUIDs [ trace . uid ] = 1 ;
2873
+ if ( newFullData [ i ] ) {
2874
+ trace = newFullData [ i ] . _fullInput ;
2875
+ if ( Plots . hasMakesDataTransform ( trace ) ) trace = newFullData [ i ] ;
2876
+ if ( seenUIDs [ trace . uid ] ) continue ;
2877
+ seenUIDs [ trace . uid ] = 1 ;
2857
2878
2858
- getDiffFlags ( oldFullData [ i ] . _fullInput , trace , [ ] , diffOpts ) ;
2879
+ getDiffFlags ( oldFullData [ i ] . _fullInput , trace , [ ] , diffOpts ) ;
2880
+ }
2859
2881
}
2860
2882
2861
2883
if ( flags . calc || flags . plot ) {
2862
2884
flags . fullReplot = true ;
2863
2885
}
2864
2886
2887
+ if ( transition && flags . nChanges && flags . nChangesAnim ) {
2888
+ flags . anim = ( flags . nChanges === flags . nChangesAnim ) && sameTraceLength ? 'all' : 'some' ;
2889
+ }
2890
+
2865
2891
return flags ;
2866
2892
}
2867
2893
2868
- function diffLayout ( gd , oldFullLayout , newFullLayout , immutable ) {
2894
+ function diffLayout ( gd , oldFullLayout , newFullLayout , immutable , transition ) {
2869
2895
var flags = editTypes . layoutFlags ( ) ;
2870
2896
flags . arrays = { } ;
2897
+ flags . rangesAltered = { } ;
2898
+ flags . nChanges = 0 ;
2899
+ flags . nChangesAnim = 0 ;
2871
2900
2872
2901
function getLayoutValObject ( parts ) {
2873
2902
return PlotSchema . getLayoutValObject ( newFullLayout , parts ) ;
@@ -2877,6 +2906,7 @@ function diffLayout(gd, oldFullLayout, newFullLayout, immutable) {
2877
2906
getValObject : getLayoutValObject ,
2878
2907
flags : flags ,
2879
2908
immutable : immutable ,
2909
+ transition : transition ,
2880
2910
gd : gd
2881
2911
} ;
2882
2912
@@ -2886,11 +2916,15 @@ function diffLayout(gd, oldFullLayout, newFullLayout, immutable) {
2886
2916
flags . layoutReplot = true ;
2887
2917
}
2888
2918
2919
+ if ( transition && flags . nChanges && flags . nChangesAnim ) {
2920
+ flags . anim = flags . nChanges === flags . nChangesAnim ? 'all' : 'some' ;
2921
+ }
2922
+
2889
2923
return flags ;
2890
2924
}
2891
2925
2892
2926
function getDiffFlags ( oldContainer , newContainer , outerparts , opts ) {
2893
- var valObject , key ;
2927
+ var valObject , key , astr ;
2894
2928
2895
2929
var getValObject = opts . getValObject ;
2896
2930
var flags = opts . flags ;
@@ -2905,6 +2939,25 @@ function getDiffFlags(oldContainer, newContainer, outerparts, opts) {
2905
2939
return ;
2906
2940
}
2907
2941
editTypes . update ( flags , valObject ) ;
2942
+
2943
+ if ( editType !== 'none' ) {
2944
+ flags . nChanges ++ ;
2945
+ }
2946
+
2947
+ // track animatable changes
2948
+ if ( opts . transition && valObject . anim ) {
2949
+ flags . nChangesAnim ++ ;
2950
+ }
2951
+
2952
+ // track cartesian axes with altered ranges
2953
+ if ( AX_RANGE_RE . test ( astr ) || AX_AUTORANGE_RE . test ( astr ) ) {
2954
+ flags . rangesAltered [ outerparts [ 0 ] ] = 1 ;
2955
+ }
2956
+
2957
+ // track datarevision changes
2958
+ if ( key === 'datarevision' ) {
2959
+ flags . newDataRevision = 1 ;
2960
+ }
2908
2961
}
2909
2962
2910
2963
function valObjectCanBeDataArray ( valObject ) {
@@ -2913,10 +2966,12 @@ function getDiffFlags(oldContainer, newContainer, outerparts, opts) {
2913
2966
2914
2967
for ( key in oldContainer ) {
2915
2968
// short-circuit based on previous calls or previous keys that already maximized the pathway
2916
- if ( flags . calc ) return ;
2969
+ if ( flags . calc && ! opts . transition ) return ;
2917
2970
2918
2971
var oldVal = oldContainer [ key ] ;
2919
2972
var newVal = newContainer [ key ] ;
2973
+ var parts = outerparts . concat ( key ) ;
2974
+ astr = parts . join ( '.' ) ;
2920
2975
2921
2976
if ( key . charAt ( 0 ) === '_' || typeof oldVal === 'function' || oldVal === newVal ) continue ;
2922
2977
@@ -2932,7 +2987,6 @@ function getDiffFlags(oldContainer, newContainer, outerparts, opts) {
2932
2987
if ( key === 'range' && newContainer . autorange ) continue ;
2933
2988
if ( ( key === 'zmin' || key === 'zmax' ) && newContainer . type === 'contourcarpet' ) continue ;
2934
2989
2935
- var parts = outerparts . concat ( key ) ;
2936
2990
valObject = getValObject ( parts ) ;
2937
2991
2938
2992
// in case type changed, we may not even *have* a valObject.
@@ -3003,6 +3057,11 @@ function getDiffFlags(oldContainer, newContainer, outerparts, opts) {
3003
3057
if ( immutable ) {
3004
3058
flags . calc = true ;
3005
3059
}
3060
+
3061
+ // look for animatable attributes when the data changed
3062
+ if ( immutable || opts . newDataRevision ) {
3063
+ changed ( ) ;
3064
+ }
3006
3065
}
3007
3066
else if ( wasArray !== nowArray ) {
3008
3067
flags . calc = true ;
0 commit comments