Skip to content

Scattergl improvements for: fill tozero with bad values fix, fills layering fix, add some line.shape values #3087

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 27 commits into from
Oct 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1c52fa6
Merge pull request #1 from plotly/master
ErwanMAS Sep 8, 2018
bdc94ce
Merge pull request #2 from plotly/master
ErwanMAS Sep 12, 2018
e69e2d6
Merge pull request #3 from plotly/master
ErwanMAS Sep 30, 2018
52020a9
Fix https://codepen.io/erwanmas/pen/JaymVr
ErwanMAS Sep 7, 2018
304083e
fix lint issues
ErwanMAS Sep 7, 2018
05343b8
only one big mock for the 3 tests
ErwanMAS Sep 7, 2018
51d6688
add simple shape for line in scattergl
ErwanMAS Sep 11, 2018
831f508
add shape to scattergl
ErwanMAS Sep 12, 2018
39eb303
remove some empty lines
ErwanMAS Sep 12, 2018
283b50d
update of the baseline images
ErwanMAS Sep 12, 2018
02e924c
we don't reuse scatter files ... because partialy impelemented
ErwanMAS Sep 12, 2018
a49e6d0
fix lint
ErwanMAS Sep 13, 2018
5d3a924
- remove line_shape_defaults.js , moe the code into scattergl/default…
ErwanMAS Sep 14, 2018
f670af2
fix lint issues
ErwanMAS Sep 14, 2018
93b61bc
- modify one test to add GL/REG version
ErwanMAS Sep 30, 2018
346a32a
- remove some console.log
ErwanMAS Sep 30, 2018
9cf7172
add baseline for the gl2d_order_error
ErwanMAS Sep 30, 2018
987e6cd
fix lint issues
ErwanMAS Sep 30, 2018
95c602e
last version , we display by order only .
ErwanMAS Oct 1, 2018
be43294
- fix gl2d_scatter_fill_self_next ( rollback the baselines test/image…
ErwanMAS Oct 5, 2018
126e29c
fix lint issues
ErwanMAS Oct 5, 2018
9cc641a
Merge branch 'master' into pr-2979
etpinard Oct 5, 2018
075bd14
DRY up fill ordering logic
etpinard Oct 5, 2018
6ae6283
DRY up scatter / scattergl fill ordering in linkTraces
etpinard Oct 5, 2018
54d8240
improve gl2d_scatter_fill_self_next_vs_nogl mock
etpinard Oct 9, 2018
d8297a0
improve line.shape 'vh' by @ErwanMAS
etpinard Oct 11, 2018
d708132
merge 'push' calls together
etpinard Oct 11, 2018
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
9 changes: 8 additions & 1 deletion src/traces/scatter/link_traces.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,16 @@ module.exports = function linkTraces(gd, plotinfo, cdscatter) {
}
}

if(trace.fill && (
trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' ||
(trace.fill.substr(0, 2) === 'to' && !trace._prevtrace))
) {
trace._ownfill = true;
}

prevtraces[group] = trace;
} else {
trace._prevtrace = trace._nexttrace = null;
trace._prevtrace = trace._nexttrace = trace._ownfill = null;
}
}

