-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Non-fancy scattergl to work with dates #1021
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
Changes from 5 commits
fac70b2
a23756d
ab4ffbf
f5d6113
3c79068
5b71b47
46a6b6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,11 +114,13 @@ proto.handlePick = function(pickResult) { | |
index = this.idToIndex[pickResult.pointId]; | ||
} | ||
|
||
var x = this.pickXData[index]; | ||
|
||
return { | ||
trace: this, | ||
dataCoord: pickResult.dataCoord, | ||
traceCoord: [ | ||
this.pickXData[index], | ||
isNumeric(x) || !Lib.isDateTime(x) ? x : Lib.dateTime2ms(x), | ||
this.pickYData[index] | ||
], | ||
textLabel: Array.isArray(this.textLabels) ? | ||
|
@@ -135,7 +137,7 @@ proto.handlePick = function(pickResult) { | |
|
||
// check if trace is fancy | ||
proto.isFancy = function(options) { | ||
if(this.scene.xaxis.type !== 'linear') return true; | ||
if(this.scene.xaxis.type !== 'linear' && this.scene.xaxis.type !== 'date') return true; | ||
if(this.scene.yaxis.type !== 'linear') return true; | ||
|
||
if(!options.x || !options.y) return true; | ||
|
@@ -270,7 +272,7 @@ proto.updateFast = function(options) { | |
pId = 0, | ||
ptr = 0; | ||
|
||
var xx, yy; | ||
var xx, yy, fastType; | ||
|
||
// TODO add 'very fast' mode that bypasses this loop | ||
// TODO bypass this on modebar +/- zoom | ||
|
@@ -279,17 +281,24 @@ proto.updateFast = function(options) { | |
yy = y[i]; | ||
|
||
// check for isNaN is faster but doesn't skip over nulls | ||
if(!isNumeric(xx) || !isNumeric(yy)) continue; | ||
fastType = isNumeric(xx) || xx instanceof Date; | ||
|
||
idToIndex[pId++] = i; | ||
if(isNumeric(yy) && (fastType || Lib.isDateTime(xx))) { | ||
|
||
positions[ptr++] = xx; | ||
positions[ptr++] = yy; | ||
if(!fastType) { | ||
xx = Lib.dateTime2ms(xx); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @etpinard @alexcjohnson as you see I ended up not skimping on tests, i.e. not just checking the first value, as we already had a check with relatively fast tests (number or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might worth exploring with placing the Maybe, we could add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... I think the autotype routine does it right. It samples not-more than 1000 pts (that takes ~ 3 In the cartesian code, with that axis type, the data-to-calcData routines (i.e. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @etpinard thanks for testing and making a decision over whether this approach is fast enough or not. The current code in master already incurred the expense of two
Back to present time: the fast path can be provided if all values can be assumed to be number (or |
||
|
||
idToIndex[pId++] = i; | ||
|
||
bounds[0] = Math.min(bounds[0], xx); | ||
bounds[1] = Math.min(bounds[1], yy); | ||
bounds[2] = Math.max(bounds[2], xx); | ||
bounds[3] = Math.max(bounds[3], yy); | ||
positions[ptr++] = xx; | ||
positions[ptr++] = yy; | ||
|
||
bounds[0] = Math.min(bounds[0], xx); | ||
bounds[1] = Math.min(bounds[1], yy); | ||
bounds[2] = Math.max(bounds[2], xx); | ||
bounds[3] = Math.max(bounds[3], yy); | ||
} | ||
} | ||
|
||
positions = truncate(positions, ptr); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
var PlotlyInternal = require('@src/plotly'); | ||
|
||
var hasWebGLSupport = require('../assets/has_webgl_support'); | ||
|
||
var createGraphDiv = require('../assets/create_graph_div'); | ||
var destroyGraphDiv = require('../assets/destroy_graph_div'); | ||
|
||
describe('date axis', function() { | ||
|
||
if(!hasWebGLSupport('axes_test date axis')) return; | ||
|
||
var gd; | ||
|
||
beforeEach(function() { | ||
gd = createGraphDiv(); | ||
}); | ||
|
||
afterEach(destroyGraphDiv); | ||
|
||
it('should use the fancy gl-vis/gl-scatter2d', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
'marker': { | ||
'color': 'rgb(31, 119, 180)', | ||
'size': 18, | ||
'symbol': [ | ||
'diamond', | ||
'cross' | ||
] | ||
}, | ||
x: [new Date('2016-10-10'), new Date('2016-10-12')], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
// one way of check which renderer - fancy vs not - we're using | ||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(0); | ||
}); | ||
|
||
it('should use the fancy gl-vis/gl-scatter2d once again', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
'marker': { | ||
'color': 'rgb(31, 119, 180)', | ||
'size': 36, | ||
'symbol': [ | ||
'circle', | ||
'cross' | ||
] | ||
}, | ||
x: [new Date('2016-10-10'), new Date('2016-10-11')], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
// one way of check which renderer - fancy vs not - we're using | ||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(0); | ||
}); | ||
|
||
it('should now use the non-fancy gl-vis/gl-scatter2d', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
mode: 'markers', // important, as otherwise lines are assumed (which needs fancy) | ||
x: [new Date('2016-10-10'), new Date('2016-10-11')], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(2); | ||
}); | ||
|
||
it('should use the non-fancy gl-vis/gl-scatter2d with string dates', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
mode: 'markers', // important, as otherwise lines are assumed (which needs fancy) | ||
x: ['2016-10-10', '2016-10-11'], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(2); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