Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5a24245

Browse filesBrowse files
authored
Merge pull request #3087 from plotly/etienne-scattergl-ordering
Scattergl improvements for: fill tozero with bad values fix, fills layering fix, add some line.shape values
2 parents 1539fea + d708132 commit 5a24245
Copy full SHA for 5a24245
Expand file treeCollapse file tree

15 files changed

+701
-71
lines changed

‎src/traces/scatter/link_traces.js

Copy file name to clipboardExpand all lines: src/traces/scatter/link_traces.js
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,16 @@ module.exports = function linkTraces(gd, plotinfo, cdscatter) {
7575
}
7676
}
7777

78+
if(trace.fill && (
79+
trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' ||
80+
(trace.fill.substr(0, 2) === 'to' && !trace._prevtrace))
81+
) {
82+
trace._ownfill = true;
83+
}
84+
7885
prevtraces[group] = trace;
7986
} else {
80-
trace._prevtrace = trace._nexttrace = null;
87+
trace._prevtrace = trace._nexttrace = trace._ownfill = null;
8188
}
8289
}
8390

‎src/traces/scatter/plot.js

Copy file name to clipboardExpand all lines: src/traces/scatter/plot.js
+3-12Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,10 @@ function createFills(gd, traceJoin, plotinfo) {
9393
var trace = d[0].trace;
9494

9595
var fillData = [];
96-
if(trace.fill && (trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' ||
97-
(trace.fill.substr(0, 2) === 'to' && !trace._prevtrace))
98-
) {
99-
fillData = ['_ownFill'];
100-
}
101-
if(trace._nexttrace) {
102-
// make the fill-to-next path now for the NEXT trace, so it shows
103-
// behind both lines.
104-
fillData.push('_nextFill');
105-
}
96+
if(trace._ownfill) fillData.push('_ownFill');
97+
if(trace._nexttrace) fillData.push('_nextFill');
10698

107-
var fillJoin = fills.selectAll('g')
108-
.data(fillData, identity);
99+
var fillJoin = fills.selectAll('g').data(fillData, identity);
109100

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

‎src/traces/scattergl/attributes.js

Copy file name to clipboardExpand all lines: src/traces/scattergl/attributes.js
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ var attrs = module.exports = overrideAll({
4646
line: {
4747
color: scatterLineAttrs.color,
4848
width: scatterLineAttrs.width,
49+
shape: {
50+
valType: 'enumerated',
51+
values: ['linear', 'hv', 'vh', 'hvh', 'vhv'],
52+
dflt: 'linear',
53+
role: 'style',
54+
editType: 'plot',
55+
description: [
56+
'Determines the line shape.',
57+
'The values correspond to step-wise line shapes.'
58+
].join(' ')
59+
},
4960
dash: {
5061
valType: 'enumerated',
5162
values: Object.keys(DASHES),

‎src/traces/scattergl/convert.js

Copy file name to clipboardExpand all lines: src/traces/scattergl/convert.js
+65-21Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,8 @@ function getSymbolSdf(symbol) {
385385
}
386386

387387
function convertLinePositions(gd, trace, positions) {
388-
var count = positions.length / 2;
388+
var len = positions.length;
389+
var count = len / 2;
389390
var linePositions;
390391
var i;
391392

@@ -394,38 +395,81 @@ function convertLinePositions(gd, trace, positions) {
394395
linePositions = [];
395396
for(i = 0; i < count - 1; i++) {
396397
if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) {
397-
linePositions.push(NaN);
398-
linePositions.push(NaN);
399-
linePositions.push(NaN);
400-
linePositions.push(NaN);
398+
linePositions.push(NaN, NaN, NaN, NaN);
399+
} else {
400+
linePositions.push(positions[i * 2], positions[i * 2 + 1]);
401+
if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) {
402+
linePositions.push(positions[i * 2 + 2], positions[i * 2 + 1]);
403+
} else {
404+
linePositions.push(NaN, NaN);
405+
}
406+
}
407+
}
408+
linePositions.push(positions[len - 2], positions[len - 1]);
409+
} else if(trace.line.shape === 'hvh') {
410+
linePositions = [];
411+
for(i = 0; i < count - 1; i++) {
412+
if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) {
413+
if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) {
414+
linePositions.push(positions[i * 2], positions[i * 2 + 1]);
415+
} else {
416+
linePositions.push(NaN, NaN);
417+
}
418+
linePositions.push(NaN, NaN);
401419
}
402420
else {
403-
linePositions.push(positions[i * 2]);
404-
linePositions.push(positions[i * 2 + 1]);
405-
linePositions.push(positions[i * 2 + 2]);
406-
linePositions.push(positions[i * 2 + 1]);
421+
var midPtX = (positions[i * 2] + positions[i * 2 + 2]) / 2;
422+
linePositions.push(
423+
positions[i * 2],
424+
positions[i * 2 + 1],
425+
midPtX,
426+
positions[i * 2 + 1],
427+
midPtX,
428+
positions[i * 2 + 3]
429+
);
407430
}
408431
}
409-
linePositions.push(positions[positions.length - 2]);
410-
linePositions.push(positions[positions.length - 1]);
432+
linePositions.push(positions[len - 2], positions[len - 1]);
433+
} else if(trace.line.shape === 'vhv') {
434+
linePositions = [];
435+
for(i = 0; i < count - 1; i++) {
436+
if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) {
437+
if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) {
438+
linePositions.push(positions[i * 2], positions[i * 2 + 1]);
439+
} else {
440+
linePositions.push(NaN, NaN);
441+
}
442+
linePositions.push(NaN, NaN);
443+
}
444+
else {
445+
var midPtY = (positions[i * 2 + 1] + positions[i * 2 + 3]) / 2;
446+
linePositions.push(
447+
positions[i * 2],
448+
positions[i * 2 + 1],
449+
positions[i * 2],
450+
midPtY,
451+
positions[i * 2 + 2],
452+
midPtY
453+
);
454+
}
455+
}
456+
linePositions.push(positions[len - 2], positions[len - 1]);
411457
} else if(trace.line.shape === 'vh') {
412458
linePositions = [];
413459
for(i = 0; i < count - 1; i++) {
414460
if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) {
415-
linePositions.push(NaN);
416-
linePositions.push(NaN);
417-
linePositions.push(NaN);
418-
linePositions.push(NaN);
461+
linePositions.push(NaN, NaN, NaN, NaN);
419462
}
420463
else {
421-
linePositions.push(positions[i * 2]);
422-
linePositions.push(positions[i * 2 + 1]);
423-
linePositions.push(positions[i * 2]);
424-
linePositions.push(positions[i * 2 + 3]);
464+
linePositions.push(positions[i * 2], positions[i * 2 + 1]);
465+
if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) {
466+
linePositions.push(positions[i * 2], positions[i * 2 + 3]);
467+
} else {
468+
linePositions.push(NaN, NaN);
469+
}
425470
}
426471
}
427-
linePositions.push(positions[positions.length - 2]);
428-
linePositions.push(positions[positions.length - 1]);
472+
linePositions.push(positions[len - 2], positions[len - 1]);
429473
} else {
430474
linePositions = positions;
431475
}