Expand Down
15 changes: 3 additions & 12 deletions src/traces/scatter/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,10 @@ function createFills(gd, traceJoin, plotinfo) {
var trace = d[0].trace;

var fillData = [];
if(trace.fill && (trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' ||
(trace.fill.substr(0, 2) === 'to' && !trace._prevtrace))
) {
fillData = ['_ownFill'];
}
if(trace._nexttrace) {
// make the fill-to-next path now for the NEXT trace, so it shows
// behind both lines.
fillData.push('_nextFill');
}
if(trace._ownfill) fillData.push('_ownFill');
if(trace._nexttrace) fillData.push('_nextFill');

var fillJoin = fills.selectAll('g')
.data(fillData, identity);
var fillJoin = fills.selectAll('g').data(fillData, identity);

fillJoin.enter().append('g');

Expand Down
11 changes: 11 additions & 0 deletions src/traces/scattergl/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,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
86 changes: 65 additions & 21 deletions src/traces/scattergl/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ function getSymbolSdf(symbol) {
}

function convertLinePositions(gd, trace, positions) {
var count = positions.length / 2;
var len = positions.length;
var count = len / 2;
var linePositions;
var i;

Expand All @@ -394,38 +395,81 @@ function convertLinePositions(gd, trace, positions) {
linePositions = [];
for(i = 0; i < count - 1; i++) {
if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) {
linePositions.push(NaN);
linePositions.push(NaN);
linePositions.push(NaN);
linePositions.push(NaN);
linePositions.push(NaN, NaN, NaN, NaN);
} else {
linePositions.push(positions[i * 2], positions[i * 2 + 1]);
if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) {
linePositions.push(positions[i * 2 + 2], positions[i * 2 + 1]);
} else {
linePositions.push(NaN, NaN);
}
}
}
linePositions.push(positions[len - 2], positions[len - 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], positions[i * 2 + 1]);
} else {
linePositions.push(NaN, NaN);
}
linePositions.push(NaN, 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]);
var midPtX = (positions[i * 2] + positions[i * 2 + 2]) / 2;
linePositions.push(
positions[i * 2],
positions[i * 2 + 1],
midPtX,
positions[i * 2 + 1],
midPtX,
positions[i * 2 + 3]
);
}
}
linePositions.push(positions[positions.length - 2]);
linePositions.push(positions[positions.length - 1]);
linePositions.push(positions[len - 2], positions[len - 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], positions[i * 2 + 1]);
} else {
linePositions.push(NaN, NaN);
}
linePositions.push(NaN, NaN);
}
else {
var midPtY = (positions[i * 2 + 1] + positions[i * 2 + 3]) / 2;
linePositions.push(
positions[i * 2],
positions[i * 2 + 1],
positions[i * 2],
midPtY,
positions[i * 2 + 2],
midPtY
);
}
}
linePositions.push(positions[len - 2], positions[len - 1]);
} else if(trace.line.shape === 'vh') {
linePositions = [];
for(i = 0; i < count - 1; i++) {
if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) {
linePositions.push(NaN);
linePositions.push(NaN);
linePositions.push(NaN);
linePositions.push(NaN);
linePositions.push(NaN, NaN, NaN, NaN);
}
else {
linePositions.push(positions[i * 2]);
linePositions.push(positions[i * 2 + 1]);
linePositions.push(positions[i * 2]);
linePositions.push(positions[i * 2 + 3]);
linePositions.push(positions[i * 2], positions[i * 2 + 1]);
if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) {
linePositions.push(positions[i * 2], positions[i * 2 + 3]);
} else {
linePositions.push(NaN, NaN);
}
}
}
linePositions.push(positions[positions.length - 2]);
linePositions.push(positions[positions.length - 1]);
linePositions.push(positions[len - 2], positions[len - 1]);
} else {
linePositions = positions;
}
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
119 changes: 82 additions & 37 deletions src/traces/scattergl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,39 +256,38 @@ function sceneUpdate(gd, subplot) {

// draw traces in proper order
scene.draw = function draw() {
var i;
for(i = 0; i < scene.count; i++) {
if(scene.fill2d && scene.fillOptions[i]) {
// must do all fills first
scene.fill2d.draw(i);
var count = scene.count;
var fill2d = scene.fill2d;
var error2d = scene.error2d;
var line2d = scene.line2d;
var scatter2d = scene.scatter2d;
var glText = scene.glText;
var select2d = scene.select2d;
var selectBatch = scene.selectBatch;
var unselectBatch = scene.unselectBatch;

for(var i = 0; i < count; i++) {
if(fill2d && scene.fillOrder[i]) {
fill2d.draw(scene.fillOrder[i]);
}
}
for(i = 0; i < scene.count; i++) {
if(scene.line2d && scene.lineOptions[i]) {
scene.line2d.draw(i);
if(line2d && scene.lineOptions[i]) {
line2d.draw(i);
}
if(scene.error2d && scene.errorXOptions[i]) {
scene.error2d.draw(i);
if(error2d) {
if(scene.errorXOptions[i]) error2d.draw(i);
if(scene.errorYOptions[i]) error2d.draw(i + count);
}
if(scene.error2d && scene.errorYOptions[i]) {
scene.error2d.draw(i + scene.count);
if(scatter2d && scene.markerOptions[i] && (!selectBatch || !selectBatch[i])) {
scatter2d.draw(i);
}
if(scene.scatter2d && scene.markerOptions[i] && (!scene.selectBatch || !scene.selectBatch[i])) {
// traces in no-selection mode
scene.scatter2d.draw(i);
if(glText[i] && scene.textOptions[i]) {
glText[i].render();
}
}

// draw traces in selection mode
if(scene.scatter2d && scene.select2d && scene.selectBatch) {
scene.select2d.draw(scene.selectBatch);
scene.scatter2d.draw(scene.unselectBatch);
}

for(i = 0; i < scene.count; i++) {
if(scene.glText[i] && scene.textOptions[i]) {
scene.glText[i].render();
}
if(scatter2d && select2d && selectBatch) {
select2d.draw(selectBatch);
scatter2d.draw(unselectBatch);
}

scene.dirty = false;
Expand Down Expand Up @@ -397,6 +396,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 @@ -405,7 +422,9 @@ function plot(gd, subplot, cdata) {
if(scene.scatter2d) {
scene.scatter2d.update(scene.markerOptions);
}

// fill requires linked traces, so we generate it's positions here
scene.fillOrder = Lib.repeat(null, scene.count);
if(scene.fill2d) {
scene.fillOptions = scene.fillOptions.map(function(fillOptions, i) {
var cdscatter = cdata[i];
Expand All @@ -416,19 +435,46 @@ function plot(gd, subplot, cdata) {
var lineOptions = scene.lineOptions[i];
var last, j;

var fillData = [];
if(trace._ownfill) fillData.push(i);
if(trace._nexttrace) fillData.push(i + 1);
if(fillData.length) scene.fillOrder[i] = fillData;

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 @@ -459,8 +505,7 @@ function plot(gd, subplot, cdata) {
for(i = Math.floor(nextPos.length / 2); i--;) {
var xx = nextPos[i * 2], yy = nextPos[i * 2 + 1];
if(isNaN(xx) || isNaN(yy)) continue;
pos.push(xx);
pos.push(yy);
pos.push(xx, yy);
}
fillOptions.fill = nextTrace.fillcolor;
}
Expand All @@ -486,7 +531,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.
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.
Loading