Skip to content

Commit 961fed4

Browse files
committed
Merge branch 'master' into pr-16190-ohlc-equal-open-close
2 parents c4f7703 + 30eb865 commit 961fed4

File tree

133 files changed

+8301
-7862
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+8301
-7862
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"gl-plot3d": "^1.5.4",
7575
"gl-pointcloud2d": "^1.0.0",
7676
"gl-scatter2d": "^1.2.2",
77-
"gl-scatter2d-sdf": "1.3.4",
77+
"gl-scatter2d-sdf": "^1.3.9",
7878
"gl-scatter3d": "^1.0.4",
7979
"gl-select-box": "^1.0.1",
8080
"gl-shader": "4.2.0",

src/components/annotations/draw.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ function drawOne(gd, index) {
112112
gd.emit('plotly_clickannotation', {
113113
index: index,
114114
annotation: optionsIn,
115-
fullAnnotation: options
115+
fullAnnotation: options,
116+
event: d3.event
116117
});
117118
});
118119

src/components/drawing/index.js

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
var d3 = require('d3');
1313
var isNumeric = require('fast-isnumeric');
14+
var tinycolor = require('tinycolor2');
1415

1516
var Registry = require('../../registry');
1617
var Color = require('../color');
@@ -202,7 +203,7 @@ drawing.symbolNumber = function(v) {
202203
return Math.floor(Math.max(v, 0));
203204
};
204205

205-
function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerLine) {
206+
function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerLine, gd) {
206207
// only scatter & box plots get marker path and opacity
207208
// bars, histograms don't
208209
if(Registry.traceIs(trace, 'symbols')) {
@@ -237,6 +238,8 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
237238
});
238239
}
239240

241+
var perPointGradient = false;
242+
240243
// 'so' is suspected outliers, for box plots
241244
var fillColor,
242245
lineColor,
@@ -256,8 +259,12 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
256259
else if(Array.isArray(markerLine.color)) lineColor = Color.defaultLine;
257260
else lineColor = markerLine.color;
258261

262+
if(Array.isArray(marker.color)) {
263+
fillColor = Color.defaultLine;
264+
perPointGradient = true;
265+
}
266+
259267
if('mc' in d) fillColor = d.mcc = markerScale(d.mc);
260-
else if(Array.isArray(marker.color)) fillColor = Color.defaultLine;
261268
else fillColor = marker.color || 'rgba(0,0,0,0)';
262269
}
263270

@@ -271,24 +278,93 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
271278
});
272279
}
273280
else {
274-
sel.style('stroke-width', lineWidth + 'px')
275-
.call(Color.fill, fillColor);
281+
sel.style('stroke-width', lineWidth + 'px');
282+
283+
var markerGradient = marker.gradient;
284+
285+
var gradientType = d.mgt;
286+
if(gradientType) perPointGradient = true;
287+
else gradientType = markerGradient && markerGradient.type;
288+
289+
if(gradientType && gradientType !== 'none') {
290+
var gradientColor = d.mgc;
291+
if(gradientColor) perPointGradient = true;
292+
else gradientColor = markerGradient.color;
293+
294+
var gradientID = 'g' + gd._fullLayout._uid + '-' + trace.uid;
295+
if(perPointGradient) gradientID += '-' + d.i;
296+
297+
sel.call(drawing.gradient, gd, gradientID, gradientType, fillColor, gradientColor);
298+
}
299+
else {
300+
sel.call(Color.fill, fillColor);
301+
}
302+
276303
if(lineWidth) {
277304
sel.call(Color.stroke, lineColor);
278305
}
279306
}
280307
}
281308

