Skip to content

Commit 29c369b

Browse files
committed
Merge commit 'refs/pull/1256/head' of github.com:plotly/plotly.js into pr1256-parcoords-etienne
2 parents b285faa + f63c36f commit 29c369b

File tree

12 files changed

+55
-38
lines changed

12 files changed

+55
-38
lines changed

src/traces/parcoords/attributes.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ module.exports = {
5656
},
5757
tickvals: axesAttrs.tickvals,
5858
ticktext: axesAttrs.ticktext,
59+
tickformat: {
60+
valType: 'string',
61+
dflt: '3s',
62+
role: 'style',
63+
description: [
64+
'Sets the tick label formatting rule using d3 formatting mini-language',
65+
'which is similar to those of Python. See',
66+
'https://github.com/d3/d3-format/blob/master/README.md#locale_format'
67+
].join(' ')
68+
},
5969
visible: {
6070
valType: 'boolean',
6171
dflt: true,

src/traces/parcoords/base_plot.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,14 @@ exports.attr = 'type';
1919

2020
exports.plot = function(gd) {
2121
var calcData = Plots.getSubplotCalcData(gd.calcdata, 'parcoords', 'parcoords');
22-
23-
// should we filterVisible here???
24-
2522
if(calcData.length) parcoordsPlot(gd, calcData);
2623
};
2724

2825
exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
29-
var hadPie = (oldFullLayout._has && oldFullLayout._has('parcoords'));
30-
var hasPie = (newFullLayout._has && newFullLayout._has('parcoords'));
26+
var hadParcoords = (oldFullLayout._has && oldFullLayout._has('parcoords'));
27+
var hasParcoords = (newFullLayout._has && newFullLayout._has('parcoords'));
3128

32-
if(hasPie && !hasPie) {
29+
if(hadParcoords && !hasParcoords) {
3330
oldFullLayout._paperdiv.selectAll('.parcoords-line-layers').remove();
3431
oldFullLayout._paperdiv.selectAll('.parcoords-line-layers').remove();
3532
oldFullLayout._paperdiv.selectAll('.parcoords').remove();

src/traces/parcoords/calc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module.exports = function calc(gd, trace) {
2323
constraintrange: inputDimensions[i].constraintrange,
2424
tickvals: inputDimensions[i].tickvals,
2525
ticktext: inputDimensions[i].ticktext,
26+
tickformat: inputDimensions[i].tickformat,
2627
visible: inputDimensions[i].visible,
2728
label: inputDimensions[i].label,
2829
values: inputDimensions[i].values

src/traces/parcoords/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ function dimensionsDefaults(traceIn, traceOut) {
6161
coerce('label');
6262
coerce('tickvals');
6363
coerce('ticktext');
64+
coerce('tickformat');
6465
coerce('range');
6566
coerce('constraintrange');
6667
coerce('values');

src/traces/parcoords/lines.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010

1111
var createREGL = require('regl');
1212
var glslify = require('glslify');
13+
var verticalPadding = require('./constants').verticalPadding;
1314
var vertexShaderSource = glslify('./shaders/vertex.glsl');
1415
var pickVertexShaderSource = glslify('./shaders/pick_vertex.glsl');
1516
var fragmentShaderSource = glslify('./shaders/fragment.glsl');
1617

1718
var depthLimitEpsilon = 1e-6; // don't change; otherwise near/far plane lines are lost
18-
var filterEpsilon = 1e-3; // don't change; otherwise filter may lose lines on domain boundaries
1919

2020
var gpuDimensionCount = 64;
2121
var sectionVertexCount = 2;
@@ -297,6 +297,7 @@ module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDim
297297
function makeItem(i, ii, x, y, panelSizeX, canvasPanelSizeY, crossfilterDimensionIndex, scatter, I, leftmost, rightmost) {
298298
var loHi, abcd, d, index;
299299
var leftRight = [i, ii];
300+
var filterEpsilon = verticalPadding / canvasPanelSizeY;
300301

301302
var dims = [0, 1].map(function() {return [0, 1, 2, 3].map(function() {return new Float32Array(16);});});
302303
var lims = [0, 1].map(function() {return [0, 1, 2, 3].map(function() {return new Float32Array(16);});});

src/traces/parcoords/parcoords.js

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ function ordinalScale(dimension) {
8787
.range(dimension.tickvals.map(function(d) {return (d - extent[0]) / (extent[1] - extent[0]);}));
8888
}
8989

90-
function unitToColorScale(cscale, cmin, cmax, coloringArray) {
90+
function unitToColorScale(cscale) {
9191

9292
var colorStops = cscale.map(function(d) {return d[0];});
9393
var colorStrings = cscale.map(function(d) {return d[1];});
@@ -103,27 +103,17 @@ function unitToColorScale(cscale, cmin, cmax, coloringArray) {
103103
.range(colorTuples.map(prop(key)));
104104
});
105105

106-
var colorToUnitScale = d3.scale.linear()
107-
.domain(d3.extent(coloringArray));
108-
109-
var unitMin = colorToUnitScale(cmin);
110-
var unitMax = colorToUnitScale(cmax);
111-
112-
var cScale = d3.scale.linear()
113-
.clamp(true)
114-
.domain([unitMin, unitMax]);
115-
116106
return function(d) {
117107
return polylinearUnitScales.map(function(s) {
118-
return s(cScale(d));
108+
return s(d);
119109
});
120110
};
121111
}
122112

123113
function model(layout, d, i, a) {
124114

125115
var lines = Lib.extendDeep({}, d.line, {
126-
color: d.line.color.map(domainToUnitScale({values: d.line.color})),
116+
color: d.line.color.map(domainToUnitScale({values: d.line.color, range: [d.line.cmin, d.line.cmax]})),
127117
blockLineCount: c.blockLineCount,
128118
canvasOverdrag: c.overdrag * c.canvasPixelRatio
129119
});
@@ -142,10 +132,10 @@ function model(layout, d, i, a) {
142132
colCount: d.dimensions.filter(visible).length,
143133
dimensions: d.dimensions,
144134
tickDistance: c.tickDistance,
145-
unitToColor: unitToColorScale(d.line.colorscale, d.line.cmin, d.line.cmax, d.line.color),
135+
unitToColor: unitToColorScale(d.line.colorscale),
146136
lines: lines,
147-
translateX: (d.domain.x[0] || 0) * layout.width,
148-
translateY: (d.domain.y[0] || 0) * layout.height,
137+
translateX: d.domain.x[0] * layout.width,
138+
translateY: layout.height - d.domain.y[1] * layout.height,
149139
pad: pad,
150140
canvasWidth: rowContentWidth * c.canvasPixelRatio + 2 * lines.canvasOverdrag,
151141
canvasHeight: rowHeight * c.canvasPixelRatio,
@@ -184,8 +174,9 @@ function viewModel(model) {
184174
return {
185175
key: key,
186176
label: dimension.label,
187-
tickvals: dimension.tickvals || false,
188-
ticktext: dimension.ticktext || false,
177+
tickFormat: dimension.tickformat,
178+
tickvals: dimension.tickvals,
179+
ticktext: dimension.ticktext,
189180
ordinal: !!dimension.tickvals,
190181
scatter: c.scatter || dimension.scatter,
191182
xIndex: i,
@@ -282,6 +273,8 @@ module.exports = function(root, svg, styledData, layout, callbacks) {
282273
var parcoordsLineLayers = root.selectAll('.parcoords-line-layers')
283274
.data(vm, keyFun);
284275

276+
parcoordsLineLayers.exit().remove();
277+
285278
parcoordsLineLayers.enter()
286279
.insert('div', '.' + svg.attr('class').split(' ').join(' .')) // not hardcoding .main-svg
287280
.classed('parcoords-line-layers', true)
@@ -316,8 +309,8 @@ module.exports = function(root, svg, styledData, layout, callbacks) {
316309
var event = d3.event;
317310
var cw = this.width;
318311
var ch = this.height;
319-
var translateY = d.model.key * (d.model.height + d.model.pad.t + d.model.pad.b);
320-
var x = event.layerX - d.model.pad.l + c.overdrag;
312+
var translateY = d.model.key * (d.model.height + d.model.pad.t + d.model.pad.b) + d.model.translateY;
313+
var x = event.layerX - d.model.pad.l + c.overdrag - d.model.translateX;
321314
var y = event.layerY - d.model.pad.t - translateY;
322315
if(x < 0 || y < 0 || x >= cw || y >= ch) {
323316
return;
@@ -329,6 +322,8 @@ module.exports = function(root, svg, styledData, layout, callbacks) {
329322
var eventData = {
330323
x: x,
331324
y: y,
325+
clientX: event.clientX,
326+
clientY: event.clientY,
332327
dataIndex: d.model.key,
333328
curveNumber: curveNumber
334329
};
@@ -358,6 +353,8 @@ module.exports = function(root, svg, styledData, layout, callbacks) {
358353
var parcoordsControlOverlay = svg.selectAll('.parcoords')
359354
.data(vm, keyFun);
360355

356+
parcoordsControlOverlay.exit().remove();
357+
361358
parcoordsControlOverlay.enter()
362359
.append('g')
363360
.classed('parcoords', true)
@@ -542,7 +539,7 @@ module.exports = function(root, svg, styledData, layout, callbacks) {
542539
.orient('left')
543540
.tickSize(4)
544541
.outerTickSize(2)
545-
.ticks(wantedTickCount, '3s') // works for continuous scales only...
542+
.ticks(wantedTickCount, d.tickFormat) // works for continuous scales only...
546543
.tickValues(d.ordinal ? // and this works for ordinal scales
547544
sdom.filter(function(d, i) {return !(i % Math.round((sdom.length / wantedTickCount)));})
548545
.map(function(d, i) {return texts && texts[i] || d;}) :
@@ -613,7 +610,7 @@ module.exports = function(root, svg, styledData, layout, callbacks) {
613610
.data(repeat, keyFun);
614611

615612
function formatExtreme(d) {
616-
return d.ordinal ? d3.format('.0s') : d3.format('.3s');
613+
return d.ordinal ? function() {return '';} : d3.format(d.tickFormat);
617614
}
618615

619616
axisExtentTopText.enter()
1.34 KB
Loading
-155 Bytes
Loading
-150 Bytes
Loading
3.02 KB
Loading

test/image/mocks/gl2d_parcoords.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"id": "Block width",
3030
"label": "Block width",
3131
"range": [0, 700000],
32+
"tickformat": "",
3233
"values": [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 436900, 373600, 268630, 439000, 381800, 491200, 402800, 381400, 485600, 600000, 372200, 394700, 383800, 401100, 356500, 313200, 487100, 490700, 432299, 530300, 521500, 456700, 333800, 343200, 394000, 328200, 487700, 383600, 317700, 324600, 482900, 515100, 500100, 562700, 486000, 453400, 352900, 331300, 496200, 469099, 472500, 354700, 507700, 509000, 439300, 525300, 347600, 379000, 432800, 378800, 383200, 523800, 600000, 313600, 497700, 411300, 420000, 381100, 342800, 385900, 268630, 495800, 488000, 446400, 397900, 373300, 385700, 396500, 475700, 510600, 586800, 596000, 407600, 439200]
3334
},
3435
{

test/jasmine/tests/parcoords_test.js

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ mock0.data[0].dimensions = [];
2222

2323
var mock = require('@mocks/gl2d_parcoords_large.json');
2424

25+
var lineStart = 30;
26+
var lineCount = 10;
27+
2528
describe('parcoords initialization tests', function() {
2629

2730
'use strict';
@@ -82,7 +85,7 @@ describe('parcoords initialization tests', function() {
8285
alienProperty: 'Alpha Centauri'
8386
}]
8487
});
85-
expect(fullTrace.dimensions).toEqual([{values: [1], visible: true, _index: 0}]);
88+
expect(fullTrace.dimensions).toEqual([{values: [1], visible: true, tickformat: '3s', _index: 0}]);
8689
});
8790

8891
it('\'dimension.visible\' should be set to false, and other props just passed through if \'values\' is not provided', function() {
@@ -125,8 +128,8 @@ describe('parcoords initialization tests', function() {
125128
{values: [1, 2], visible: false} // shouldn't be truncated to as false
126129
]});
127130
expect(fullTrace.dimensions).toEqual([
128-
{values: [321, 534, 542], visible: true, _index: 0},
129-
{values: [562, 124, 942], visible: true, _index: 1},
131+
{values: [321, 534, 542], visible: true, tickformat: '3s', _index: 0},
132+
{values: [562, 124, 942], visible: true, tickformat: '3s', _index: 1},
130133
{values: [], visible: false},
131134
{values: [1, 2], visible: false}
132135
]);
@@ -225,8 +228,9 @@ describe('parcoords', function() {
225228

226229
beforeAll(function() {
227230
mock.data[0].dimensions.forEach(function(d) {
228-
d.values = d.values.slice(0, 100);
231+
d.values = d.values.slice(lineStart, lineStart + lineCount);
229232
});
233+
mock.data[0].line.color = mock.data[0].line.color.slice(lineStart, lineStart + lineCount);
230234
});
231235

232236
afterEach(destroyGraphDiv);
@@ -494,6 +498,10 @@ describe('parcoords', function() {
494498

495499
beforeEach(function(done) {
496500
mockCopy = Lib.extendDeep({}, mock);
501+
mockCopy.data[0].domain = {
502+
x: [0.1, 0.9],
503+
y: [0.05, 0.85]
504+
};
497505
gd = createGraphDiv();
498506
Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done);
499507
});
@@ -583,6 +591,7 @@ describe('parcoords', function() {
583591
restyleDimension('label', 'new label')()
584592
.then(restyleDimension('tickvals', [[0, 0.1, 0.4, 1, 2]]))
585593
.then(restyleDimension('ticktext', [['alpha', 'gamma', 'beta', 'omega', 'epsilon']]))
594+
.then(restyleDimension('tickformat', '4s'))
586595
.then(restyleDimension('range', [[0, 2]]))
587596
.then(restyleDimension('constraintrange', [[0, 1]]))
588597
.then(restyleDimension('values', [[0, 0.1, 0.4, 1, 2, 0, 0.1, 0.4, 1, 2]]))
@@ -661,15 +670,15 @@ describe('parcoords', function() {
661670

662671
expect(tester.get()).toBe(false);
663672

664-
mouseEvent('mousemove', 111, 207);
665-
mouseEvent('mouseover', 111, 207);
673+
mouseEvent('mousemove', 853, 254);
674+
mouseEvent('mouseover', 853, 254);
666675

667676
window.setTimeout(function() {
668677

669-
expect(tester.get().hover.curveNumber).toBe(36);
678+
expect(tester.get().hover.curveNumber).toBe(4);
670679

671-
mouseEvent('mousemove', 110, 126);
672-
mouseEvent('mouseover', 110, 126);
680+
mouseEvent('mousemove', 800, 240);
681+
mouseEvent('mouseover', 800, 240);
673682

674683
window.setTimeout(function() {
675684

0 commit comments

Comments
 (0)