‎src/traces/scattergl/defaults.js

Copy file name to clipboardExpand all lines: src/traces/scattergl/defaults.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
4242
if(subTypes.hasLines(traceOut)) {
4343
coerce('connectgaps');
4444
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
45+
coerce('line.shape');
4546
}
4647

4748
if(subTypes.hasMarkers(traceOut)) {

‎src/traces/scattergl/index.js

Copy file name to clipboardExpand all lines: src/traces/scattergl/index.js
+82-37Lines changed: 82 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -256,39 +256,38 @@ function sceneUpdate(gd, subplot) {
256256

257257
// draw traces in proper order
258258
scene.draw = function draw() {
259-
var i;
260-
for(i = 0; i < scene.count; i++) {
261-
if(scene.fill2d && scene.fillOptions[i]) {
262-
// must do all fills first
263-
scene.fill2d.draw(i);
259+
var count = scene.count;
260+
var fill2d = scene.fill2d;
261+
var error2d = scene.error2d;
262+
var line2d = scene.line2d;
263+
var scatter2d = scene.scatter2d;
264+
var glText = scene.glText;
265+
var select2d = scene.select2d;
266+
var selectBatch = scene.selectBatch;
267+
var unselectBatch = scene.unselectBatch;
268+
269+
for(var i = 0; i < count; i++) {
270+
if(fill2d && scene.fillOrder[i]) {
271+
fill2d.draw(scene.fillOrder[i]);
264272
}
265-
}
266-
for(i = 0; i < scene.count; i++) {
267-
if(scene.line2d && scene.lineOptions[i]) {
268-
scene.line2d.draw(i);
273+
if(line2d && scene.lineOptions[i]) {
274+
line2d.draw(i);
269275
}
270-
if(scene.error2d && scene.errorXOptions[i]) {
271-
scene.error2d.draw(i);
276+
if(error2d) {
277+
if(scene.errorXOptions[i]) error2d.draw(i);
278+
if(scene.errorYOptions[i]) error2d.draw(i + count);
272279
}
273-
if(scene.error2d && scene.errorYOptions[i]) {
274-
scene.error2d.draw(i + scene.count);
280+
if(scatter2d && scene.markerOptions[i] && (!selectBatch || !selectBatch[i])) {
281+
scatter2d.draw(i);
275282
}
276-
if(scene.scatter2d && scene.markerOptions[i] && (!scene.selectBatch || !scene.selectBatch[i])) {
277-
// traces in no-selection mode
278-
scene.scatter2d.draw(i);
283+
if(glText[i] && scene.textOptions[i]) {
284+
glText[i].render();
279285
}
280286
}
281287

282-
// draw traces in selection mode
283-
if(scene.scatter2d && scene.select2d && scene.selectBatch) {
284-
scene.select2d.draw(scene.selectBatch);
285-
scene.scatter2d.draw(scene.unselectBatch);
286-
}
287-
288-
for(i = 0; i < scene.count; i++) {
289-
if(scene.glText[i] && scene.textOptions[i]) {
290-
scene.glText[i].render();
291-
}
288+
if(scatter2d && select2d && selectBatch) {
289+
select2d.draw(selectBatch);
290+
scatter2d.draw(unselectBatch);
292291
}
293292

294293
scene.dirty = false;
@@ -397,6 +396,24 @@ function plot(gd, subplot, cdata) {
397396
}
398397
if(scene.line2d) {
399398
scene.line2d.update(scene.lineOptions);
399+
scene.lineOptions = scene.lineOptions.map(function(lineOptions) {
400+
if(lineOptions && lineOptions.positions) {
401+
var pos = [], srcPos = lineOptions.positions;
402+
403+
var firstptdef = 0;
404+
while(isNaN(srcPos[firstptdef]) || isNaN(srcPos[firstptdef + 1])) {
405+
firstptdef += 2;
406+
}
407+
var lastptdef = srcPos.length - 2;
408+
while(isNaN(srcPos[lastptdef]) || isNaN(srcPos[lastptdef + 1])) {
409+
lastptdef += -2;
410+
}
411+
pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2));
412+
lineOptions.positions = pos;
413+
}
414+
return lineOptions;
415+
});
416+
scene.line2d.update(scene.lineOptions);
400417
}
401418
if(scene.error2d) {
402419
var errorBatch = (scene.errorXOptions || []).concat(scene.errorYOptions || []);
@@ -405,7 +422,9 @@ function plot(gd, subplot, cdata) {
405422
if(scene.scatter2d) {
406423
scene.scatter2d.update(scene.markerOptions);
407424
}
425+
408426
// fill requires linked traces, so we generate it's positions here
427+
scene.fillOrder = Lib.repeat(null, scene.count);
409428
if(scene.fill2d) {
410429
scene.fillOptions = scene.fillOptions.map(function(fillOptions, i) {
411430
var cdscatter = cdata[i];
@@ -416,19 +435,46 @@ function plot(gd, subplot, cdata) {
416435
var lineOptions = scene.lineOptions[i];
417436
var last, j;
418437

438+
var fillData = [];
439+
if(trace._ownfill) fillData.push(i);
440+
if(trace._nexttrace) fillData.push(i + 1);
441+
if(fillData.length) scene.fillOrder[i] = fillData;
442+
419443
var pos = [], srcPos = (lineOptions && lineOptions.positions) || stash.positions;
420444

421445
if(trace.fill === 'tozeroy') {
422-
pos = [srcPos[0], 0];
423-
pos = pos.concat(srcPos);
424-
pos.push(srcPos[srcPos.length - 2]);
425-
pos.push(0);
446+
var firstpdef = 0;
447+
while(isNaN(srcPos[firstpdef + 1])) {
448+
firstpdef += 2;
449+
}
450+
var lastpdef = srcPos.length - 2;
451+
while(isNaN(srcPos[lastpdef + 1])) {
452+
lastpdef += -2;
453+
}
454+
if(srcPos[firstpdef + 1] !== 0) {
455+
pos = [ srcPos[firstpdef], 0 ];
456+
}
457+
pos = pos.concat(srcPos.slice(firstpdef, lastpdef + 2));
458+
if(srcPos[lastpdef + 1] !== 0) {
459+
pos = pos.concat([ srcPos[lastpdef], 0 ]);
460+
}
426461
}
427462
else if(trace.fill === 'tozerox') {
428-
pos = [0, srcPos[1]];
429-
pos = pos.concat(srcPos);
430-
pos.push(0);
431-
pos.push(srcPos[srcPos.length - 1]);
463+
var firstptdef = 0;
464+
while(isNaN(srcPos[firstptdef])) {
465+
firstptdef += 2;
466+
}
467+
var lastptdef = srcPos.length - 2;
468+
while(isNaN(srcPos[lastptdef])) {
469+
lastptdef += -2;
470+
}
471+
if(srcPos[firstptdef] !== 0) {
472+
pos = [ 0, srcPos[firstptdef + 1] ];
473+
}
474+
pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2));
475+
if(srcPos[lastptdef] !== 0) {
476+
pos = pos.concat([ 0, srcPos[lastptdef + 1]]);
477+
}
432478
}
433479
else if(trace.fill === 'toself' || trace.fill === 'tonext') {
434480
pos = [];
@@ -459,8 +505,7 @@ function plot(gd, subplot, cdata) {
459505
for(i = Math.floor(nextPos.length / 2); i--;) {
460506
var xx = nextPos[i * 2], yy = nextPos[i * 2 + 1];
461507
if(isNaN(xx) || isNaN(yy)) continue;
462-
pos.push(xx);
463-
pos.push(yy);
508+
pos.push(xx, yy);
464509
}
465510
fillOptions.fill = nextTrace.fillcolor;
466511
}
@@ -486,7 +531,7 @@ function plot(gd, subplot, cdata) {
486531
pos = pos.concat(prevLinePos);
487532
fillOptions.hole = hole;
488533
}
489-
534+
fillOptions.fillmode = trace.fill;
490535
fillOptions.opacity = trace.opacity;
491536
fillOptions.positions = pos;
492537

10 Bytes
Loading
Loading
57.9 KB
Loading
Loading
77.2 KB
Loading

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.