Skip to content

Funnelarea traces #3876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
May 22, 2019
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d77474e
add funnelarea to lib components plot api etc
archmoj May 17, 2019
2d090d1
refactor other traces to reuse code in funnelarea
archmoj May 17, 2019
7b0e602
add funnelarea trace code
archmoj May 17, 2019
1b8caed
add funnelarea jasmine and image tests
archmoj May 17, 2019
32b7b0b
correct groupscale in various dim ratios
archmoj May 18, 2019
68bebc2
Merge branch 'master' into funnelarea-traces
etpinard May 20, 2019
7c3369b
rm 'i' & 'v' from funnelarea event data
etpinard May 20, 2019
abc3b39
revise hiddenlabels coerce - rm hiddenLabels unused category - rm _ha…
archmoj May 20, 2019
316aff9
more explicit funnelarea marker line color - dont inherit from sunburst
archmoj May 20, 2019
7f2dc2a
drop round stroke line join
archmoj May 20, 2019
7e6b9ae
drop quadrants and move func from funnelarea plot - add todo comment …
archmoj May 20, 2019
8bd1875
default funnelarea textinfo to percent not value
archmoj May 21, 2019
fa5b273
move convexPolygonArea to funnelarea_test - add another set of tests …
archmoj May 21, 2019
38b474d
revise funnelarea title attribute - drop support for old API
archmoj May 21, 2019
de8b517
add mock light and dark colorways for pie and funnelarea
archmoj May 21, 2019
a6a6d62
drop sort from one jasmine mock
archmoj May 21, 2019
42ca38e
moduleHasUnSelected > moduleHasUnselected
archmoj May 21, 2019
32c96d2
no need to outsidetextfont attribute in funnelarea
archmoj May 21, 2019
2ad1843
fixup name of funnelarea mock used in mock list
etpinard May 21, 2019
8af4d12
add textposition inside none - change pie title and textposition edit…
archmoj May 21, 2019
4711c5c
Merge branch 'funnelarea-traces' into funnelarea-traces_dev
archmoj May 21, 2019
a9625b6
drop funnelarea sort - auto sort when funnelarea is aggregated - fixu…
archmoj May 21, 2019
1426be7
Merge branch 'master' into funnelarea-traces
etpinard May 21, 2019
79415cd
use trace._meta for funnelarea title.text
etpinard May 21, 2019
e227763
remove outsudetext from funnelarea mock
archmoj May 21, 2019
04b14a8
clear TODO comment for hiddenlabels role
archmoj May 21, 2019
4d89d1d
apply domain width and height with aspectratio
archmoj May 21, 2019
23bc199
add delay between sort-by-value tests
etpinard May 21, 2019
dd673a2
add test for pie title.position restyle calls
etpinard May 21, 2019
6673fac
:hocho: "TODO: test" for attrs that already have sufficient coverage
etpinard May 21, 2019
c64fe84
drop @flaky on @noCI test
etpinard May 21, 2019
77f1c59
drop @noCI on funnel & waterfall select tests
etpinard May 21, 2019
28b2f14
improve funnelarea scalegroup
archmoj May 22, 2019
c42a899
add shapes around domain boxes in funnelarea mocks
archmoj May 22, 2019
84b0dd1
flip processing aspectratio
archmoj May 22, 2019
08a1f7b
remove unused mock
archmoj May 22, 2019
b8b3d94
fit r using trace.aspectratio when having non scalegroup
archmoj May 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/funnelarea.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

