Skip to content

Commit db6b942

Browse files
committed
Test moving transition and doCalcdata to plots.js
1 parent 82fefa9 commit db6b942

File tree

2 files changed

+295
-296
lines changed

2 files changed

+295
-296
lines changed

src/plot_api/plot_api.js

Lines changed: 2 additions & 295 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ Plotly.plot = function(gd, data, layout, config) {
158158
// generate calcdata, if we need to
159159
// to force redoing calcdata, just delete it before calling Plotly.plot
160160
var recalc = !gd.calcdata || gd.calcdata.length !== (gd.data || []).length;
161-
if(recalc) doCalcdata(gd);
161+
if(recalc) Plots.doCalcdata(gd);
162162

163163
// in case it has changed, attach fullData traces to calcdata
164164
for(var i = 0; i < gd.calcdata.length; i++) {
@@ -853,77 +853,6 @@ Plotly.newPlot = function(gd, data, layout, config) {
853853
return Plotly.plot(gd, data, layout, config);
854854
};
855855

856-
function doCalcdata(gd, traces) {
857-
var axList = Plotly.Axes.list(gd),
858-
fullData = gd._fullData,
859-
fullLayout = gd._fullLayout,
860-
i;
861-
862-
// XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without
863-
// *all* needing doCalcdata:
864-
var calcdata = new Array(fullData.length);
865-
var oldCalcdata = (gd.calcdata || []).slice(0);
866-
gd.calcdata = calcdata;
867-
868-
// extra helper variables
869-
// firstscatter: fill-to-next on the first trace goes to zero
870-
gd.firstscatter = true;
871-
872-
// how many box plots do we have (in case they're grouped)
873-
gd.numboxes = 0;
874-
875-
// for calculating avg luminosity of heatmaps
876-
gd._hmpixcount = 0;
877-
gd._hmlumcount = 0;
878-
879-
// for sharing colors across pies (and for legend)
880-
fullLayout._piecolormap = {};
881-
fullLayout._piedefaultcolorcount = 0;
882-
883-
// initialize the category list, if there is one, so we start over
884-
// to be filled in later by ax.d2c
885-
for(i = 0; i < axList.length; i++) {
886-
axList[i]._categories = axList[i]._initialCategories.slice();
887-
}
888-
889-
for(i = 0; i < fullData.length; i++) {
890-
// If traces were specified and this trace was not included, then transfer it over from
891-
// the old calcdata:
892-
if(Array.isArray(traces) && traces.indexOf(i) === -1) {
893-
calcdata[i] = oldCalcdata[i];
894-
continue;
895-
}
896-
897-
var trace = fullData[i],
898-
_module = trace._module,
899-
cd = [];
900-
901-
// If traces were specified and this trace was not included, then transfer it over from
902-
// the old calcdata:
903-
if(Array.isArray(traces) && traces.indexOf(i) === -1) {
904-
calcdata[i] = oldCalcdata[i];
905-
continue;
906-
}
907-
908-
if(_module && trace.visible === true) {
909-
if(_module.calc) cd = _module.calc(gd, trace);
910-
}
911-
912-
// make sure there is a first point
913-
// this ensures there is a calcdata item for every trace,
914-
// even if cartesian logic doesn't handle it
915-
if(!Array.isArray(cd) || !cd[0]) cd = [{x: false, y: false}];
916-
917-
// add the trace-wide properties to the first point,
918-
// per point properties to every point
919-
// t is the holder for trace-wide properties
920-
if(!cd[0].t) cd[0].t = {};
921-
cd[0].trace = trace;
922-
923-
calcdata[i] = cd;
924-
}
925-
}
926-
927856
/**
928857
* Wrap negative indicies to their positive counterparts.
929858
*
@@ -2526,228 +2455,6 @@ Plotly.relayout = function relayout(gd, astr, val) {
25262455
});
25272456
};
25282457

2529-
/**
2530-
* Transition to a set of new data and layout properties
2531-
*
2532-
* @param {string id or DOM element} gd
2533-
* the id or DOM element of the graph container div
2534-
*/
2535-
Plotly.transition = function(gd, data, layout, traceIndices, transitionOpts) {
2536-
gd = getGraphDiv(gd);
2537-
2538-
var i, traceIdx;
2539-
var fullLayout = gd._fullLayout;
2540-
2541-
transitionOpts = Plots.supplyTransitionDefaults(transitionOpts);
2542-
2543-
var dataLength = Array.isArray(data) ? data.length : 0;
2544-
2545-
// Select which traces will be updated:
2546-
if(isNumeric(traceIndices)) traceIndices = [traceIndices];
2547-
else if(!Array.isArray(traceIndices) || !traceIndices.length) {
2548-
traceIndices = gd.data.map(function(v, i) { return i; });
2549-
}
2550-
2551-
if(traceIndices.length > dataLength) {
2552-
traceIndices = traceIndices.slice(0, dataLength);
2553-
}
2554-
2555-
var transitionedTraces = [];
2556-
2557-
function prepareTransitions() {
2558-
var plotinfo, i;
2559-
for(i = 0; i < traceIndices.length; i++) {
2560-
var traceIdx = traceIndices[i];
2561-
var trace = gd._fullData[traceIdx];
2562-
var module = trace._module;
2563-
2564-
if(!module || !module.animatable) {
2565-
continue;
2566-
}
2567-
2568-
transitionedTraces.push(traceIdx);
2569-
2570-
// This is a multi-step process. First clone w/o arrays so that
2571-
// we're not modifying the original:
2572-
var update = Lib.extendDeepNoArrays({}, data[i]);
2573-
2574-
// Then expand object paths since we don't obey object-overwrite
2575-
// semantics here:
2576-
update = Lib.expandObjectPaths(update);
2577-
2578-
// Finally apply the update (without copying arrays, of course):
2579-
Lib.extendDeepNoArrays(gd.data[traceIndices[i]], update);
2580-
}
2581-
2582-
// Supply defaults after applying the incoming properties. Note that any attempt
2583-
// to simplify this step and reduce the amount of work resulted in the reconstruction
2584-
// of essentially the whole supplyDefaults step, so that it seems sensible to just use
2585-
// supplyDefaults even though it's heavier than would otherwise be desired for
2586-
// transitions:
2587-
Plots.supplyDefaults(gd);
2588-
2589-
// This step fies the .xaxis and .yaxis references that otherwise
2590-
// aren't updated by the supplyDefaults step:
2591-
var subplots = Plotly.Axes.getSubplots(gd);
2592-
for(i = 0; i < subplots.length; i++) {
2593-
plotinfo = gd._fullLayout._plots[subplots[i]];
2594-
plotinfo.xaxis = plotinfo.x();
2595-
plotinfo.yaxis = plotinfo.y();
2596-
}
2597-
2598-
doCalcdata(gd);
2599-
2600-
ErrorBars.calc(gd);
2601-
2602-
return Promise.resolve();
2603-
}
2604-
2605-
function executeCallbacks(list) {
2606-
var p = Promise.resolve();
2607-
if(!list) return p;
2608-
while(list.length) {
2609-
p = p.then((list.shift()));
2610-
}
2611-
return p;
2612-
}
2613-
2614-
function flushCallbacks(list) {
2615-
if(!list) return;
2616-
while(list.length) {
2617-
list.shift();
2618-
}
2619-
}
2620-
2621-
var aborted = false;
2622-
2623-
function executeTransitions() {
2624-
return new Promise(function(resolve) {
2625-
// This flag is used to disabled things like autorange:
2626-
gd._transitioning = true;
2627-
2628-
// When instantaneous updates are coming through quickly, it's too much to simply disable
2629-
// all interaction, so store this flag so we can disambiguate whether mouse interactions
2630-
// should be fully disabled or not:
2631-
if(transitionOpts.transitionduration > 0) {
2632-
gd._transitioningWithDuration = true;
2633-
}
2634-
2635-
gd._transitionData._interruptCallbacks.push(function() {
2636-
aborted = true;
2637-
});
2638-
2639-
// Construct callbacks that are executed on transition end. This ensures the d3 transitions
2640-
// are *complete* before anything else is done.
2641-
var numCallbacks = 0;
2642-
var numCompleted = 0;
2643-
function makeCallback() {
2644-
numCallbacks++;
2645-
return function() {
2646-
numCompleted++;
2647-
// When all are complete, perform a redraw:
2648-
if(!aborted && numCompleted === numCallbacks) {
2649-
completeTransition(resolve);
2650-
}
2651-
};
2652-
}
2653-
2654-
var traceTransitionOpts;
2655-
var j;
2656-
var basePlotModules = fullLayout._basePlotModules;
2657-
var hasAxisTransition = false;
2658-
2659-
if(layout) {
2660-
for(j = 0; j < basePlotModules.length; j++) {
2661-
if(basePlotModules[j].transitionAxes) {
2662-
var newLayout = Lib.expandObjectPaths(layout);
2663-
hasAxisTransition = basePlotModules[j].transitionAxes(gd, newLayout, transitionOpts, makeCallback) || hasAxisTransition;
2664-
}
2665-
}
2666-
}
2667-
2668-
// Here handle the exception that we refuse to animate scales and axes at the same
2669-
// time. In other words, if there's an axis transition, then set the data transition
2670-
// to instantaneous.
2671-
if(hasAxisTransition) {
2672-
traceTransitionOpts = Lib.extendFlat({}, transitionOpts);
2673-
traceTransitionOpts.transitionduration = 0;
2674-
} else {
2675-
traceTransitionOpts = transitionOpts;
2676-
}
2677-
2678-
for(j = 0; j < basePlotModules.length; j++) {
2679-
// Note that we pass a callback to *create* the callback that must be invoked on completion.
2680-
// This is since not all traces know about transitions, so it greatly simplifies matters if
2681-
// the trace is responsible for creating a callback, if needed, and then executing it when
2682-
// the time is right.
2683-
basePlotModules[j].plot(gd, transitionedTraces, traceTransitionOpts, makeCallback);
2684-
}
2685-
2686-
// If nothing else creates a callback, then this will trigger the completion in the next tick:
2687-
setTimeout(makeCallback());
2688-
2689-
});
2690-
}
2691-
2692-
function completeTransition(callback) {
2693-
flushCallbacks(gd._transitionData._interruptCallbacks);
2694-
2695-
return Promise.resolve().then(function() {
2696-
if(transitionOpts.redraw) {
2697-
return Plotly.redraw(gd);
2698-
}
2699-
}).then(function() {
2700-
// Set transitioning false again once the redraw has occurred. This is used, for example,
2701-
// to prevent the trailing redraw from autoranging:
2702-
gd._transitioning = false;
2703-
gd._transitioningWithDuration = false;
2704-
2705-
gd.emit('plotly_transitioned', []);
2706-
}).then(callback);
2707-
}
2708-
2709-
function interruptPreviousTransitions() {
2710-
gd.emit('plotly_transitioninterrupted', []);
2711-
2712-
// If a transition is interrupted, set this to false. At the moment, the only thing that would
2713-
// interrupt a transition is another transition, so that it will momentarily be set to true
2714-
// again, but this determines whether autorange or dragbox work, so it's for the sake of
2715-
// cleanliness:
2716-
gd._transitioning = false;
2717-
gd._transtionWithDuration = false;
2718-
2719-
return executeCallbacks(gd._transitionData._interruptCallbacks);
2720-
}
2721-
2722-
for(i = 0; i < traceIndices.length; i++) {
2723-
traceIdx = traceIndices[i];
2724-
var contFull = gd._fullData[traceIdx];
2725-
var module = contFull._module;
2726-
2727-
if(!module) continue;
2728-
2729-
if(!module.animatable) {
2730-
var thisUpdate = {};
2731-
2732-
for(var ai in data[i]) {
2733-
thisUpdate[ai] = [data[i][ai]];
2734-
}
2735-
}
2736-
}
2737-
2738-
var seq = [Plots.previousPromises, interruptPreviousTransitions, prepareTransitions, executeTransitions];
2739-
2740-
2741-
var transitionStarting = Lib.syncOrAsync(seq, gd);
2742-
2743-
if(!transitionStarting || !transitionStarting.then) transitionStarting = Promise.resolve();
2744-
2745-
return transitionStarting.then(function() {
2746-
gd.emit('plotly_transitioning', []);
2747-
return gd;
2748-
});
2749-
};
2750-
27512458
/**
27522459
* Animate to a keyframe
27532460
*
@@ -2854,7 +2561,7 @@ Plotly.animate = function(gd, frameOrGroupNameOrFrameList, transitionOpts, anima
28542561
trans._lastframeat = Date.now();
28552562
trans._timetonext = newFrame.transitionOpts.frameduration;
28562563

2857-
Plotly.transition(gd,
2564+
Plots.transition(gd,
28582565
newFrame.frame.data,
28592566
newFrame.frame.layout,
28602567
newFrame.frame.traces,

0 commit comments

Comments
 (0)