'use strict'; var d3 = require('@plotly/d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); var BADNUM = require('../../constants/numerical').BADNUM; var barPlot = require('../bar/plot'); var clearMinTextSize = require('../bar/uniform_text').clearMinTextSize; module.exports = function plot(gd, plotinfo, cdModule, traceLayer) { var fullLayout = gd._fullLayout; clearMinTextSize('funnel', fullLayout); plotConnectorRegions(gd, plotinfo, cdModule, traceLayer); plotConnectorLines(gd, plotinfo, cdModule, traceLayer); barPlot.plot(gd, plotinfo, cdModule, traceLayer, { mode: fullLayout.funnelmode, norm: fullLayout.funnelmode, gap: fullLayout.funnelgap, groupgap: fullLayout.funnelgroupgap }); }; function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) { var xa = plotinfo.xaxis; var ya = plotinfo.yaxis; Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) { var plotGroup = d3.select(this); var trace = cd[0].trace; var group = Lib.ensureSingle(plotGroup, 'g', 'regions'); if(!trace.connector || !trace.connector.visible) { group.remove(); return; } var isHorizontal = (trace.orientation === 'h'); var connectors = group.selectAll('g.region').data(Lib.identity); connectors.enter().append('g') .classed('region', true); connectors.exit().remove(); var len = connectors.size(); connectors.each(function(di, i) { // don't draw lines between nulls if(i !== len - 1 && !di.cNext) return; var xy = getXY(di, xa, ya, isHorizontal); var x = xy[0]; var y = xy[1]; var shape = ''; if( x[0] !== BADNUM && y[0] !== BADNUM && x[1] !== BADNUM && y[1] !== BADNUM && x[2] !== BADNUM && y[2] !== BADNUM && x[3] !== BADNUM && y[3] !== BADNUM ) { if(isHorizontal) { shape += 'M' + x[0] + ',' + y[1] + 'L' + x[2] + ',' + y[2] + 'H' + x[3] + 'L' + x[1] + ',' + y[1] + 'Z'; } else { shape += 'M' + x[1] + ',' + y[1] + 'L' + x[2] + ',' + y[3] + 'V' + y[2] + 'L' + x[1] + ',' + y[0] + 'Z'; } } if(shape === '') shape = 'M0,0Z'; Lib.ensureSingle(d3.select(this), 'path') .attr('d', shape) .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); }); }); } function plotConnectorLines(gd, plotinfo, cdModule, traceLayer) { var xa = plotinfo.xaxis; var ya = plotinfo.yaxis; Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) { var plotGroup = d3.select(this); var trace = cd[0].trace; var group = Lib.ensureSingle(plotGroup, 'g', 'lines'); if(!trace.connector || !trace.connector.visible || !trace.connector.line.width) { group.remove(); return; } var isHorizontal = (trace.orientation === 'h'); var connectors = group.selectAll('g.line').data(Lib.identity); connectors.enter().append('g') .classed('line', true); connectors.exit().remove(); var len = connectors.size(); connectors.each(function(di, i) { // don't draw lines between nulls if(i !== len - 1 && !di.cNext) return; var xy = getXY(di, xa, ya, isHorizontal); var x = xy[0]; var y = xy[1]; var shape = ''; if(x[3] !== undefined && y[3] !== undefined) { if(isHorizontal) { shape += 'M' + x[0] + ',' + y[1] + 'L' + x[2] + ',' + y[2]; shape += 'M' + x[1] + ',' + y[1] + 'L' + x[3] + ',' + y[2]; } else { shape += 'M' + x[1] + ',' + y[1] + 'L' + x[2] + ',' + y[3]; shape += 'M' + x[1] + ',' + y[0] + 'L' + x[2] + ',' + y[2]; } } if(shape === '') shape = 'M0,0Z'; Lib.ensureSingle(d3.select(this), 'path') .attr('d', shape) .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); }); }); } function getXY(di, xa, ya, isHorizontal) { var s = []; var p = []; var sAxis = isHorizontal ? xa : ya; var pAxis = isHorizontal ? ya : xa; s[0] = sAxis.c2p(di.s0, true); p[0] = pAxis.c2p(di.p0, true); s[1] = sAxis.c2p(di.s1, true); p[1] = pAxis.c2p(di.p1, true); s[2] = sAxis.c2p(di.nextS0, true); p[2] = pAxis.c2p(di.nextP0, true); s[3] = sAxis.c2p(di.nextS1, true); p[3] = pAxis.c2p(di.nextP1, true); return isHorizontal ? [s, p] : [p, s]; }