-
-
Couldn't load subscription status.
- 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 3 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 |
|---|---|---|
|
|
@@ -118,7 +118,7 @@ proto.handlePick = function(pickResult) { | |
| trace: this, | ||
| dataCoord: pickResult.dataCoord, | ||
| traceCoord: [ | ||
| this.pickXData[index], | ||
| Number(this.pickXData[index]), // non-fancy scattergl has Dates | ||
| this.pickYData[index] | ||
| ], | ||
| textLabel: Array.isArray(this.textLabels) ? | ||
|
|
@@ -135,7 +135,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; | ||
|
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. 👍 |
||
| if(this.scene.yaxis.type !== 'linear') return true; | ||
|
|
||
| if(!options.x || !options.y) return true; | ||
|
|
@@ -279,7 +279,8 @@ proto.updateFast = function(options) { | |
| yy = y[i]; | ||
|
|
||
| // check for isNaN is faster but doesn't skip over nulls | ||
| if(!isNumeric(xx) || !isNumeric(yy)) continue; | ||
| if(!isNumeric(yy)) continue; | ||
| if(!isNumeric(xx) && !(xx instanceof Date)) continue; | ||
|
||
|
|
||
| idToIndex[pId++] = i; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ var Plots = require('@src/plots/plots'); | |
| var Lib = require('@src/lib'); | ||
| var Color = require('@src/components/color'); | ||
| var tinycolor = require('tinycolor2'); | ||
| var hasWebGLSupport = require('../assets/has_webgl_support'); | ||
|
||
|
|
||
| var handleTickValueDefaults = require('@src/plots/cartesian/tick_value_defaults'); | ||
| var Axes = PlotlyInternal.Axes; | ||
|
|
@@ -387,6 +388,84 @@ describe('Test axes', function() { | |
| }); | ||
| }); | ||
|
|
||
| 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); | ||
| }); | ||
|
|
||
| }); | ||
|
|
||
| describe('categoryorder', function() { | ||
|
|
||
| var gd; | ||
|
|
||
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.
@monfera while pure-js users of plotly.js can use
Dateobjects, plot.ly (and plotly.js users that may want to serialize their plots) use date strings viaLib.dateTime2ms(here is what regular cartesian does). I realize that this will be slower, but can we at least support it for compatibility with the rest of our dates?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.
Hey Alex, good point. Currently,
scatterworks with ISO formatted dates e.g.2016-10-13but I'll need to add a conversion from string to date forscattergl. It'll be done upfront. The line you refer to above probably won't need to change as by the time the tooltip gets data it's already in the standard JSDateformat, but the front-end part needs some logic. To avoid having to loop through a possibly large number of array elements, I'm thinking about just checking the type of the first element of the array; if it'sDateit's fine; if it's a string, then convert all elements toDate. Is it OK in your opinion and also @etpinard ?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.
It makes me a little wary, but I can't think of a reason users would mix
Dates and date strings (at least within one trace - definitely different traces should be checked independently). The first element may not be enough though, in case it'snullor something, but the first valid element seems OK. Especially since this trace type is specifically built for performance, I guess we can impose some sane restrictions on the users.I haven't really looked at the architecture here, but if you're already converting the values you can just go straight to milliseconds, ignore
Dateobjects altogether. Also notice that it's not exactly ISO 8601 we use, I don't know its name but I think of it as SQL date format - ie maximally it's2016-10-13 12:34:56.789123but we're permissive about letting you truncate it after any part.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.
Alex I'd probably reuse the date conversion routine you pointed to above, as if at all possible, I'd shy away from rolling a new
string->Dateparser. Yes I agree with using epoch milliseconds as a general principle esp. on greenfield projects, although inplotlyit looks like it's not typically done. There's already conversion by default, as WebGL buffers cover float arrays, so it does get converted to epoch ms already.