diff --git a/src/traces/scattergl/attributes.js b/src/traces/scattergl/attributes.js index 385fb765742..0d9e438bf08 100644 --- a/src/traces/scattergl/attributes.js +++ b/src/traces/scattergl/attributes.js @@ -54,6 +54,17 @@ var attrs = module.exports = overrideAll({ line: { color: scatterLineAttrs.color, width: scatterLineAttrs.width, + shape: { + valType: 'enumerated', + values: ['linear', 'hv', 'vh', 'hvh', 'vhv'], + dflt: 'linear', + role: 'style', + editType: 'plot', + description: [ + 'Determines the line shape.', + 'The values correspond to step-wise line shapes.' + ].join(' ') + }, dash: { valType: 'enumerated', values: Object.keys(DASHES), diff --git a/src/traces/scattergl/convert.js b/src/traces/scattergl/convert.js index f0ffbf8220f..8f488078665 100644 --- a/src/traces/scattergl/convert.js +++ b/src/traces/scattergl/convert.js @@ -393,17 +393,74 @@ function convertLinePositions(gd, trace, positions) { if(trace.line.shape === 'hv') { linePositions = []; for(i = 0; i < count - 1; i++) { - if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { + if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { + linePositions.push(positions[i * 2]); + linePositions.push(positions[i * 2 + 1]); + } else { + linePositions.push(NaN); + linePositions.push(NaN); + } linePositions.push(NaN); linePositions.push(NaN); + } + else { + linePositions.push(positions[i * 2]); + linePositions.push(positions[i * 2 + 1]); + linePositions.push(positions[i * 2 + 2]); + linePositions.push(positions[i * 2 + 1]); + } + } + linePositions.push(positions[positions.length - 2]); + linePositions.push(positions[positions.length - 1]); + } else if(trace.line.shape === 'hvh') { + linePositions = []; + for(i = 0; i < count - 1; i++) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { + if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { + linePositions.push(positions[i * 2]); + linePositions.push(positions[i * 2 + 1]); + } else { + linePositions.push(NaN); + linePositions.push(NaN); + } linePositions.push(NaN); linePositions.push(NaN); } else { + var midPtX = (positions[i * 2] + positions[i * 2 + 2]) / 2; linePositions.push(positions[i * 2]); linePositions.push(positions[i * 2 + 1]); - linePositions.push(positions[i * 2 + 2]); + linePositions.push(midPtX); linePositions.push(positions[i * 2 + 1]); + linePositions.push(midPtX); + linePositions.push(positions[i * 2 + 3]); + } + } + linePositions.push(positions[positions.length - 2]); + linePositions.push(positions[positions.length - 1]); + } else if(trace.line.shape === 'vhv') { + linePositions = []; + for(i = 0; i < count - 1; i++) { + if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { + if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { + linePositions.push(positions[i * 2]); + linePositions.push(positions[i * 2 + 1]); + } else { + linePositions.push(NaN); + linePositions.push(NaN); + } + linePositions.push(NaN); + linePositions.push(NaN); + } + else { + var midPtY = (positions[i * 2 + 1] + positions[i * 2 + 3]) / 2; + linePositions.push(positions[i * 2]); + linePositions.push(positions[i * 2 + 1]); + linePositions.push(positions[i * 2]); + linePositions.push(midPtY); + linePositions.push(positions[i * 2 + 2]); + linePositions.push(midPtY); } } linePositions.push(positions[positions.length - 2]); diff --git a/src/traces/scattergl/defaults.js b/src/traces/scattergl/defaults.js index 2703cb31b20..1120edea4f1 100644 --- a/src/traces/scattergl/defaults.js +++ b/src/traces/scattergl/defaults.js @@ -42,6 +42,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout if(subTypes.hasLines(traceOut)) { coerce('connectgaps'); handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + coerce('line.shape'); } if(subTypes.hasMarkers(traceOut)) { diff --git a/src/traces/scattergl/index.js b/src/traces/scattergl/index.js index 14f8b27d021..a4c3e237a81 100644 --- a/src/traces/scattergl/index.js +++ b/src/traces/scattergl/index.js @@ -259,25 +259,69 @@ function sceneUpdate(gd, subplot) { // draw traces in proper order scene.draw = function draw() { var i; + var we_must_draw_previous_line_marker = 0; for(i = 0; i < scene.count; i++) { + var we_defer_somes_draw = 0; + if(scene.fill2d && scene.fillOptions[i] && scene.fillOptions[i].fillmode && scene.fillOptions[i].fillmode === 'tonext') { + we_defer_somes_draw = 1; + } else { + if(we_must_draw_previous_line_marker && scene.line2d && scene.lineOptions[i - 1]) { + scene.line2d.draw(i - 1); + } + if(we_must_draw_previous_line_marker && scene.scatter2d && scene.markerOptions[i - 1]) { + scene.scatter2d.draw(i - 1); + } + if(we_must_draw_previous_line_marker && scene.error2d && scene.errorXOptions[i - 1]) { + scene.error2d.draw(i - 1); + } + if(we_must_draw_previous_line_marker && scene.error2d && scene.errorYOptions[i - 1]) { + scene.error2d.draw(i - 1 + scene.count); + } + we_must_draw_previous_line_marker = 0; + } if(scene.fill2d && scene.fillOptions[i]) { - // must do all fills first scene.fill2d.draw(i); } - } - for(i = 0; i < scene.count; i++) { + // we draw line2d + if(we_must_draw_previous_line_marker && scene.line2d && scene.lineOptions[i - 1]) { + scene.line2d.draw(i - 1); + } if(scene.line2d && scene.lineOptions[i]) { - scene.line2d.draw(i); + if(we_defer_somes_draw === 0) { + scene.line2d.draw(i); + } + } + // we draw error2d + if(we_must_draw_previous_line_marker && scene.error2d && scene.errorXOptions[i - 1]) { + scene.error2d.draw(i - 1); } if(scene.error2d && scene.errorXOptions[i]) { scene.error2d.draw(i); } + if(we_must_draw_previous_line_marker && scene.error2d && scene.errorYOptions[i - 1]) { + scene.error2d.draw(i - 1 + scene.count); + } if(scene.error2d && scene.errorYOptions[i]) { scene.error2d.draw(i + scene.count); } - if(scene.scatter2d && scene.markerOptions[i] && (!scene.selectBatch || !scene.selectBatch[i])) { - // traces in no-selection mode - scene.scatter2d.draw(i); + // we draw scatter2d + if(!scene.selectBatch || !scene.selectBatch[i]) { + if(we_must_draw_previous_line_marker && scene.scatter2d && scene.markerOptions[i - 1]) { + scene.scatter2d.draw(i - 1); + } + if(scene.scatter2d && scene.markerOptions[i]) { + if(we_defer_somes_draw === 0) { + scene.scatter2d.draw(i); + } + } + } + if(scene.glText[i] && scene.textOptions[i]) { + scene.glText[i].render(); + } + if(we_defer_somes_draw === 1) { + we_must_draw_previous_line_marker = 1; + } else { + we_must_draw_previous_line_marker = 0; } } @@ -287,12 +331,6 @@ function sceneUpdate(gd, subplot) { scene.scatter2d.draw(scene.unselectBatch); } - for(i = 0; i < scene.count; i++) { - if(scene.glText[i] && scene.textOptions[i]) { - scene.glText[i].render(); - } - } - scene.dirty = false; }; @@ -419,6 +457,24 @@ function plot(gd, subplot, cdata) { } if(scene.line2d) { scene.line2d.update(scene.lineOptions); + scene.lineOptions = scene.lineOptions.map(function(lineOptions) { + if(lineOptions && lineOptions.positions) { + var pos = [], srcPos = lineOptions.positions; + + var firstptdef = 0; + while(isNaN(srcPos[firstptdef]) || isNaN(srcPos[firstptdef + 1])) { + firstptdef += 2; + } + var lastptdef = srcPos.length - 2; + while(isNaN(srcPos[lastptdef]) || isNaN(srcPos[lastptdef + 1])) { + lastptdef += -2; + } + pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2)); + lineOptions.positions = pos; + } + return lineOptions; + }); + scene.line2d.update(scene.lineOptions); } if(scene.error2d) { var errorBatch = (scene.errorXOptions || []).concat(scene.errorYOptions || []); @@ -441,16 +497,38 @@ function plot(gd, subplot, cdata) { var pos = [], srcPos = (lineOptions && lineOptions.positions) || stash.positions; if(trace.fill === 'tozeroy') { - pos = [srcPos[0], 0]; - pos = pos.concat(srcPos); - pos.push(srcPos[srcPos.length - 2]); - pos.push(0); + var firstpdef = 0; + while(isNaN(srcPos[firstpdef + 1])) { + firstpdef += 2; + } + var lastpdef = srcPos.length - 2; + while(isNaN(srcPos[lastpdef + 1])) { + lastpdef += -2; + } + if(srcPos[firstpdef + 1] !== 0) { + pos = [ srcPos[firstpdef], 0 ]; + } + pos = pos.concat(srcPos.slice(firstpdef, lastpdef + 2)); + if(srcPos[lastpdef + 1] !== 0) { + pos = pos.concat([ srcPos[lastpdef], 0 ]); + } } else if(trace.fill === 'tozerox') { - pos = [0, srcPos[1]]; - pos = pos.concat(srcPos); - pos.push(0); - pos.push(srcPos[srcPos.length - 1]); + var firstptdef = 0; + while(isNaN(srcPos[firstptdef])) { + firstptdef += 2; + } + var lastptdef = srcPos.length - 2; + while(isNaN(srcPos[lastptdef])) { + lastptdef += -2; + } + if(srcPos[firstptdef] !== 0) { + pos = [ 0, srcPos[firstptdef + 1] ]; + } + pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2)); + if(srcPos[lastptdef] !== 0) { + pos = pos.concat([ 0, srcPos[lastptdef + 1]]); + } } else if(trace.fill === 'toself' || trace.fill === 'tonext') { pos = []; @@ -508,7 +586,7 @@ function plot(gd, subplot, cdata) { pos = pos.concat(prevLinePos); fillOptions.hole = hole; } - + fillOptions.fillmode = trace.fill; fillOptions.opacity = trace.opacity; fillOptions.positions = pos; diff --git a/test/image/baselines/gl2d_fill-ordering.png b/test/image/baselines/gl2d_fill-ordering.png index 7b71d7d2dcb..ed2acbd53cc 100644 Binary files a/test/image/baselines/gl2d_fill-ordering.png and b/test/image/baselines/gl2d_fill-ordering.png differ diff --git a/test/image/baselines/gl2d_fill_trace_tozero_order.png b/test/image/baselines/gl2d_fill_trace_tozero_order.png new file mode 100644 index 00000000000..5fbfce15d4f Binary files /dev/null and b/test/image/baselines/gl2d_fill_trace_tozero_order.png differ diff --git a/test/image/baselines/gl2d_order_error.png b/test/image/baselines/gl2d_order_error.png new file mode 100644 index 00000000000..250eb8f64fe Binary files /dev/null and b/test/image/baselines/gl2d_order_error.png differ diff --git a/test/image/baselines/gl2d_scatter_fill_self_next_vs_nogl.png b/test/image/baselines/gl2d_scatter_fill_self_next_vs_nogl.png new file mode 100644 index 00000000000..aa5e6d7677d Binary files /dev/null and b/test/image/baselines/gl2d_scatter_fill_self_next_vs_nogl.png differ diff --git a/test/image/baselines/gl2d_shape_line.png b/test/image/baselines/gl2d_shape_line.png new file mode 100644 index 00000000000..acda9683978 Binary files /dev/null and b/test/image/baselines/gl2d_shape_line.png differ diff --git a/test/image/mocks/gl2d_fill_trace_tozero_order.json b/test/image/mocks/gl2d_fill_trace_tozero_order.json new file mode 100644 index 00000000000..1018bbe1a8a --- /dev/null +++ b/test/image/mocks/gl2d_fill_trace_tozero_order.json @@ -0,0 +1,141 @@ +{ + "data": [ + { + "x": [null, 3 , 3, null, null ], + "y": [ 25,30,35,40 ,50 ], + "type": "scattergl", + "fill": "tozerox", + "mode": "none", + "showlegend": true, "xaxis": "x", "yaxis": "y" , + "fillcolor": "#FF69B4", + "line": { "color": "#FF69B4" } + }, + { + "x": [ null, null, null, 5, 5 ], + "y": [ 25,30,35,40 ,50 ], + "type": "scattergl", + "fill": "tozerox", + "mode": "markers+lines", + "showlegend": true, "xaxis": "x", "yaxis": "y" , + "fillcolor": "#202ff0", + "line": { "color": "#101ff0" } + }, + { + "x": [null, 3 , 3, null, null ], + "y": [ 25,30,35,40 ,50 ], + "type": "scatter", + "fill": "tozerox", + "mode": "none", + "showlegend": true, "xaxis": "x2", "yaxis": "y2" , + "fillcolor": "#DD5792", + "line": { "color": "#DD5792" } + }, + { + "x": [ null, null, null, 5, 5 ], + "y": [ 25,30,35,40 ,50 ], + "type": "scatter", + "fill": "tozerox", + "mode": "markers+lines", + "showlegend": true, "xaxis": "x2", "yaxis": "y2" , + "fillcolor": "#000fd0", + "line": { "color": "#0000d0" } + }, + { + "x": [ 1, 2, 3, 4, 5 ], + "y": [ null, 50, 50,null ,null ], + "type": "scattergl", + "fill": "tozeroy", + "mode": "none", + "showlegend": true, "xaxis": "x3", "yaxis": "y3" , + "fillcolor": "#80aa70", + "line": { "color": "#80aa70" } + }, + { + "x": [ 1, 2, 3, 4, 5 ], + "y": [null ,null ,null , 50, 50 ], + "type": "scattergl", + "fill": "tozeroy", + "mode": "markers+lines", + "showlegend": true, "xaxis": "x3", "yaxis": "y3" , + "fillcolor": "#f09090", + "line": { "color": "#e0b0b0" } + }, + { + "x": [ 1, 2, 3, 4, 5 ], + "y": [ null, 50, 50,null ,null ], + "type": "scatter", + "fill": "tozeroy", + "mode": "none", + "showlegend": true, "xaxis": "x4", "yaxis": "y4" , + "fillcolor": "#608a50", + "line": { "color": "#608a50" } + }, + { + "x": [ 1, 2, 3, 4, 5 ], + "y": [null ,null ,null , 50, 50 ], + "type": "scatter", + "fill": "tozeroy", + "mode": "markers+lines", + "showlegend": true, "xaxis": "x4", "yaxis": "y4" , + "fillcolor": "#e07070", + "line": { "color": "#c09090" } + }, + { + "x": [ 1, 1, 2, 3, 4, 5,5 ], + "y": [ 0,25,25,25,25,25,0 ], + "type": "scattergl", + "fill": "tozeroy", + "mode": "markers+lines", + "showlegend": true, "xaxis": "x5", "yaxis": "y5" , + "fillcolor": "#f02f20", + "line": { "color": "#f01f10" } + }, + { + "x": [ 1, 2, 2, 3, 4, 4,5 ], + "y": [ 0, 0,50,50,50, 0,0 ], + "type": "scattergl", + "fill": "tozeroy", + "mode": "none", + "showlegend": true, "xaxis": "x5", "yaxis": "y5" , + "fillcolor": "#90ff70", + "line": { "color": "#90ff70" } + }, + { + "x": [ 1, 1, 2, 3, 4, 5,5 ], + "y": [ 0,25,25,25,25,25,0 ], + "type": "scatter", + "fill": "tozeroy", + "mode": "markers+lines", + "showlegend": true, "xaxis": "x6", "yaxis": "y6" , + "fillcolor": "#d00f00", + "line": { "color": "#d00000" } + }, + { + "x": [ 1, 2, 2, 3, 4, 4,5 ], + "y": [ 0, 0,50,50,50, 0,0 ], + "type": "scatter", + "fill": "tozeroy", + "mode": "none", + "showlegend": true, "xaxis": "x6", "yaxis": "y6" , + "fillcolor": "#70df50", + "line": { "color": "#70df50" } + } + ], + "layout": { + "width": 800,"height": 800, + "margin": {"l": 60, "r": 60, "t": 60, "b": 60}, + "grid": {"columns": 2, "rows": 3, "pattern": "independent", "roworder": "bottom to top"} , + "xaxis" : { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis2": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis3": { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis4": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis5": { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis6": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "yaxis" : { "title": "" , "type": "linear", "range": [0,60], "nticks": 3 }, + "yaxis2": { "title": "" , "type": "linear", "range": [0,60], "nticks": 3 }, + "yaxis3": { "title": "" , "type": "linear", "range": [0,60], "nticks": 3 }, + "yaxis4": { "title": "" , "type": "linear", "range": [0,60], "nticks": 3 }, + "yaxis5": { "title": "" , "type": "linear", "range": [0,60], "nticks": 3 }, + "yaxis6": { "title": "" , "type": "linear", "range": [0,60], "nticks": 3 } + } +} diff --git a/test/image/mocks/gl2d_order_error.json b/test/image/mocks/gl2d_order_error.json new file mode 100644 index 00000000000..49158e78d38 --- /dev/null +++ b/test/image/mocks/gl2d_order_error.json @@ -0,0 +1,86 @@ +{ + "data": [{ + "type": "scattergl", + "y": [2, 3, 2, 0], + "xaxis": "x", "yaxis": "y" , + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#800"},"line": {"color": "#400"} + },{ + "type": "scattergl", + "y": [3, 2, 1, 1], "mode":"text","xaxis": "x", "yaxis": "y" , + "text": ["A","B","C","D"], + "textfont": { "size": [ 30, 20 , 30 , 30 ] } + },{ + "type": "scattergl", + "y": [1, 4, 0, 3], + "fillcolor":"#282","fill": "tozeroy", "xaxis": "x", "yaxis": "y" , + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#060"},"line": {"color": "#030"} + },{ + "type": "scatter", + "y": [2, 3, 2, 0], + "xaxis": "x2", "yaxis": "y2" , + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#088"},"line": {"color": "#044"} + },{ + "type": "scatter", + "y": [3, 2, 1, 1], "mode":"text","xaxis": "x2", "yaxis": "y2" , + "text": ["A","B","C","D"], + "textfont": { "size": [ 30, 20 , 30 , 30 ] } + },{ + "type": "scatter", + "y": [1, 4, 0, 3], + "fillcolor":"#882","fill": "tozeroy", "xaxis": "x2", "yaxis": "y2" , + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#660"},"line": {"color": "#330"} + },{ + "type": "scattergl", + "y": [2, 3, 2, 0], + "fill": "tozeroy", "xaxis": "x3", "yaxis": "y3" , + "fillcolor": "#f00", + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#800"},"line": {"color": "#400"} + },{ + "type": "scattergl", + "y": [1, 4, 0, 3], + "fill": "tozeroy", "xaxis": "x3", "yaxis": "y3" , + "fillcolor": "#0c0", + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#060"},"line": {"color": "#030"} + },{ + "type": "scatter", + "y": [2, 3, 2, 0], + "fill": "tozeroy", "xaxis": "x4", "yaxis": "y4" , + "fillcolor": "#f08", + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#088"},"line": {"color": "#044"} + },{ + "type": "scatter", + "y": [1, 4, 0, 3], + "fill": "tozeroy", "xaxis": "x4", "yaxis": "y4" , + "fillcolor": "#0c8", + "error_x": {"value": 0.4, "type": "constant","color":"#028"}, + "error_y": {"value": 0.3, "type": "constant","color":"#820"}, + "marker": {"color": "#660"},"line": {"color": "#330"} + }], + "layout": { + "width": 800,"height": 800, + "margin": {"l": 100, "r": 100, "t": 100, "b": 100}, + "grid": {"columns": 2, "rows": 2, "pattern": "independent", "roworder": "bottom to top"} , + "xaxis" : { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis2": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis3": { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis4": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "yaxis" : { "title": "GL" , "type": "linear", "range": [-1,5], "nticks": 3 }, + "yaxis2": { "title": "" , "type": "linear", "range": [-1,5], "nticks": 3 }, + "yaxis3": { "title": "GL" , "type": "linear", "range": [-1,5], "nticks": 3 }, + "yaxis4": { "title": "" , "type": "linear", "range": [-1,5], "nticks": 3 } + } +} diff --git a/test/image/mocks/gl2d_scatter_fill_self_next_vs_nogl.json b/test/image/mocks/gl2d_scatter_fill_self_next_vs_nogl.json new file mode 100644 index 00000000000..8298d023376 --- /dev/null +++ b/test/image/mocks/gl2d_scatter_fill_self_next_vs_nogl.json @@ -0,0 +1,110 @@ +{ + "data":[ + { + "x": [1, 2, 3, 1, null, 4, 5, 6], + "y": [2, 3, 2, 2, null, 3, 4, 3], + "fill": "tonext","fillcolor":"#282", "line": { "color": "#8c8" }, + "type": "scattergl" + }, + { + "x": [-1, 4, 9, null, 0, 1, 2], + "y": [1, 6, 1, null, 5, 6, 5], + "fill": "tonext","fillcolor":"#822", "line": { "color": "#c88" }, + "type": "scattergl" + }, + { + "x": [2, 7, 9], + "y": [2, 4, 2], + "fill": "toself","fillcolor":"#228", "line": { "color": "#88c" }, + "type": "scattergl" + }, + { + "x": [1, 2, 3, 1, null, 4, 5, 6], + "y": [2, 3, 2, 2, null, 3, 4, 3], + "fill": "tonext","fillcolor":"#282", "line": { "color": "#8c8" }, + "type": "scatter", "showlegend": true, "xaxis": "x2", "yaxis": "y2" + }, + { + "x": [-1, 4, 9, null, 0, 1, 2], + "y": [1, 6, 1, null, 5, 6, 5], + "fill": "tonext","fillcolor":"#822", "line": { "color": "#c88" }, + "type": "scatter", "showlegend": true, "xaxis": "x2", "yaxis": "y2" + }, + { + "x": [2, 7, 9], + "y": [2, 4, 2], + "fill": "toself","fillcolor":"#228", "line": { "color": "#88c" }, + "type": "scatter","showlegend": true, "xaxis": "x2", "yaxis": "y2" + }, + { + "x": [1, 2, 3, 1, null, 4, 5, 6], + "y": [2, 3, 2, 2, null, 3, 4, 3], + "error_x": {"value": 0.6, "type": "constant","color":"#cf0"}, + "error_y": {"value": 0.4, "type": "constant","color":"#fc0"}, + "fill": "tonext","fillcolor":"#282", "line": { "color": "#8c8" }, + "type": "scattergl", "showlegend": true, "xaxis": "x3", "yaxis": "y3" + }, + { + "x": [-1, 4, 9, null, 0, 1, 2], + "y": [1, 6, 1, null, 5, 6, 5], + "error_x": {"value": 0.6, "type": "constant","color":"#cf0"}, + "error_y": {"value": 0.4, "type": "constant","color":"#fc0"}, + "fill": "tonext","fillcolor":"#822", "line": { "color": "#c88" }, + "type": "scattergl", "showlegend": true, "xaxis": "x3", "yaxis": "y3" + }, + { + "x": [-2,-2, 0, 8,10 ,10], + "y": [ 0, 1, 7, 7, 1 , 0], + "fill": "tonext","fillcolor":"#828", "line": { "color": "#c8c" }, + "type": "scattergl", "showlegend": true, "xaxis": "x3", "yaxis": "y3" + }, + { + "x": [9,10,11], + "y": [7, 8, 7], + "fill": "toself","fillcolor":"#228", "line": { "color": "#88c" }, + "type": "scattergl", "showlegend": true, "xaxis": "x3", "yaxis": "y3" + }, + { + "x": [1, 2, 3, 1, null, 4, 5, 6], + "y": [2, 3, 2, 2, null, 3, 4, 3], + "error_x": {"value": 0.6, "type": "constant","color":"#cf0"}, + "error_y": {"value": 0.4, "type": "constant","color":"#fc0"}, + "fill": "tonext","fillcolor":"#282", "line": { "color": "#8c8" }, + "type": "scatter", "showlegend": true, "xaxis": "x4", "yaxis": "y4" + }, + { + "x": [-1, 4, 9, null, 0, 1, 2], + "y": [1, 6, 1, null, 5, 6, 5], + "error_x": {"value": 0.6, "type": "constant","color":"#cf0"}, + "error_y": {"value": 0.4, "type": "constant","color":"#fc0"}, + "fill": "tonext","fillcolor":"#822", "line": { "color": "#c88" }, + "type": "scatter", "showlegend": true, "xaxis": "x4", "yaxis": "y4" + }, + { + "x": [-2,-2, 0, 8,10 ,10], + "y": [ 0, 1, 7, 7, 1 , 0], + "fill": "tonext","fillcolor":"#828", "line": { "color": "#c8c" }, + "type": "scatter", "showlegend": true, "xaxis": "x4", "yaxis": "y4" + }, + { + "x": [9,10,11], + "y": [7, 8, 7], + "fill": "toself","fillcolor":"#228", "line": { "color": "#88c" }, + "type": "scatter","showlegend": true, "xaxis": "x4", "yaxis": "y4" + } + ], + "layout":{ + "title": "Fill toself and tonext", + "width": 600,"height": 600, + "margin": {"l": 20, "r": 40, "t": 40, "b": 40}, + "grid": {"columns": 2, "rows": 2, "pattern": "independent", "roworder": "bottom to top"} , + "xaxis" : { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis2": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "yaxis" : { "title": "" , "type": "linear", "range": [0,9], "nticks": 3 }, + "yaxis2": { "title": "" , "type": "linear", "range": [0,9], "nticks": 3 }, + "xaxis3": { "title": "GL" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "xaxis4": { "title": "" , "type": "linear", "rangemode": "tozero", "nticks": 3 }, + "yaxis3": { "title": "" , "type": "linear", "range": [0,9], "nticks": 3 }, + "yaxis4": { "title": "" , "type": "linear", "range": [0,9], "nticks": 3 } + } +} diff --git a/test/image/mocks/gl2d_shape_line.json b/test/image/mocks/gl2d_shape_line.json new file mode 100644 index 00000000000..d44205a9231 --- /dev/null +++ b/test/image/mocks/gl2d_shape_line.json @@ -0,0 +1,107 @@ +{ + "data": [ +{ +"x": [10,11, 12, 13, 14, 15 ,null, 16 , 17 , 18 , 19 ], + "y": [null,26, 28, 27, 29,null,null, 26, 30, 30 , null ], + "mode": "lines+markers","fill":"tozeroy", + "name": "hv", + "line": {"shape": "hv"}, + "type": "scattergl" +},{ + "x": [10,11, 12, 13, 14, 15 ,null, 16 , 17 , 18 , 19 ], + "y": [null,21, 23, 22, 24,null,null, 21, 25 , 25 , null ], + "mode": "lines+markers","fill":"tozeroy", + "name": "vh", + "line": {"shape": "vh"}, + "type": "scattergl" +},{ + "x": [10,11, 12, 13, 14, 15 , null , 16 , 17 , 18 , 19 ], + "y": [null,16, 18, 17, 19,null,null , 16, 20 , 20 , null ], + "mode": "lines+markers","fill":"tozeroy", + "name": "hvh", + "line": {"shape": "hvh"}, + "type": "scattergl" +}, +{ + "x": [10,11, 12, 13, 14, 15 ,null, 16 , 17 , 18 , 19 ], + "y": [null,11, 13, 12, 14,null,null, 11, 15 , 15 , null ], + "mode": "lines+markers","fill":"tozeroy", + "name": "vhv", + "line": {"shape": "vhv"}, + "type": "scattergl" +}, +{ + "x": [10,11, 12, 13, 14, 15 ,null, 16 , 17 , 18 , 19 ], + "y": [null,6, 8, 7, 9,null, null, 6, 10 , 10 , null ], + "mode": "lines+markers","fill":"tozeroy", + "name": "spline", + "line": {"shape": "spline","smoothing":4}, + "type": "scattergl" +}, +{ + "x": [10,11, 12, 13, 14, 15 , 16 , 17 , 18 , 19 ], + "y": [null,1, 3, 2, 4,null, 1 , 5 , 5 , null ], + "mode": "lines+markers","fill":"tozeroy", + "name": "linear", + "line": {"shape": "linear"}, + "type": "scattergl" +},{ + "x": [1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 ], + "y": [26, 28, 27, 29,null, 26, 30, 30 , null ], + "mode": "lines+markers", + "name": "hv", + "line": {"shape": "hv"}, + "type": "scattergl" +},{ + "x": [1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 ], + "y": [21, 23, 22, 24,null, 21, 25 , 25 , null ], + "mode": "lines+markers", + "name": "vh", + "line": {"shape": "vh"}, + "type": "scattergl" +},{ + "x": [1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 ], + "y": [16, 18, 17, 19,null, 16, 20 , 20 , null ], + "mode": "lines+markers", + "name": "hvh", + "line": {"shape": "hvh"}, + "type": "scattergl" +},{ + "x": [1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 ], + "y": [11, 13, 12, 14,null, 11, 15 , 15 , null ], + "mode": "lines+markers", + "name": "vhv", + "line": {"shape": "vhv"}, + "type": "scattergl" +},{ + "x": [1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 ], + "y": [6, 8, 7, 9,null, 6, 10 , 10 , null ], + "mode": "lines+markers", + "name": "spline", + "line": {"shape": "spline","smoothing":4}, + "type": "scattergl" +},{ + "x": [1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 ], + "y": [1, 3, 2, 4,null, 1 , 5 , 5 , null ], + "mode": "lines+markers", + "name": "linear", + "line": {"shape": "linear"}, + "type": "scattergl" +} +], + "layout": { + "margin": { + "b": 100, + "l": 100, + "t": 100, + "r": 100 + }, + "xaxis": { + "title": "x1" + }, + "yaxis": { + "title": "y1" + }, + "dragmode": "zoom" + } +}