Skip to content

Fix fill tozero with undefined value and overlaping of fill area #2979

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

Closed
Closed
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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 src/traces/scattergl/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
61 changes: 59 additions & 2 deletions src/traces/scattergl/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
1 change: 1 addition & 0 deletions src/traces/scattergl/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
70 changes: 52 additions & 18 deletions src/traces/scattergl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,8 @@ function sceneUpdate(gd, subplot) {
var i;
for(i = 0; i < scene.count; i++) {
if(scene.fill2d && scene.fillOptions[i]) {
// must do all fills first
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Looks like this broke the gl2d_scatter_fill_self_next mock:

peek 2018-10-04 17-07

The first two traces have fill: 'tonext' meaning their fills should be behind both the data[0] and data[1] markers. See corresponding SVG structure:

image

available here -> https://rreusser.github.io/plotly-mock-viewer/#scatter_fill_self_next

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i pushed a new version .

scene.fill2d.draw(i);
}
}
for(i = 0; i < scene.count; i++) {
if(scene.line2d && scene.lineOptions[i]) {
scene.line2d.draw(i);
}
Expand All @@ -279,6 +276,9 @@ function sceneUpdate(gd, subplot) {
// traces in no-selection mode
scene.scatter2d.draw(i);
}
if(scene.glText[i] && scene.textOptions[i]) {
scene.glText[i].render();
}
}

// draw traces in selection mode
Expand All @@ -287,12 +287,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;
};

Expand Down Expand Up @@ -419,6 +413,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 || []);
Expand All @@ -441,16 +453,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 = [];
Expand Down Expand Up @@ -508,7 +542,7 @@ function plot(gd, subplot, cdata) {
pos = pos.concat(prevLinePos);
fillOptions.hole = hole;
}

fillOptions.fillmode = trace.fill;
fillOptions.opacity = trace.opacity;
fillOptions.positions = pos;

Expand Down
Binary file modified test/image/baselines/gl2d_fill-ordering.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/image/baselines/gl2d_order_error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/gl2d_scatter_fill_self_next.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/image/baselines/gl2d_shape_line.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
141 changes: 141 additions & 0 deletions test/image/mocks/gl2d_fill_trace_tozero_order.json
Original file line number Diff line number Diff line change
@@ -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 }
}
}
Loading