Skip to content

Commit 2ebc1a9

Browse files
committed
add backoff to line
1 parent 9e14777 commit 2ebc1a9

18 files changed

+491
-23
lines changed

src/traces/scatter/attributes.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,26 @@ module.exports = {
292292
].join(' ')
293293
},
294294
dash: extendFlat({}, dash, {editType: 'style'}),
295+
backoff: { // TODO: do we want to have a similar option for the start of the line? If so what the name should be?
296+
valType: 'number',
297+
min: 0,
298+
dflt: 0,
299+
arrayOk: true,
300+
editType: 'plot',
301+
description: [
302+
'Sets the line back off from the end point of the nth line segment (in px).',
303+
'This option is useful e.g. to avoid overlap with arrowhead markers.',
304+
].join(' ')
305+
},
295306
simplify: {
296307
valType: 'boolean',
297-
dflt: true,
298308
editType: 'plot',
299309
description: [
300310
'Simplifies lines by removing nearly-collinear points. When transitioning',
301311
'lines, it may be desirable to disable this so that the number of points',
302-
'along the resulting SVG path is unaffected.'
312+
'along the resulting SVG path is unaffected.',
313+
'Defaults to *false* when `backoff` is set,',
314+
'otherwise defaults to *true*.'
303315
].join(' ')
304316
},
305317
editType: 'plot'

src/traces/scatter/defaults.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3939
coerce('mode', defaultMode);
4040

4141
if(subTypes.hasLines(traceOut)) {
42-
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
42+
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
4343
handleLineShapeDefaults(traceIn, traceOut, coerce);
4444
coerce('connectgaps');
45-
coerce('line.simplify');
45+
coerce('line.simplify', traceOut.backoff ? false : true);
4646
}
4747

4848
if(subTypes.hasMarkers(traceOut)) {

src/traces/scatter/line_defaults.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ var hasColorscale = require('../../components/colorscale/helpers').hasColorscale
55
var colorscaleDefaults = require('../../components/colorscale/defaults');
66

77
module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) {
8+
if(!opts) opts = {};
9+
810
var markerColor = (traceIn.marker || {}).color;
911

1012
coerce('line.color', defaultColor);
@@ -17,5 +19,7 @@ module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout,
1719
}
1820

1921
coerce('line.width');
20-
if(!(opts || {}).noDash) coerce('line.dash');
22+
23+
if(!opts.noDash) coerce('line.dash');
24+
if(opts.backoff) coerce('line.backoff');
2125
};

src/traces/scatter/line_points.js

+48
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = function linePoints(d, opts) {
1818
var yLog = ya.type === 'log';
1919
var xLen = xa._length;
2020
var yLen = ya._length;
21+
var backoff = opts.backoff;
2122
var connectGaps = opts.connectGaps;
2223
var baseTolerance = opts.baseTolerance;
2324
var shape = opts.shape;
@@ -446,5 +447,52 @@ module.exports = function linePoints(d, opts) {
446447
segments.push(pts.slice(0, pti));
447448
}
448449

450+
if(backoff) {
451+
var newSegments = [];
452+
var arrayBackoff = Lib.isArrayOrTypedArray(backoff);
453+
var lastShapeChar = shape.slice(shape.length - 1);
454+
i = -1;
455+
for(var j = 0; j < segments.length; j++) {
456+
i++;
457+
for(var k = 0; k < segments[j].length - 1; k++) {
458+
var start = segments[j][k];
459+
var end = segments[j][k + 1];
460+
461+
var x1 = start[0];
462+
var y1 = start[1];
463+
464+
var x2 = end[0];
465+
var y2 = end[1];
466+
467+
var dx = x2 - x1;
468+
var dy = y2 - y1;
469+
470+
var t = Math.atan2(dy, dx);
471+
if(lastShapeChar === 'h') {
472+
t = dx < 0 ? Math.PI : 0;
473+
} else if(lastShapeChar === 'v') {
474+
t = dy > 0 ? Math.PI / 2 : -Math.PI / 2;
475+
}
476+
477+
var b = arrayBackoff ? backoff[i] : backoff;
478+
479+
var x = x2 - b * Math.cos(t);
480+
var y = y2 - b * Math.sin(t);
481+
482+
if(
483+
((x <= x2 && x >= x1) || (x >= x2 && x <= x1)) &&
484+
((y <= y2 && y >= y1) || (y >= y2 && y <= y1))
485+
) {
486+
if(!newSegments[j]) newSegments[j] = [];
487+
488+
newSegments[j].push(start);
489+
newSegments[j].push([x, y]);
490+
}
491+
}
492+
}
493+
494+
return newSegments;
495+
}
496+
449497
return segments;
450498
};

src/traces/scatter/plot.js

+1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
212212
connectGaps: trace.connectgaps,
213213
baseTolerance: Math.max(line.width || 1, 3) / 4,
214214
shape: line.shape,
215+
backoff: line.backoff,
215216
simplify: line.simplify,
216217
fill: trace.fill
217218
});