282-
drawing.singlePointStyle = function(d, sel, trace) {
283-
var marker = trace.marker,
284-
markerLine = marker.line;
309+
var HORZGRADIENT = {x1: 1, x2: 0, y1: 0, y2: 0};
310+
var VERTGRADIENT = {x1: 0, x2: 0, y1: 1, y2: 0};
285311

286-
// allow array marker and marker line colors to be
287-
// scaled by given max and min to colorscales
288-
var markerScale = drawing.tryColorscale(marker, ''),
289-
lineScale = drawing.tryColorscale(marker, 'line');
312+
drawing.gradient = function(sel, gd, gradientID, type, color1, color2) {
313+
var gradient = gd._fullLayout._defs.select('.gradients')
314+
.selectAll('#' + gradientID)
315+
.data([type + color1 + color2], Lib.identity);
316+
317+
gradient.exit().remove();
290318

291-
singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerLine);
319+
gradient.enter()
320+
.append(type === 'radial' ? 'radialGradient' : 'linearGradient')
321+
.each(function() {
322+
var el = d3.select(this);
323+
if(type === 'horizontal') el.attr(HORZGRADIENT);
324+
else if(type === 'vertical') el.attr(VERTGRADIENT);
325+
326+
el.attr('id', gradientID);
327+
328+
var tc1 = tinycolor(color1);
329+
var tc2 = tinycolor(color2);
330+
331+
el.append('stop').attr({
332+
offset: '0%',
333+
'stop-color': Color.tinyRGB(tc2),
334+
'stop-opacity': tc2.getAlpha()
335+
});
336+
337+
el.append('stop').attr({
338+
offset: '100%',
339+
'stop-color': Color.tinyRGB(tc1),
340+
'stop-opacity': tc1.getAlpha()
341+
});
342+
});
343+
344+
sel.style({
345+
fill: 'url(#' + gradientID + ')',
346+
'fill-opacity': null
347+
});
348+
};
349+
350+
/*
351+
* Make the gradients container and clear out any previous gradients.
352+
* We never collect all the gradients we need in one place,
353+
* so we can't ever remove gradients that have stopped being useful,
354+
* except all at once before a full redraw.
355+
* The upside of this is arbitrary points can share gradient defs
356+
*/
357+
drawing.initGradients = function(gd) {
358+
var gradientsGroup = gd._fullLayout._defs.selectAll('.gradients').data([0]);
359+
gradientsGroup.enter().append('g').classed('gradients', true);
360+
361+
gradientsGroup.selectAll('linearGradient,radialGradient').remove();
362+
};
363+
364+
drawing.singlePointStyle = function(d, sel, trace, markerScale, lineScale, gd) {
365+
var marker = trace.marker;
366+
367+
singlePointStyle(d, sel, trace, markerScale, lineScale, marker, marker.line, gd);
292368

293369
};
294370

@@ -298,11 +374,12 @@ drawing.pointStyle = function(s, trace) {
298374
// allow array marker and marker line colors to be
299375
// scaled by given max and min to colorscales
300376
var marker = trace.marker;
301-
var markerScale = drawing.tryColorscale(marker, ''),
302-
lineScale = drawing.tryColorscale(marker, 'line');
377+
var markerScale = drawing.tryColorscale(marker, '');
378+
var lineScale = drawing.tryColorscale(marker, 'line');
379+
var gd = Lib.getPlotDiv(s.node());
303380

304381
s.each(function(d) {
305-
drawing.singlePointStyle(d, d3.select(this), trace, markerScale, lineScale);
382+
drawing.singlePointStyle(d, d3.select(this), trace, markerScale, lineScale, gd);
306383
});
307384
};
308385