module.exports = require('../src/traces/funnelarea');
1 change: 1 addition & 0 deletions lib/index-finance.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Plotly.register([
require('./bar'),
require('./histogram'),
require('./pie'),
require('./funnelarea'),
require('./ohlc'),
require('./candlestick'),
require('./funnel'),
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Plotly.register([

require('./pie'),
require('./sunburst'),
require('./funnelarea'),

require('./scatter3d'),
require('./surface'),
Expand Down
2 changes: 1 addition & 1 deletion src/components/fx/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module.exports = function calc(gd) {
// don't include hover calc fields for pie traces
// as calcdata items might be sorted by value and
// won't match the data array order.
if(Registry.traceIs(trace, 'pie')) continue;
if(Registry.traceIs(trace, 'pie-like')) continue;

var fillFn = Registry.traceIs(trace, '2dMap') ? paste : Lib.fillArray;

Expand Down
3 changes: 1 addition & 2 deletions src/components/legend/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var Registry = require('../../registry');
Expand Down Expand Up @@ -42,7 +41,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
legendReallyHasATrace = true;
// Always show the legend by default if there's a pie,
// or if there's only one trace but it's explicitly shown
if(Registry.traceIs(trace, 'pie') ||
if(Registry.traceIs(trace, 'pie-like') ||
trace._input.showlegend === true
) {
legendTraceCount++;
Expand Down
14 changes: 7 additions & 7 deletions src/components/legend/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ module.exports = function draw(gd) {
for(var j = 0; j < legendData[i].length; j++) {
var item = legendData[i][j][0];
var trace = item.trace;
var isPie = Registry.traceIs(trace, 'pie');
var name = isPie ? item.label : trace.name;
var isPieLike = Registry.traceIs(trace, 'pie-like');
var name = isPieLike ? item.label : trace.name;
maxLength = Math.max(maxLength, name && name.length || 0);
}
}
Expand Down Expand Up @@ -110,7 +110,7 @@ module.exports = function draw(gd) {

traces.style('opacity', function(d) {
var trace = d[0].trace;
if(Registry.traceIs(trace, 'pie')) {
if(Registry.traceIs(trace, 'pie-like')) {
return hiddenSlices.indexOf(d[0].label) !== -1 ? 0.5 : 1;
} else {
return trace.visible === 'legendonly' ? 0.5 : 1;
Expand Down Expand Up @@ -375,7 +375,7 @@ function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) {
if(trace._group) {
evtData.group = trace._group;
}
if(trace.type === 'pie') {
if(Registry.traceIs(trace, 'pie-like')) {
evtData.label = legendItem.datum()[0].label;
}

Expand All @@ -399,11 +399,11 @@ function drawTexts(g, gd, maxLength) {
var legendItem = g.data()[0][0];
var fullLayout = gd._fullLayout;
var trace = legendItem.trace;
var isPie = Registry.traceIs(trace, 'pie');
var isPieLike = Registry.traceIs(trace, 'pie-like');
var traceIndex = trace.index;
var isEditable = gd._context.edits.legendText && !isPie;
var isEditable = gd._context.edits.legendText && !isPieLike;

var name = isPie ? legendItem.label : trace.name;
var name = isPieLike ? legendItem.label : trace.name;
if(fullLayout.meta) {
name = Lib.templateString(name, {meta: fullLayout.meta});
}
Expand Down
4 changes: 1 addition & 3 deletions src/components/legend/get_legend_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var Registry = require('../../registry');
var helpers = require('./helpers');


module.exports = function getLegendData(calcdata, opts) {
var lgroupToTraces = {};
var lgroups = [];
Expand Down Expand Up @@ -45,7 +43,7 @@ module.exports = function getLegendData(calcdata, opts) {

if(!trace.visible || !trace.showlegend) continue;

if(Registry.traceIs(trace, 'pie')) {
if(Registry.traceIs(trace, 'pie-like')) {
if(!slicesShown[lgroup]) slicesShown[lgroup] = {};

for(j = 0; j < cd.length; j++) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/legend/handle_click.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ module.exports = function handleClick(g, gd, numClicks) {
SHOWISOLATETIP = false;
}

if(Registry.traceIs(fullTrace, 'pie')) {
if(Registry.traceIs(fullTrace, 'pie-like')) {
var thisLabel = legendItem.label;
var thisLabelIndex = hiddenSlices.indexOf(thisLabel);

Expand Down
26 changes: 19 additions & 7 deletions src/components/legend/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ module.exports = function style(s, gd) {
.each(styleFunnels)
.each(styleBars)
.each(styleBoxes)
.each(styleFunnelareas)
.each(stylePies)
.each(styleLines)
.each(stylePoints)
Expand Down Expand Up @@ -307,14 +308,14 @@ module.exports = function style(s, gd) {
}

function styleBars(d) {
styleBarFamily(d, this);
styleBarLike(d, this);
}

function styleFunnels(d) {
styleBarFamily(d, this, 'funnel');
styleBarLike(d, this, 'funnel');
}

function styleBarFamily(d, lThis, desiredType) {
function styleBarLike(d, lThis, desiredType) {
var trace = d[0].trace;
var marker = trace.marker || {};
var markerLine = marker.line || {};
Expand Down Expand Up @@ -435,13 +436,24 @@ module.exports = function style(s, gd) {
}

function stylePies(d) {
stylePieLike(d, this, 'pie');
}

function styleFunnelareas(d) {
stylePieLike(d, this, 'funnelarea');
}

function stylePieLike(d, lThis, desiredType) {
var d0 = d[0];
var trace = d0.trace;

var pts = d3.select(this).select('g.legendpoints')
.selectAll('path.legendpie')
.data(Registry.traceIs(trace, 'pie') && trace.visible ? [d] : []);
pts.enter().append('path').classed('legendpie', true)
var isVisible = (!desiredType) ? Registry.traceIs(trace, desiredType) :
(trace.type === desiredType && trace.visible);

var pts = d3.select(lThis).select('g.legendpoints')
.selectAll('path.legend' + desiredType)
.data(isVisible ? [d] : []);
pts.enter().append('path').classed('legend' + desiredType, true)
.attr('d', 'M6,6H-6V-6H6Z')
.attr('transform', 'translate(20,0)');
pts.exit().remove();
Expand Down
3 changes: 2 additions & 1 deletion src/components/modebar/manage.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd, showSendToCloud) {
var hasGL3D = fullLayout._has('gl3d');
var hasGeo = fullLayout._has('geo');
var hasPie = fullLayout._has('pie');
var hasFunnelarea = fullLayout._has('funnelarea');
var hasGL2D = fullLayout._has('gl2d');
var hasTernary = fullLayout._has('ternary');
var hasMapbox = fullLayout._has('mapbox');
Expand Down Expand Up @@ -113,7 +114,7 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd, showSendToCloud) {
var resetGroup = [];
var dragModeGroup = [];

if((hasCartesian || hasGL2D || hasPie || hasTernary) + hasGeo + hasGL3D + hasMapbox + hasPolar > 1) {
if((hasCartesian || hasGL2D || hasPie || hasFunnelarea || hasTernary) + hasGeo + hasGL3D + hasMapbox + hasPolar > 1) {
// graphs with more than one plot types get 'union buttons'
// which reset the view or toggle hover labels across all subplots.
hoverGroup = ['toggleHover'];
Expand Down
12 changes: 12 additions & 0 deletions src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1159,3 +1159,15 @@ lib.fillText = function(calcPt, trace, contOut) {
lib.isValidTextValue = function(v) {
return v || v === 0;
};

lib.formatPercent = function(ratio, n) {
n = n || 0;
var str = (Math.round(100 * ratio * Math.pow(10, n)) * Math.pow(0.1, n)).toFixed(n) + '%';
for(var i = 0; i < n; i++) {
if(str.indexOf('.') !== -1) {
str = str.replace('0%', '%');
str = str.replace('.%', '%');
}
}
return str;
};
3 changes: 1 addition & 2 deletions src/plot_api/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var isNumeric = require('fast-isnumeric');
Expand Down Expand Up @@ -328,7 +327,7 @@ exports.cleanData = function(data) {
trace.scene = Plots.subplotsRegistry.gl3d.cleanId(trace.scene);
}

if(!traceIs(trace, 'pie') && !traceIs(trace, 'bar-like')) {
if(!traceIs(trace, 'pie-like') && !traceIs(trace, 'bar-like')) {
if(Array.isArray(trace.textposition)) {
for(i = 0; i < trace.textposition.length; i++) {
trace.textposition[i] = cleanTextPosition(trace.textposition[i]);
Expand Down
14 changes: 9 additions & 5 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
* LICENSE file in the root directory of this source tree.
*/


'use strict';


var d3 = require('d3');
var isNumeric = require('fast-isnumeric');
var hasHover = require('has-hover');
Expand Down Expand Up @@ -1634,7 +1632,10 @@ function _restyle(gd, aobj, traces) {
doextra(prefixDot + 'len', innerContFull.len *
(newVal === 'fraction' ? 1 / lennorm : lennorm), i);
}
} else if(ai === 'type' && (newVal === 'pie') !== (oldVal === 'pie')) {
} else if(ai === 'type' && (
(newVal === 'pie') !== (oldVal === 'pie') ||
(newVal === 'funnelarea') !== (oldVal === 'funnelarea')
)) {
var labelsTo = 'x';
var valuesTo = 'y';
if((newVal === 'bar' || oldVal === 'bar') && cont.orientation === 'h') {
Expand All @@ -1645,7 +1646,7 @@ function _restyle(gd, aobj, traces) {
Lib.swapAttrs(cont, ['d?', '?0'], 'label', labelsTo);
Lib.swapAttrs(cont, ['?', '?src'], 'values', valuesTo);

if(oldVal === 'pie') {
if(oldVal === 'pie' || oldVal === 'funnelarea') {
nestedProperty(cont, 'marker.color')
.set(nestedProperty(cont, 'marker.colors').get());

Expand Down Expand Up @@ -3769,10 +3770,13 @@ function makePlotFramework(gd) {
// single geo layer for the whole plot
fullLayout._geolayer = fullLayout._paper.append('g').classed('geolayer', true);

// single funnelarea layer for the whole plot
fullLayout._funnelarealayer = fullLayout._paper.append('g').classed('funnelarealayer', true);

// single pie layer for the whole plot
fullLayout._pielayer = fullLayout._paper.append('g').classed('pielayer', true);

// single sunbursrt layer for the whole plot
// single sunburst layer for the whole plot
fullLayout._sunburstlayer = fullLayout._paper.append('g').classed('sunburstlayer', true);

// fill in image server scrape-svg
Expand Down
4 changes: 2 additions & 2 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var d3 = require('d3');
Expand Down Expand Up @@ -2722,9 +2721,10 @@ plots.doCalcdata = function(gd, traces) {
gd._hmpixcount = 0;
gd._hmlumcount = 0;

// for sharing colors across pies / sunbursts (and for legend)
// for sharing colors across pies / sunbursts / funnelarea (and for legend)
fullLayout._piecolormap = {};
fullLayout._sunburstcolormap = {};
fullLayout._funnelareacolormap = {};

// If traces were specified and this trace was not included,
// then transfer it over from the old calcdata:
Expand Down
4 changes: 2 additions & 2 deletions src/snapshot/cloneplot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var Registry = require('../registry');
var Lib = require('../lib');

var extendFlat = Lib.extendFlat;
Expand Down Expand Up @@ -89,7 +89,7 @@ module.exports = function clonePlot(graphObj, options) {
var trace = newData[i];
trace.showscale = false;
if(trace.marker) trace.marker.showscale = false;
if(trace.type === 'pie') trace.textposition = 'none';
if(Registry.traceIs(trace, 'pie-like')) trace.textposition = 'none';
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/traces/bar/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ module.exports = {
valType: 'enumerated',
values: ['end', 'middle', 'start'],
dflt: 'end',
role: 'info', // TODO: or style ?
role: 'info',
editType: 'plot',
description: [
'Determines if texts are kept at center or start/end points in `textposition` *inside* mode.'
Expand All @@ -98,7 +98,7 @@ module.exports = {
textangle: {
valType: 'angle',
dflt: 'auto',
role: 'info', // TODO: or style ?
role: 'info',
editType: 'plot',
description: [
'Sets the angle of the tick labels with respect to the bar.',
Expand Down
Loading