src/traces/scattercarpet/attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module.exports = {
6161
color: scatterLineAttrs.color,
6262
width: scatterLineAttrs.width,
6363
dash: scatterLineAttrs.dash,
64+
backoff: scatterLineAttrs.backoff,
6465
shape: extendFlat({}, scatterLineAttrs.shape,
6566
{values: ['linear', 'spline']}),
6667
smoothing: scatterLineAttrs.smoothing,

src/traces/scattercarpet/defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
4242
coerce('mode', defaultMode);
4343

4444
if(subTypes.hasLines(traceOut)) {
45-
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
45+
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
4646
handleLineShapeDefaults(traceIn, traceOut, coerce);
4747
coerce('connectgaps');
4848
}

src/traces/scatterpolar/attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ module.exports = {
8282
color: lineAttrs.color,
8383
width: lineAttrs.width,
8484
dash: lineAttrs.dash,
85+
backoff: lineAttrs.backoff,
8586
shape: extendFlat({}, lineAttrs.shape, {
8687
values: ['linear', 'spline']
8788
}),

src/traces/scatterpolar/defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
3030
if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
3131

3232
if(subTypes.hasLines(traceOut)) {
33-
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
33+
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
3434
handleLineShapeDefaults(traceIn, traceOut, coerce);
3535
coerce('connectgaps');
3636
}

src/traces/scattersmith/attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ module.exports = {
3838
color: lineAttrs.color,
3939
width: lineAttrs.width,
4040
dash: lineAttrs.dash,
41+
backoff: lineAttrs.backoff,
4142
shape: extendFlat({}, lineAttrs.shape, {
4243
values: ['linear', 'spline']
4344
}),

src/traces/scattersmith/defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
2929
if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
3030

3131
if(subTypes.hasLines(traceOut)) {
32-
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
32+
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
3333
handleLineShapeDefaults(traceIn, traceOut, coerce);
3434
coerce('connectgaps');
3535
}

src/traces/scatterternary/attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ module.exports = {
8989
color: scatterLineAttrs.color,
9090
width: scatterLineAttrs.width,
9191
dash: dash,
92+
backoff: scatterLineAttrs.backoff,
9293
shape: extendFlat({}, scatterLineAttrs.shape,
9394
{values: ['linear', 'spline']}),
9495
smoothing: scatterLineAttrs.smoothing,

src/traces/scatterternary/defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
5656
coerce('mode', defaultMode);
5757

5858
if(subTypes.hasLines(traceOut)) {
59-
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
59+
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
6060
handleLineShapeDefaults(traceIn, traceOut, coerce);
6161
coerce('connectgaps');
6262
}
Loading
81.9 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
{
2+
"data": [
3+
{
4+
"line": {
5+
"backoff": 10,
6+
"width": 5,
7+
"shape": "linear"
8+
},
9+
"mode": "lines+markers",
10+
"name": "'linear'",
11+
"type": "scatter",
12+
"marker": {
13+
"angleref": "previous",
14+
"symbol": "arrow-wide",
15+
"size": 20
16+
},
17+
"x": [
18+
1,
19+
2,
20+
3,
21+
4,
22+
5
23+
],
24+
"y": [
25+
1,
26+
3,
27+
2,
28+
3,
29+
1
30+
]
31+
},
32+
{
33+
"line": {
34+
"backoff": 10,
35+
"width": 5,
36+
"shape": "spline"
37+
},
38+
"mode": "lines+markers",
39+
"name": "'spline'",
40+
"type": "scatter",
41+
"marker": {
42+
"angleref": "previous",
43+
"symbol": "arrow-wide",
44+
"size": 20
45+
},
46+
"x": [
47+
1,
48+
2,
49+
3,
50+
4,
51+
5
52+
],
53+
"y": [
54+
6,
55+
8,
56+
7,
57+
8,
58+
6
59+
]
60+
},
61+
{
62+
"line": {
63+
"backoff": 10,
64+
"width": 5,
65+
"shape": "vhv"
66+
},
67+
"mode": "lines+markers",
68+
"name": "'vhv'",
69+
"type": "scatter",
70+
"marker": {
71+
"angleref": "previous",
72+
"symbol": "arrow-wide",
73+
"size": 20
74+
},
75+
"x": [
76+
1,
77+
2,
78+
3,
79+
4,
80+
5
81+
],
82+
"y": [
83+
11,
84+
13,
85+
12,
86+
13,
87+
11
88+
]
89+
},
90+
{
91+
"line": {
92+
"backoff": 10,
93+
"width": 5,
94+
"shape": "hvh"
95+
},
96+
"mode": "lines+markers",
97+
"name": "'hvh'",
98+
"type": "scatter",
99+
"marker": {
100+
"angleref": "previous",
101+
"symbol": "arrow-wide",
102+
"size": 20
103+
},
104+
"x": [
105+
1,
106+
2,
107+
3,
108+
4,
109+
5
110+
],
111+
"y": [
112+
16,
113+
18,
114+
17,
115+
18,
116+
16
117+
]
118+
},
119+
{
120+
"line": {
121+
"backoff": 10,
122+
"width": 5,
123+
"shape": "vh"
124+
},
125+
"mode": "lines+markers",
126+
"name": "'vh'",
127+
"type": "scatter",
128+
"marker": {
129+
"angleref": "previous",
130+
"symbol": "arrow-wide",
131+
"size": 20
132+
},
133+
"x": [
134+
1,
135+
2,
136+
3,
137+
4,
138+
5
139+
],
140+
"y": [
141+
21,
142+
23,
143+
22,
144+
23,
145+
21
146+
]
147+
},
148+
{
149+
"line": {
150+
"backoff": 10,
151+
"width": 5,
152+
"shape": "hv"
153+
},
154+
"mode": "lines+markers",
155+
"name": "'hv'",
156+
"type": "scatter",
157+
"marker": {
158+
"angleref": "previous",
159+
"symbol": "arrow-wide",
160+
"size": 20
161+
},
162+
"x": [
163+
1,
164+
2,
165+
3,
166+
4,
167+
5
168+
],
169+
"y": [
170+
26,
171+
28,
172+
27,
173+
28,
174+
26
175+
]
176+
}
177+
],
178+
"layout": {
179+
"title": {
180+
"text" : "line shape and arrows with backoff"
181+
},
182+
"legend": {
183+
"orientation": "h"
184+
},
185+
"height": 700,
186+
"width": 700
187+
}
188+
}

0 commit comments

Comments
 (0)