@@ -512,6 +589,7 @@ drawing.makeTester = function(gd) {
512589
// always returns a copy of the bbox, so the caller can modify it safely
513590
var savedBBoxes = [],
514591
maxSavedBBoxes = 10000;
592+
515593
drawing.bBox = function(node) {
516594
// cache elements we've already measured so we don't have to
517595
// remeasure the same thing many times
@@ -520,32 +598,36 @@ drawing.bBox = function(node) {
520598
return Lib.extendFlat({}, savedBBoxes[saveNum.value]);
521599
}
522600

523-
var test3 = d3.select('#js-plotly-tester'),
524-
tester = test3.node();
601+
if(!drawing.test3) {
602+
drawing.test3 = d3.select('#js-plotly-tester');
603+
drawing.tester = drawing.test3.node();
604+
}
525605

526606
// copy the node to test into the tester
527607
var testNode = node.cloneNode(true);
528-
tester.appendChild(testNode);
608+
drawing.tester.appendChild(testNode);
529609
// standardize its position... do we really want to do this?
530610
d3.select(testNode).attr({
531611
x: 0,
532612
y: 0,
533613
transform: ''
534614
});
535615

536-
var testRect = testNode.getBoundingClientRect(),
537-
refRect = test3.select('.js-reference-point')
616+
var testRect = testNode.getBoundingClientRect();
617+
if(!drawing.refRect) {
618+
drawing.refRect = drawing.test3.select('.js-reference-point')
538619
.node().getBoundingClientRect();
620+
}
539621

540-
tester.removeChild(testNode);
622+
drawing.tester.removeChild(testNode);
541623

542624
var bb = {
543625
height: testRect.height,
544626
width: testRect.width,
545-
left: testRect.left - refRect.left,
546-
top: testRect.top - refRect.top,
547-
right: testRect.right - refRect.left,
548-
bottom: testRect.bottom - refRect.top
627+
left: testRect.left - drawing.refRect.left,
628+
top: testRect.top - drawing.refRect.top,
629+
right: testRect.right - drawing.refRect.left,
630+
bottom: testRect.bottom - drawing.refRect.top
549631
};
550632

551633
// make sure we don't have too many saved boxes,

src/components/legend/draw.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,9 @@ function handleClick(g, gd, numClicks) {
514514
allTraces.push(i);
515515
// Allow the legendonly state through for *all* trace types (including
516516
// carpet for which it's overridden with true/false in supplyDefaults)
517-
traceVisibility.push('legendonly');
517+
traceVisibility.push(
518+
Registry.traceIs(fullData[i], 'notLegendIsolatable') ? true : 'legendonly'
519+
);
518520
}
519521

520522
if(legendgroup === '') {

src/lib/svg_text_utils.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ var stringMappings = require('../constants/string_mappings');
1919

2020
// Append SVG
2121

22+
var parser = new DOMParser();
23+
2224
d3.selection.prototype.appendSVG = function(_svgString) {
2325
var skeleton = [
2426
'<svg xmlns="', xmlnsNamespaces.svg, '" ',
@@ -27,7 +29,7 @@ d3.selection.prototype.appendSVG = function(_svgString) {
2729
'</svg>'
2830
].join('');
2931

30-
var dom = new DOMParser().parseFromString(skeleton, 'application/xml'),
32+
var dom = parser.parseFromString(skeleton, 'application/xml'),
3133
childNode = dom.documentElement.firstChild;
3234

3335
while(childNode) {

src/plot_api/manage_arrays.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var nestedProperty = require('../lib/nested_property');
1313
var isPlainObject = require('../lib/is_plain_object');
1414
var noop = require('../lib/noop');
1515
var Loggers = require('../lib/loggers');
16+
var sorterAsc = require('../lib/search').sorterAsc;
1617
var Registry = require('../registry');
1718

1819

@@ -101,7 +102,7 @@ exports.applyContainerArrayChanges = function applyContainerArrayChanges(gd, np,
101102
return true;
102103
}
103104

104-
var componentNums = Object.keys(edits).map(Number).sort(),
105+
var componentNums = Object.keys(edits).map(Number).sort(sorterAsc),
105106
componentArrayIn = np.get(),
106107
componentArray = componentArrayIn || [],
107108
// componentArrayFull is used just to keep splices in line between

src/plot_api/plot_api.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ Plotly.plot = function(gd, data, layout, config) {
153153
makePlotFramework(gd);
154154
}
155155

156+
// clear gradient defs on each .plot call, because we know we'll loop through all traces
157+
Drawing.initGradients(gd);
158+
156159
// save initial show spikes once per graph
157160
if(graphWasEmpty) Plotly.Axes.saveShowSpikeInitial(gd);
158161

@@ -285,7 +288,8 @@ Plotly.plot = function(gd, data, layout, config) {
285288
// Now plot the data
286289
function drawData() {
287290
var calcdata = gd.calcdata,
288-
i;
291+
i,
292+
rangesliderContainers = fullLayout._infolayer.selectAll('g.rangeslider-container');
289293

290294
// in case of traces that were heatmaps or contour maps
291295
// previously, remove them and their colorbars explicitly
@@ -305,7 +309,7 @@ Plotly.plot = function(gd, data, layout, config) {
305309
.selectAll(query)
306310
.remove();
307311

308-
fullLayout._infolayer.selectAll('g.rangeslider-container')
312+
rangesliderContainers
309313
.selectAll(query)
310314
.remove();
311315
}

src/plots/gl2d/camera.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ function createCamera(scene) {
110110
result.boxEnd[1] = dataY;
111111

112112
// we need to mark the box as initialized right away
113-
// so that we can tell the start and end pionts apart
113+
// so that we can tell the start and end points apart
114114
result.boxInited = true;
115115

116116
// but don't actually enable the box until the cursor moves
@@ -189,6 +189,10 @@ function createCamera(scene) {
189189
result.boxEnabled = false;
190190
result.boxInited = false;
191191
}
192+
// if box was inited but button released then - reset the box
193+
else if(result.boxInited) {
194+
result.boxInited = false;
195+
}
192196
break;
193197

194198
case 'pan':

src/traces/scatter/arrays_to_calcdata.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ var Lib = require('../../lib');
1515
// arrayOk attributes, merge them into calcdata array
1616
module.exports = function arraysToCalcdata(cd, trace) {
1717

18+
// so each point knows which index it originally came from
19+
for(var i = 0; i < cd.length; i++) cd[i].i = i;
20+
1821
Lib.mergeArray(trace.text, cd, 'tx');
1922
Lib.mergeArray(trace.hovertext, cd, 'htx');
2023
Lib.mergeArray(trace.customdata, cd, 'data');
@@ -37,5 +40,11 @@ module.exports = function arraysToCalcdata(cd, trace) {
3740
Lib.mergeArray(markerLine.color, cd, 'mlc');
3841
Lib.mergeArray(markerLine.width, cd, 'mlw');
3942
}
43+
44+
var markerGradient = marker.gradient;
45+
if(markerGradient && markerGradient.type !== 'none') {
46+
Lib.mergeArray(markerGradient.type, cd, 'mgt');
47+
Lib.mergeArray(markerGradient.color, cd, 'mgc');
48+
}
4049
}
4150
};

src/traces/scatter/attributes.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,29 @@ module.exports = {
311311
}
312312
},
313313
colorAttributes('marker.line')
314-
)
314+
),
315+
gradient: {
316+
type: {
317+
valType: 'enumerated',
318+
values: ['radial', 'horizontal', 'vertical', 'none'],
319+
arrayOk: true,
320+
dflt: 'none',
321+
role: 'style',
322+
description: [
323+
'Sets the type of gradient used to fill the markers'
324+
].join(' ')
325+
},
326+
color: {
327+
valType: 'color',
328+
arrayOk: true,
329+
role: 'style',
330+
description: [
331+
'Sets the final color of the gradient fill:',
332+
'the center color for radial, the right for horizontal,',
333+
'or the bottom for vertical.',
334+
].join(' ')
335+
}
336+
}
315337
},
316338
colorAttributes('marker')
317339
),

src/traces/scatter/defaults.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
5050
}
5151

5252
if(subTypes.hasMarkers(traceOut)) {
53-
handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce);
53+
handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true});
5454
}
5555

5656
if(subTypes.hasText(traceOut)) {

0 commit comments

Comments
 (0)