plotly.js 1.52.1 → 1.52.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.fossa.yml +58 -0
- package/.ignore +3 -0
- package/CHANGELOG.md +21 -0
- package/dist/README.md +25 -25
- package/dist/plot-schema.json +8 -8
- package/dist/plotly-basic.js +187 -54
- package/dist/plotly-basic.min.js +2 -2
- package/dist/plotly-cartesian.js +187 -54
- package/dist/plotly-cartesian.min.js +2 -2
- package/dist/plotly-finance.js +187 -54
- package/dist/plotly-finance.min.js +2 -2
- package/dist/plotly-geo-assets.js +2 -2
- package/dist/plotly-geo.js +168 -49
- package/dist/plotly-geo.min.js +2 -2
- package/dist/plotly-gl2d.js +173 -51
- package/dist/plotly-gl2d.min.js +2 -2
- package/dist/plotly-gl3d.js +668 -449
- package/dist/plotly-gl3d.min.js +2 -2
- package/dist/plotly-mapbox.js +170 -50
- package/dist/plotly-mapbox.min.js +2 -2
- package/dist/plotly-with-meta.js +823 -533
- package/dist/plotly.js +814 -525
- package/dist/plotly.min.js +2 -2
- package/package.json +24 -23
- package/src/assets/geo_assets.js +1 -1
- package/src/components/annotations/attributes.js +1 -1
- package/src/core.js +1 -1
- package/src/lib/index.js +6 -3
- package/src/plot_api/subroutines.js +6 -0
- package/src/plot_api/validate.js +4 -3
- package/src/plots/cartesian/axes.js +6 -2
- package/src/plots/cartesian/constants.js +1 -2
- package/src/plots/cartesian/layout_defaults.js +112 -27
- package/src/plots/gl3d/scene.js +361 -323
- package/src/plots/layout_attributes.js +2 -2
- package/src/plots/mapbox/layers.js +2 -1
- package/src/plots/plots.js +30 -9
- package/src/traces/bar/hover.js +6 -1
- package/src/traces/bar/plot.js +13 -4
- package/src/traces/mesh3d/convert.js +9 -5
- package/src/traces/pie/attributes.js +7 -6
- package/src/traces/treemap/plot.js +2 -0
- package/tasks/test_syntax.js +1 -1
package/src/plots/gl3d/scene.js
CHANGED
|
@@ -30,10 +30,269 @@ var createAxesOptions = require('./layout/convert');
|
|
|
30
30
|
var createSpikeOptions = require('./layout/spikes');
|
|
31
31
|
var computeTickMarks = require('./layout/tick_marks');
|
|
32
32
|
|
|
33
|
+
var isMobile = require('is-mobile');
|
|
34
|
+
var tablet = isTablet();
|
|
35
|
+
|
|
36
|
+
function isTablet() {
|
|
37
|
+
if(!navigator) return false;
|
|
38
|
+
|
|
39
|
+
var ua;
|
|
40
|
+
// same interface as applied by is-mobile module
|
|
41
|
+
if(!ua && typeof navigator !== 'undefined') ua = navigator.userAgent;
|
|
42
|
+
if(ua && ua.headers && typeof ua.headers['user-agent'] === 'string') {
|
|
43
|
+
ua = ua.headers['user-agent'];
|
|
44
|
+
}
|
|
45
|
+
if(typeof ua !== 'string') return false;
|
|
46
|
+
|
|
47
|
+
var result = isMobile({
|
|
48
|
+
ua: ua,
|
|
49
|
+
tablet: true
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// handle iPad pro or iPad with iOs 13 using Safari
|
|
53
|
+
// see https://github.com/plotly/plotly.js/issues/4502
|
|
54
|
+
if(
|
|
55
|
+
result === false &&
|
|
56
|
+
ua.indexOf('Macintosh') !== -1 &&
|
|
57
|
+
ua.indexOf('Safari') !== -1 &&
|
|
58
|
+
navigator.maxTouchPoints > 1
|
|
59
|
+
) {
|
|
60
|
+
result = true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
33
66
|
|
|
34
67
|
var STATIC_CANVAS, STATIC_CONTEXT;
|
|
35
68
|
|
|
36
|
-
function
|
|
69
|
+
function Scene(options, fullLayout) {
|
|
70
|
+
// create sub container for plot
|
|
71
|
+
var sceneContainer = document.createElement('div');
|
|
72
|
+
var plotContainer = options.container;
|
|
73
|
+
|
|
74
|
+
// keep a ref to the graph div to fire hover+click events
|
|
75
|
+
this.graphDiv = options.graphDiv;
|
|
76
|
+
|
|
77
|
+
// create SVG container for hover text
|
|
78
|
+
var svgContainer = document.createElementNS(
|
|
79
|
+
'http://www.w3.org/2000/svg',
|
|
80
|
+
'svg');
|
|
81
|
+
svgContainer.style.position = 'absolute';
|
|
82
|
+
svgContainer.style.top = svgContainer.style.left = '0px';
|
|
83
|
+
svgContainer.style.width = svgContainer.style.height = '100%';
|
|
84
|
+
svgContainer.style['z-index'] = 20;
|
|
85
|
+
svgContainer.style['pointer-events'] = 'none';
|
|
86
|
+
sceneContainer.appendChild(svgContainer);
|
|
87
|
+
this.svgContainer = svgContainer;
|
|
88
|
+
|
|
89
|
+
// Tag the container with the sceneID
|
|
90
|
+
sceneContainer.id = options.id;
|
|
91
|
+
sceneContainer.style.position = 'absolute';
|
|
92
|
+
sceneContainer.style.top = sceneContainer.style.left = '0px';
|
|
93
|
+
sceneContainer.style.width = sceneContainer.style.height = '100%';
|
|
94
|
+
plotContainer.appendChild(sceneContainer);
|
|
95
|
+
|
|
96
|
+
this.fullLayout = fullLayout;
|
|
97
|
+
this.id = options.id || 'scene';
|
|
98
|
+
this.fullSceneLayout = fullLayout[this.id];
|
|
99
|
+
|
|
100
|
+
// Saved from last call to plot()
|
|
101
|
+
this.plotArgs = [ [], {}, {} ];
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
* Move this to calc step? Why does it work here?
|
|
105
|
+
*/
|
|
106
|
+
this.axesOptions = createAxesOptions(fullLayout, fullLayout[this.id]);
|
|
107
|
+
this.spikeOptions = createSpikeOptions(fullLayout[this.id]);
|
|
108
|
+
this.container = sceneContainer;
|
|
109
|
+
this.staticMode = !!options.staticPlot;
|
|
110
|
+
this.pixelRatio = this.pixelRatio || options.plotGlPixelRatio || 2;
|
|
111
|
+
|
|
112
|
+
// Coordinate rescaling
|
|
113
|
+
this.dataScale = [1, 1, 1];
|
|
114
|
+
|
|
115
|
+
this.contourLevels = [ [], [], [] ];
|
|
116
|
+
|
|
117
|
+
this.convertAnnotations = Registry.getComponentMethod('annotations3d', 'convert');
|
|
118
|
+
this.drawAnnotations = Registry.getComponentMethod('annotations3d', 'draw');
|
|
119
|
+
|
|
120
|
+
this.initializeGLPlot();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var proto = Scene.prototype;
|
|
124
|
+
|
|
125
|
+
proto.tryCreatePlot = function() {
|
|
126
|
+
var scene = this;
|
|
127
|
+
var opts = {
|
|
128
|
+
canvas: scene.canvas,
|
|
129
|
+
gl: scene.gl,
|
|
130
|
+
glOptions: {
|
|
131
|
+
preserveDrawingBuffer: tablet,
|
|
132
|
+
premultipliedAlpha: true,
|
|
133
|
+
antialias: true
|
|
134
|
+
},
|
|
135
|
+
container: scene.container,
|
|
136
|
+
axes: scene.axesOptions,
|
|
137
|
+
spikes: scene.spikeOptions,
|
|
138
|
+
pickRadius: 10,
|
|
139
|
+
snapToData: true,
|
|
140
|
+
autoScale: true,
|
|
141
|
+
autoBounds: false,
|
|
142
|
+
cameraObject: scene.camera,
|
|
143
|
+
pixelRatio: scene.pixelRatio
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// for static plots, we reuse the WebGL context
|
|
147
|
+
// as WebKit doesn't collect them reliably
|
|
148
|
+
if(scene.staticMode) {
|
|
149
|
+
if(!STATIC_CONTEXT) {
|
|
150
|
+
STATIC_CANVAS = document.createElement('canvas');
|
|
151
|
+
STATIC_CONTEXT = getContext({
|
|
152
|
+
canvas: STATIC_CANVAS,
|
|
153
|
+
preserveDrawingBuffer: true,
|
|
154
|
+
premultipliedAlpha: true,
|
|
155
|
+
antialias: true
|
|
156
|
+
});
|
|
157
|
+
if(!STATIC_CONTEXT) {
|
|
158
|
+
throw new Error('error creating static canvas/context for image server');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
opts.gl = STATIC_CONTEXT;
|
|
163
|
+
opts.canvas = STATIC_CANVAS;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
var failed = 0;
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
scene.glplot = createPlot(opts);
|
|
170
|
+
} catch(e) {
|
|
171
|
+
failed++;
|
|
172
|
+
try { // try second time to fix issue with Chrome 77 https://github.com/plotly/plotly.js/issues/4233
|
|
173
|
+
scene.glplot = createPlot(opts);
|
|
174
|
+
} catch(e) {
|
|
175
|
+
failed++;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return failed < 2;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
proto.initializeGLCamera = function() {
|
|
183
|
+
var scene = this;
|
|
184
|
+
var cameraData = scene.fullSceneLayout.camera;
|
|
185
|
+
var isOrtho = (cameraData.projection.type === 'orthographic');
|
|
186
|
+
|
|
187
|
+
scene.camera = createCamera(scene.container, {
|
|
188
|
+
center: [cameraData.center.x, cameraData.center.y, cameraData.center.z],
|
|
189
|
+
eye: [cameraData.eye.x, cameraData.eye.y, cameraData.eye.z],
|
|
190
|
+
up: [cameraData.up.x, cameraData.up.y, cameraData.up.z],
|
|
191
|
+
_ortho: isOrtho,
|
|
192
|
+
zoomMin: 0.01,
|
|
193
|
+
zoomMax: 100,
|
|
194
|
+
mode: 'orbit'
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
proto.initializeGLPlot = function() {
|
|
199
|
+
var scene = this;
|
|
200
|
+
|
|
201
|
+
scene.initializeGLCamera();
|
|
202
|
+
|
|
203
|
+
var success = scene.tryCreatePlot();
|
|
204
|
+
/*
|
|
205
|
+
* createPlot will throw when webgl is not enabled in the client.
|
|
206
|
+
* Lets return an instance of the module with all functions noop'd.
|
|
207
|
+
* The destroy method - which will remove the container from the DOM
|
|
208
|
+
* is overridden with a function that removes the container only.
|
|
209
|
+
*/
|
|
210
|
+
if(!success) return showNoWebGlMsg(scene);
|
|
211
|
+
|
|
212
|
+
// List of scene objects
|
|
213
|
+
scene.traces = {};
|
|
214
|
+
|
|
215
|
+
scene.make4thDimension();
|
|
216
|
+
|
|
217
|
+
var gd = scene.graphDiv;
|
|
218
|
+
var layout = gd.layout;
|
|
219
|
+
|
|
220
|
+
var makeUpdate = function() {
|
|
221
|
+
var update = {};
|
|
222
|
+
|
|
223
|
+
if(scene.isCameraChanged(layout)) {
|
|
224
|
+
// camera updates
|
|
225
|
+
update[scene.id + '.camera'] = scene.getCamera();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if(scene.isAspectChanged(layout)) {
|
|
229
|
+
// scene updates
|
|
230
|
+
update[scene.id + '.aspectratio'] = scene.glplot.getAspectratio();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return update;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
var relayoutCallback = function(scene) {
|
|
237
|
+
if(scene.fullSceneLayout.dragmode === false) return;
|
|
238
|
+
|
|
239
|
+
var update = makeUpdate();
|
|
240
|
+
scene.saveLayout(layout);
|
|
241
|
+
scene.graphDiv.emit('plotly_relayout', update);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
scene.glplot.canvas.addEventListener('mouseup', function() {
|
|
245
|
+
relayoutCallback(scene);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
scene.glplot.canvas.addEventListener('wheel', function(e) {
|
|
249
|
+
if(gd._context._scrollZoom.gl3d) {
|
|
250
|
+
if(scene.camera._ortho) {
|
|
251
|
+
var s = (e.deltaX > e.deltaY) ? 1.1 : 1.0 / 1.1;
|
|
252
|
+
var o = scene.glplot.getAspectratio();
|
|
253
|
+
scene.glplot.setAspectratio({
|
|
254
|
+
x: s * o.x,
|
|
255
|
+
y: s * o.y,
|
|
256
|
+
z: s * o.z
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
relayoutCallback(scene);
|
|
261
|
+
}
|
|
262
|
+
}, passiveSupported ? {passive: false} : false);
|
|
263
|
+
|
|
264
|
+
scene.glplot.canvas.addEventListener('mousemove', function() {
|
|
265
|
+
if(scene.fullSceneLayout.dragmode === false) return;
|
|
266
|
+
if(scene.camera.mouseListener.buttons === 0) return;
|
|
267
|
+
|
|
268
|
+
var update = makeUpdate();
|
|
269
|
+
scene.graphDiv.emit('plotly_relayouting', update);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
if(!scene.staticMode) {
|
|
273
|
+
scene.glplot.canvas.addEventListener('webglcontextlost', function(event) {
|
|
274
|
+
if(gd && gd.emit) {
|
|
275
|
+
gd.emit('plotly_webglcontextlost', {
|
|
276
|
+
event: event,
|
|
277
|
+
layer: scene.id
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}, false);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
scene.glplot.oncontextloss = function() {
|
|
284
|
+
scene.recoverContext();
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
scene.glplot.onrender = function() {
|
|
288
|
+
scene.render();
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
return true;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
proto.render = function() {
|
|
295
|
+
var scene = this;
|
|
37
296
|
var gd = scene.graphDiv;
|
|
38
297
|
var trace;
|
|
39
298
|
|
|
@@ -128,7 +387,7 @@ function render(scene) {
|
|
|
128
387
|
}
|
|
129
388
|
tx = vectorTx.join('<br>');
|
|
130
389
|
} else if(trace.type === 'isosurface' || trace.type === 'volume') {
|
|
131
|
-
labels.valueLabel = Axes.tickText(scene.
|
|
390
|
+
labels.valueLabel = Axes.tickText(scene._mockAxis, scene._mockAxis.d2l(selection.traceCoordinate[3]), 'hover').text;
|
|
132
391
|
vectorTx.push('value: ' + labels.valueLabel);
|
|
133
392
|
if(selection.textLabel) {
|
|
134
393
|
vectorTx.push(selection.textLabel);
|
|
@@ -195,242 +454,25 @@ function render(scene) {
|
|
|
195
454
|
}
|
|
196
455
|
|
|
197
456
|
scene.drawAnnotations(scene);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function tryCreatePlot(scene, cameraObject, pixelRatio, canvas, gl) {
|
|
201
|
-
var glplotOptions = {
|
|
202
|
-
canvas: canvas,
|
|
203
|
-
gl: gl,
|
|
204
|
-
container: scene.container,
|
|
205
|
-
axes: scene.axesOptions,
|
|
206
|
-
spikes: scene.spikeOptions,
|
|
207
|
-
pickRadius: 10,
|
|
208
|
-
snapToData: true,
|
|
209
|
-
autoScale: true,
|
|
210
|
-
autoBounds: false,
|
|
211
|
-
cameraObject: cameraObject,
|
|
212
|
-
pixelRatio: pixelRatio
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
// for static plots, we reuse the WebGL context
|
|
216
|
-
// as WebKit doesn't collect them reliably
|
|
217
|
-
if(scene.staticMode) {
|
|
218
|
-
if(!STATIC_CONTEXT) {
|
|
219
|
-
STATIC_CANVAS = document.createElement('canvas');
|
|
220
|
-
STATIC_CONTEXT = getContext({
|
|
221
|
-
canvas: STATIC_CANVAS,
|
|
222
|
-
preserveDrawingBuffer: true,
|
|
223
|
-
premultipliedAlpha: true,
|
|
224
|
-
antialias: true
|
|
225
|
-
});
|
|
226
|
-
if(!STATIC_CONTEXT) {
|
|
227
|
-
throw new Error('error creating static canvas/context for image server');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
glplotOptions.pixelRatio = scene.pixelRatio;
|
|
231
|
-
glplotOptions.gl = STATIC_CONTEXT;
|
|
232
|
-
glplotOptions.canvas = STATIC_CANVAS;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
var failed = 0;
|
|
236
|
-
|
|
237
|
-
try {
|
|
238
|
-
scene.glplot = createPlot(glplotOptions);
|
|
239
|
-
} catch(e) {
|
|
240
|
-
failed++;
|
|
241
|
-
try { // try second time to fix issue with Chrome 77 https://github.com/plotly/plotly.js/issues/4233
|
|
242
|
-
scene.glplot = createPlot(glplotOptions);
|
|
243
|
-
} catch(e) {
|
|
244
|
-
failed++;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return failed < 2;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function initializeGLPlot(scene, canvas, gl) {
|
|
252
|
-
scene.initializeGLCamera();
|
|
253
|
-
|
|
254
|
-
var success = tryCreatePlot(scene, scene.camera, scene.pixelRatio, canvas, gl);
|
|
255
|
-
/*
|
|
256
|
-
* createPlot will throw when webgl is not enabled in the client.
|
|
257
|
-
* Lets return an instance of the module with all functions noop'd.
|
|
258
|
-
* The destroy method - which will remove the container from the DOM
|
|
259
|
-
* is overridden with a function that removes the container only.
|
|
260
|
-
*/
|
|
261
|
-
if(!success) return showNoWebGlMsg(scene);
|
|
262
|
-
|
|
263
|
-
var gd = scene.graphDiv;
|
|
264
|
-
var layout = gd.layout;
|
|
265
|
-
|
|
266
|
-
var makeUpdate = function() {
|
|
267
|
-
var update = {};
|
|
268
|
-
|
|
269
|
-
if(scene.isCameraChanged(layout)) {
|
|
270
|
-
// camera updates
|
|
271
|
-
update[scene.id + '.camera'] = scene.getCamera();
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if(scene.isAspectChanged(layout)) {
|
|
275
|
-
// scene updates
|
|
276
|
-
update[scene.id + '.aspectratio'] = scene.glplot.getAspectratio();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return update;
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
var relayoutCallback = function(scene) {
|
|
283
|
-
if(scene.fullSceneLayout.dragmode === false) return;
|
|
284
|
-
|
|
285
|
-
var update = makeUpdate();
|
|
286
|
-
scene.saveLayout(layout);
|
|
287
|
-
scene.graphDiv.emit('plotly_relayout', update);
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
scene.glplot.canvas.addEventListener('mouseup', function() {
|
|
291
|
-
relayoutCallback(scene);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
scene.glplot.canvas.addEventListener('wheel', function(e) {
|
|
295
|
-
if(gd._context._scrollZoom.gl3d) {
|
|
296
|
-
if(scene.glplot.camera._ortho) {
|
|
297
|
-
var s = (e.deltaX > e.deltaY) ? 1.1 : 1.0 / 1.1;
|
|
298
|
-
var o = scene.glplot.getAspectratio();
|
|
299
|
-
scene.glplot.setAspectratio({
|
|
300
|
-
x: s * o.x,
|
|
301
|
-
y: s * o.y,
|
|
302
|
-
z: s * o.z
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
relayoutCallback(scene);
|
|
307
|
-
}
|
|
308
|
-
}, passiveSupported ? {passive: false} : false);
|
|
309
|
-
|
|
310
|
-
scene.glplot.canvas.addEventListener('mousemove', function() {
|
|
311
|
-
if(scene.fullSceneLayout.dragmode === false) return;
|
|
312
|
-
if(scene.camera.mouseListener.buttons === 0) return;
|
|
313
|
-
|
|
314
|
-
var update = makeUpdate();
|
|
315
|
-
scene.graphDiv.emit('plotly_relayouting', update);
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
if(!scene.staticMode) {
|
|
319
|
-
scene.glplot.canvas.addEventListener('webglcontextlost', function(event) {
|
|
320
|
-
if(gd && gd.emit) {
|
|
321
|
-
gd.emit('plotly_webglcontextlost', {
|
|
322
|
-
event: event,
|
|
323
|
-
layer: scene.id
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
}, false);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
scene.glplot.camera = scene.camera;
|
|
330
|
-
|
|
331
|
-
scene.glplot.oncontextloss = function() {
|
|
332
|
-
scene.recoverContext();
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
scene.glplot.onrender = render.bind(null, scene);
|
|
336
|
-
|
|
337
|
-
// List of scene objects
|
|
338
|
-
scene.traces = {};
|
|
339
|
-
|
|
340
|
-
scene.make4thDimension();
|
|
341
|
-
|
|
342
|
-
return true;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function Scene(options, fullLayout) {
|
|
346
|
-
// create sub container for plot
|
|
347
|
-
var sceneContainer = document.createElement('div');
|
|
348
|
-
var plotContainer = options.container;
|
|
349
|
-
|
|
350
|
-
// keep a ref to the graph div to fire hover+click events
|
|
351
|
-
this.graphDiv = options.graphDiv;
|
|
352
|
-
|
|
353
|
-
// create SVG container for hover text
|
|
354
|
-
var svgContainer = document.createElementNS(
|
|
355
|
-
'http://www.w3.org/2000/svg',
|
|
356
|
-
'svg');
|
|
357
|
-
svgContainer.style.position = 'absolute';
|
|
358
|
-
svgContainer.style.top = svgContainer.style.left = '0px';
|
|
359
|
-
svgContainer.style.width = svgContainer.style.height = '100%';
|
|
360
|
-
svgContainer.style['z-index'] = 20;
|
|
361
|
-
svgContainer.style['pointer-events'] = 'none';
|
|
362
|
-
sceneContainer.appendChild(svgContainer);
|
|
363
|
-
this.svgContainer = svgContainer;
|
|
364
|
-
|
|
365
|
-
// Tag the container with the sceneID
|
|
366
|
-
sceneContainer.id = options.id;
|
|
367
|
-
sceneContainer.style.position = 'absolute';
|
|
368
|
-
sceneContainer.style.top = sceneContainer.style.left = '0px';
|
|
369
|
-
sceneContainer.style.width = sceneContainer.style.height = '100%';
|
|
370
|
-
plotContainer.appendChild(sceneContainer);
|
|
371
|
-
|
|
372
|
-
this.fullLayout = fullLayout;
|
|
373
|
-
this.id = options.id || 'scene';
|
|
374
|
-
this.fullSceneLayout = fullLayout[this.id];
|
|
375
|
-
|
|
376
|
-
// Saved from last call to plot()
|
|
377
|
-
this.plotArgs = [ [], {}, {} ];
|
|
378
|
-
|
|
379
|
-
/*
|
|
380
|
-
* Move this to calc step? Why does it work here?
|
|
381
|
-
*/
|
|
382
|
-
this.axesOptions = createAxesOptions(fullLayout, fullLayout[this.id]);
|
|
383
|
-
this.spikeOptions = createSpikeOptions(fullLayout[this.id]);
|
|
384
|
-
this.container = sceneContainer;
|
|
385
|
-
this.staticMode = !!options.staticPlot;
|
|
386
|
-
this.pixelRatio = this.pixelRatio || options.plotGlPixelRatio || 2;
|
|
387
|
-
|
|
388
|
-
// Coordinate rescaling
|
|
389
|
-
this.dataScale = [1, 1, 1];
|
|
390
|
-
|
|
391
|
-
this.contourLevels = [ [], [], [] ];
|
|
392
|
-
|
|
393
|
-
this.convertAnnotations = Registry.getComponentMethod('annotations3d', 'convert');
|
|
394
|
-
this.drawAnnotations = Registry.getComponentMethod('annotations3d', 'draw');
|
|
395
|
-
|
|
396
|
-
initializeGLPlot(this);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
var proto = Scene.prototype;
|
|
400
|
-
|
|
401
|
-
proto.initializeGLCamera = function() {
|
|
402
|
-
var cameraData = this.fullSceneLayout.camera;
|
|
403
|
-
var isOrtho = (cameraData.projection.type === 'orthographic');
|
|
404
|
-
|
|
405
|
-
this.camera = createCamera(this.container, {
|
|
406
|
-
center: [cameraData.center.x, cameraData.center.y, cameraData.center.z],
|
|
407
|
-
eye: [cameraData.eye.x, cameraData.eye.y, cameraData.eye.z],
|
|
408
|
-
up: [cameraData.up.x, cameraData.up.y, cameraData.up.z],
|
|
409
|
-
_ortho: isOrtho,
|
|
410
|
-
zoomMin: 0.01,
|
|
411
|
-
zoomMax: 100,
|
|
412
|
-
mode: 'orbit'
|
|
413
|
-
});
|
|
414
457
|
};
|
|
415
458
|
|
|
416
459
|
proto.recoverContext = function() {
|
|
417
460
|
var scene = this;
|
|
418
|
-
var gl = this.glplot.gl;
|
|
419
|
-
var canvas = this.glplot.canvas;
|
|
420
461
|
|
|
421
|
-
|
|
462
|
+
scene.glplot.dispose();
|
|
422
463
|
|
|
423
|
-
|
|
424
|
-
if(gl.isContextLost()) {
|
|
464
|
+
var tryRecover = function() {
|
|
465
|
+
if(scene.glplot.gl.isContextLost()) {
|
|
425
466
|
requestAnimationFrame(tryRecover);
|
|
426
467
|
return;
|
|
427
468
|
}
|
|
428
|
-
if(!initializeGLPlot(
|
|
469
|
+
if(!scene.initializeGLPlot()) {
|
|
429
470
|
Lib.error('Catastrophic and unrecoverable WebGL error. Context lost.');
|
|
430
471
|
return;
|
|
431
472
|
}
|
|
432
473
|
scene.plot.apply(scene, scene.plotArgs);
|
|
433
|
-
}
|
|
474
|
+
};
|
|
475
|
+
|
|
434
476
|
requestAnimationFrame(tryRecover);
|
|
435
477
|
};
|
|
436
478
|
|
|
@@ -498,39 +540,35 @@ function computeAnnotationBounds(scene, bounds) {
|
|
|
498
540
|
}
|
|
499
541
|
|
|
500
542
|
proto.plot = function(sceneData, fullLayout, layout) {
|
|
543
|
+
var scene = this;
|
|
544
|
+
|
|
501
545
|
// Save parameters
|
|
502
|
-
|
|
546
|
+
scene.plotArgs = [sceneData, fullLayout, layout];
|
|
503
547
|
|
|
504
|
-
if(
|
|
548
|
+
if(scene.glplot.contextLost) return;
|
|
505
549
|
|
|
506
550
|
var data, trace;
|
|
507
551
|
var i, j, axis, axisType;
|
|
508
|
-
var fullSceneLayout = fullLayout[
|
|
509
|
-
var sceneLayout = layout[
|
|
510
|
-
|
|
511
|
-
if(fullSceneLayout.bgcolor) this.glplot.clearColor = str2RGBAarray(fullSceneLayout.bgcolor);
|
|
512
|
-
else this.glplot.clearColor = [0, 0, 0, 0];
|
|
513
|
-
|
|
514
|
-
this.glplot.snapToData = true;
|
|
552
|
+
var fullSceneLayout = fullLayout[scene.id];
|
|
553
|
+
var sceneLayout = layout[scene.id];
|
|
515
554
|
|
|
516
555
|
// Update layout
|
|
517
|
-
|
|
518
|
-
|
|
556
|
+
scene.fullLayout = fullLayout;
|
|
557
|
+
scene.fullSceneLayout = fullSceneLayout;
|
|
519
558
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
this.spikeOptions.merge(fullSceneLayout);
|
|
559
|
+
scene.axesOptions.merge(fullLayout, fullSceneLayout);
|
|
560
|
+
scene.spikeOptions.merge(fullSceneLayout);
|
|
523
561
|
|
|
524
562
|
// Update camera and camera mode
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
563
|
+
scene.setViewport(fullSceneLayout);
|
|
564
|
+
scene.updateFx(fullSceneLayout.dragmode, fullSceneLayout.hovermode);
|
|
565
|
+
scene.camera.enableWheel = scene.graphDiv._context._scrollZoom.gl3d;
|
|
528
566
|
|
|
529
|
-
// Update scene
|
|
530
|
-
|
|
567
|
+
// Update scene background
|
|
568
|
+
scene.glplot.setClearColor(str2RGBAarray(fullSceneLayout.bgcolor));
|
|
531
569
|
|
|
532
570
|
// Update axes functions BEFORE updating traces
|
|
533
|
-
|
|
571
|
+
scene.setConvert(axis);
|
|
534
572
|
|
|
535
573
|
// Convert scene data
|
|
536
574
|
if(!sceneData) sceneData = [];
|
|
@@ -560,10 +598,10 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
560
598
|
}
|
|
561
599
|
|
|
562
600
|
// Save scale
|
|
563
|
-
|
|
601
|
+
scene.dataScale = dataScale;
|
|
564
602
|
|
|
565
603
|
// after computeTraceBounds where ax._categories are filled in
|
|
566
|
-
|
|
604
|
+
scene.convertAnnotations(this);
|
|
567
605
|
|
|
568
606
|
// Update traces
|
|
569
607
|
for(i = 0; i < sceneData.length; ++i) {
|
|
@@ -571,24 +609,24 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
571
609
|
if(data.visible !== true || data._length === 0) {
|
|
572
610
|
continue;
|
|
573
611
|
}
|
|
574
|
-
trace =
|
|
612
|
+
trace = scene.traces[data.uid];
|
|
575
613
|
if(trace) {
|
|
576
614
|
if(trace.data.type === data.type) {
|
|
577
615
|
trace.update(data);
|
|
578
616
|
} else {
|
|
579
617
|
trace.dispose();
|
|
580
618
|
trace = data._module.plot(this, data);
|
|
581
|
-
|
|
619
|
+
scene.traces[data.uid] = trace;
|
|
582
620
|
}
|
|
583
621
|
} else {
|
|
584
622
|
trace = data._module.plot(this, data);
|
|
585
|
-
|
|
623
|
+
scene.traces[data.uid] = trace;
|
|
586
624
|
}
|
|
587
625
|
trace.name = data.name;
|
|
588
626
|
}
|
|
589
627
|
|
|
590
628
|
// Remove empty traces
|
|
591
|
-
var traceIds = Object.keys(
|
|
629
|
+
var traceIds = Object.keys(scene.traces);
|
|
592
630
|
|
|
593
631
|
traceIdLoop:
|
|
594
632
|
for(i = 0; i < traceIds.length; ++i) {
|
|
@@ -598,13 +636,13 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
598
636
|
continue traceIdLoop;
|
|
599
637
|
}
|
|
600
638
|
}
|
|
601
|
-
trace =
|
|
639
|
+
trace = scene.traces[traceIds[i]];
|
|
602
640
|
trace.dispose();
|
|
603
|
-
delete
|
|
641
|
+
delete scene.traces[traceIds[i]];
|
|
604
642
|
}
|
|
605
643
|
|
|
606
644
|
// order object per trace index
|
|
607
|
-
|
|
645
|
+
scene.glplot.objects.sort(function(a, b) {
|
|
608
646
|
return a._trace.data.index - b._trace.data.index;
|
|
609
647
|
});
|
|
610
648
|
|
|
@@ -631,8 +669,8 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
631
669
|
sceneBounds[0][i] = Infinity;
|
|
632
670
|
sceneBounds[1][i] = -Infinity;
|
|
633
671
|
|
|
634
|
-
var objects =
|
|
635
|
-
var annotations =
|
|
672
|
+
var objects = scene.glplot.objects;
|
|
673
|
+
var annotations = scene.fullSceneLayout.annotations || [];
|
|
636
674
|
var axLetter = axis._name.charAt(0);
|
|
637
675
|
|
|
638
676
|
for(j = 0; j < objects.length; j++) {
|
|
@@ -690,8 +728,10 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
690
728
|
axisDataRange[i] = sceneBounds[1][i] - sceneBounds[0][i];
|
|
691
729
|
|
|
692
730
|
// Update plot bounds
|
|
693
|
-
|
|
694
|
-
|
|
731
|
+
scene.glplot.setBounds(i, {
|
|
732
|
+
min: sceneBounds[0][i] * dataScale[i],
|
|
733
|
+
max: sceneBounds[1][i] * dataScale[i]
|
|
734
|
+
});
|
|
695
735
|
}
|
|
696
736
|
|
|
697
737
|
var axesScaleRatio = [1, 1, 1];
|
|
@@ -746,11 +786,11 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
746
786
|
* Finally assign the computed aspecratio to the glplot module. This will have an effect
|
|
747
787
|
* on the next render cycle.
|
|
748
788
|
*/
|
|
749
|
-
|
|
789
|
+
scene.glplot.setAspectratio(fullSceneLayout.aspectratio);
|
|
750
790
|
|
|
751
791
|
// save 'initial' camera view settings for modebar button
|
|
752
|
-
if(!
|
|
753
|
-
|
|
792
|
+
if(!scene.viewInitial.aspectratio) {
|
|
793
|
+
scene.viewInitial.aspectratio = {
|
|
754
794
|
x: fullSceneLayout.aspectratio.x,
|
|
755
795
|
y: fullSceneLayout.aspectratio.y,
|
|
756
796
|
z: fullSceneLayout.aspectratio.z
|
|
@@ -762,7 +802,7 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
762
802
|
var size = fullLayout._size || null;
|
|
763
803
|
|
|
764
804
|
if(domain && size) {
|
|
765
|
-
var containerStyle =
|
|
805
|
+
var containerStyle = scene.container.style;
|
|
766
806
|
containerStyle.position = 'absolute';
|
|
767
807
|
containerStyle.left = (size.l + domain.x[0] * size.w) + 'px';
|
|
768
808
|
containerStyle.top = (size.t + (1 - domain.y[1]) * size.h) + 'px';
|
|
@@ -771,18 +811,19 @@ proto.plot = function(sceneData, fullLayout, layout) {
|
|
|
771
811
|
}
|
|
772
812
|
|
|
773
813
|
// force redraw so that promise is returned when rendering is completed
|
|
774
|
-
|
|
814
|
+
scene.glplot.redraw();
|
|
775
815
|
};
|
|
776
816
|
|
|
777
817
|
proto.destroy = function() {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
818
|
+
var scene = this;
|
|
819
|
+
|
|
820
|
+
if(!scene.glplot) return;
|
|
821
|
+
scene.camera.mouseListener.enabled = false;
|
|
822
|
+
scene.container.removeEventListener('wheel', scene.camera.wheelListener);
|
|
823
|
+
scene.camera = null;
|
|
824
|
+
scene.glplot.dispose();
|
|
825
|
+
scene.container.parentNode.removeChild(scene.container);
|
|
826
|
+
scene.glplot = null;
|
|
786
827
|
};
|
|
787
828
|
|
|
788
829
|
// getCameraArrays :: plotly_coords -> gl-plot3d_coords
|
|
@@ -808,42 +849,34 @@ function getLayoutCamera(camera) {
|
|
|
808
849
|
|
|
809
850
|
// get camera position in plotly coords from 'gl-plot3d' coords
|
|
810
851
|
proto.getCamera = function() {
|
|
811
|
-
this
|
|
812
|
-
|
|
852
|
+
var scene = this;
|
|
853
|
+
scene.camera.view.recalcMatrix(scene.camera.view.lastT());
|
|
854
|
+
return getLayoutCamera(scene.camera);
|
|
813
855
|
};
|
|
814
856
|
|
|
815
857
|
// set gl-plot3d camera position and scene aspects with a set of plotly coords
|
|
816
858
|
proto.setViewport = function(sceneLayout) {
|
|
859
|
+
var scene = this;
|
|
817
860
|
var cameraData = sceneLayout.camera;
|
|
818
861
|
|
|
819
|
-
|
|
820
|
-
|
|
862
|
+
scene.camera.lookAt.apply(this, getCameraArrays(cameraData));
|
|
863
|
+
scene.glplot.setAspectratio(sceneLayout.aspectratio);
|
|
821
864
|
|
|
822
865
|
var newOrtho = (cameraData.projection.type === 'orthographic');
|
|
823
|
-
var oldOrtho =
|
|
866
|
+
var oldOrtho = scene.camera._ortho;
|
|
824
867
|
|
|
825
868
|
if(newOrtho !== oldOrtho) {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
RGBA[0], RGBA[1], RGBA[2], RGBA[3]
|
|
831
|
-
);
|
|
832
|
-
this.glplot.gl.clear(
|
|
833
|
-
this.glplot.gl.DEPTH_BUFFER_BIT |
|
|
834
|
-
this.glplot.gl.COLOR_BUFFER_BIT
|
|
835
|
-
);
|
|
836
|
-
|
|
837
|
-
this.glplot.dispose();
|
|
838
|
-
|
|
839
|
-
initializeGLPlot(this);
|
|
840
|
-
this.glplot.camera._ortho = newOrtho;
|
|
869
|
+
scene.glplot.redraw(); // TODO: figure out why we need to redraw here?
|
|
870
|
+
scene.glplot.clearRGBA();
|
|
871
|
+
scene.glplot.dispose();
|
|
872
|
+
scene.initializeGLPlot();
|
|
841
873
|
}
|
|
842
874
|
};
|
|
843
875
|
|
|
844
876
|
proto.isCameraChanged = function(layout) {
|
|
845
|
-
var
|
|
846
|
-
var
|
|
877
|
+
var scene = this;
|
|
878
|
+
var cameraData = scene.getCamera();
|
|
879
|
+
var cameraNestedProp = Lib.nestedProperty(layout, scene.id + '.camera');
|
|
847
880
|
var cameraDataLastSave = cameraNestedProp.get();
|
|
848
881
|
|
|
849
882
|
function same(x, y, i, j) {
|
|
@@ -876,8 +909,9 @@ proto.isCameraChanged = function(layout) {
|
|
|
876
909
|
};
|
|
877
910
|
|
|
878
911
|
proto.isAspectChanged = function(layout) {
|
|
879
|
-
var
|
|
880
|
-
var
|
|
912
|
+
var scene = this;
|
|
913
|
+
var aspectData = scene.glplot.getAspectratio();
|
|
914
|
+
var aspectNestedProp = Lib.nestedProperty(layout, scene.id + '.aspectratio');
|
|
881
915
|
var aspectDataLastSave = aspectNestedProp.get();
|
|
882
916
|
|
|
883
917
|
return (
|
|
@@ -890,7 +924,8 @@ proto.isAspectChanged = function(layout) {
|
|
|
890
924
|
|
|
891
925
|
// save camera to user layout (i.e. gd.layout)
|
|
892
926
|
proto.saveLayout = function(layout) {
|
|
893
|
-
var
|
|
927
|
+
var scene = this;
|
|
928
|
+
var fullLayout = scene.fullLayout;
|
|
894
929
|
|
|
895
930
|
var cameraData;
|
|
896
931
|
var cameraNestedProp;
|
|
@@ -900,42 +935,42 @@ proto.saveLayout = function(layout) {
|
|
|
900
935
|
var aspectNestedProp;
|
|
901
936
|
var aspectDataLastSave;
|
|
902
937
|
|
|
903
|
-
var cameraChanged =
|
|
904
|
-
var aspectChanged =
|
|
938
|
+
var cameraChanged = scene.isCameraChanged(layout);
|
|
939
|
+
var aspectChanged = scene.isAspectChanged(layout);
|
|
905
940
|
|
|
906
941
|
var hasChanged = cameraChanged || aspectChanged;
|
|
907
942
|
if(hasChanged) {
|
|
908
943
|
var preGUI = {};
|
|
909
944
|
if(cameraChanged) {
|
|
910
|
-
cameraData =
|
|
911
|
-
cameraNestedProp = Lib.nestedProperty(layout,
|
|
945
|
+
cameraData = scene.getCamera();
|
|
946
|
+
cameraNestedProp = Lib.nestedProperty(layout, scene.id + '.camera');
|
|
912
947
|
cameraDataLastSave = cameraNestedProp.get();
|
|
913
948
|
|
|
914
|
-
preGUI[
|
|
949
|
+
preGUI[scene.id + '.camera'] = cameraDataLastSave;
|
|
915
950
|
}
|
|
916
951
|
if(aspectChanged) {
|
|
917
|
-
aspectData =
|
|
918
|
-
aspectNestedProp = Lib.nestedProperty(layout,
|
|
952
|
+
aspectData = scene.glplot.getAspectratio();
|
|
953
|
+
aspectNestedProp = Lib.nestedProperty(layout, scene.id + '.aspectratio');
|
|
919
954
|
aspectDataLastSave = aspectNestedProp.get();
|
|
920
955
|
|
|
921
|
-
preGUI[
|
|
956
|
+
preGUI[scene.id + '.aspectratio'] = aspectDataLastSave;
|
|
922
957
|
}
|
|
923
958
|
Registry.call('_storeDirectGUIEdit', layout, fullLayout._preGUI, preGUI);
|
|
924
959
|
|
|
925
960
|
if(cameraChanged) {
|
|
926
961
|
cameraNestedProp.set(cameraData);
|
|
927
962
|
|
|
928
|
-
var cameraFullNP = Lib.nestedProperty(fullLayout,
|
|
963
|
+
var cameraFullNP = Lib.nestedProperty(fullLayout, scene.id + '.camera');
|
|
929
964
|
cameraFullNP.set(cameraData);
|
|
930
965
|
}
|
|
931
966
|
|
|
932
967
|
if(aspectChanged) {
|
|
933
968
|
aspectNestedProp.set(aspectData);
|
|
934
969
|
|
|
935
|
-
var aspectFullNP = Lib.nestedProperty(fullLayout,
|
|
970
|
+
var aspectFullNP = Lib.nestedProperty(fullLayout, scene.id + '.aspectratio');
|
|
936
971
|
aspectFullNP.set(aspectData);
|
|
937
972
|
|
|
938
|
-
|
|
973
|
+
scene.glplot.redraw();
|
|
939
974
|
}
|
|
940
975
|
}
|
|
941
976
|
|
|
@@ -943,7 +978,8 @@ proto.saveLayout = function(layout) {
|
|
|
943
978
|
};
|
|
944
979
|
|
|
945
980
|
proto.updateFx = function(dragmode, hovermode) {
|
|
946
|
-
var
|
|
981
|
+
var scene = this;
|
|
982
|
+
var camera = scene.camera;
|
|
947
983
|
if(camera) {
|
|
948
984
|
// rotate and orbital are synonymous
|
|
949
985
|
if(dragmode === 'orbit') {
|
|
@@ -957,15 +993,15 @@ proto.updateFx = function(dragmode, hovermode) {
|
|
|
957
993
|
// The setter for camera.mode animates the transition to z-up,
|
|
958
994
|
// but only if we *don't* explicitly set z-up earlier via the
|
|
959
995
|
// relayout. So push `up` back to layout & fullLayout manually now.
|
|
960
|
-
var gd =
|
|
996
|
+
var gd = scene.graphDiv;
|
|
961
997
|
var fullLayout = gd._fullLayout;
|
|
962
|
-
var fullCamera =
|
|
998
|
+
var fullCamera = scene.fullSceneLayout.camera;
|
|
963
999
|
var x = fullCamera.up.x;
|
|
964
1000
|
var y = fullCamera.up.y;
|
|
965
1001
|
var z = fullCamera.up.z;
|
|
966
1002
|
// only push `up` back to (full)layout if it's going to change
|
|
967
1003
|
if(z / Math.sqrt(x * x + y * y + z * z) < 0.999) {
|
|
968
|
-
var attr =
|
|
1004
|
+
var attr = scene.id + '.camera.up';
|
|
969
1005
|
var zUp = {x: 0, y: 0, z: 1};
|
|
970
1006
|
var edits = {};
|
|
971
1007
|
edits[attr] = zUp;
|
|
@@ -981,19 +1017,20 @@ proto.updateFx = function(dragmode, hovermode) {
|
|
|
981
1017
|
}
|
|
982
1018
|
|
|
983
1019
|
// to put dragmode and hovermode on the same grounds from relayout
|
|
984
|
-
|
|
1020
|
+
scene.fullSceneLayout.hovermode = hovermode;
|
|
985
1021
|
};
|
|
986
1022
|
|
|
987
1023
|
proto.toImage = function(format) {
|
|
988
|
-
|
|
1024
|
+
var scene = this;
|
|
989
1025
|
|
|
990
|
-
if(
|
|
1026
|
+
if(!format) format = 'png';
|
|
1027
|
+
if(scene.staticMode) scene.container.appendChild(STATIC_CANVAS);
|
|
991
1028
|
|
|
992
1029
|
// Force redraw
|
|
993
|
-
|
|
1030
|
+
scene.glplot.redraw();
|
|
994
1031
|
|
|
995
1032
|
// Grab context and yank out pixels
|
|
996
|
-
var gl =
|
|
1033
|
+
var gl = scene.glplot.gl;
|
|
997
1034
|
var w = gl.drawingBufferWidth;
|
|
998
1035
|
var h = gl.drawingBufferHeight;
|
|
999
1036
|
|
|
@@ -1034,31 +1071,32 @@ proto.toImage = function(format) {
|
|
|
1034
1071
|
dataURL = canvas.toDataURL('image/png');
|
|
1035
1072
|
}
|
|
1036
1073
|
|
|
1037
|
-
if(
|
|
1074
|
+
if(scene.staticMode) scene.container.removeChild(STATIC_CANVAS);
|
|
1038
1075
|
|
|
1039
1076
|
return dataURL;
|
|
1040
1077
|
};
|
|
1041
1078
|
|
|
1042
1079
|
proto.setConvert = function() {
|
|
1080
|
+
var scene = this;
|
|
1043
1081
|
for(var i = 0; i < 3; i++) {
|
|
1044
|
-
var ax =
|
|
1045
|
-
Axes.setConvert(ax,
|
|
1082
|
+
var ax = scene.fullSceneLayout[axisProperties[i]];
|
|
1083
|
+
Axes.setConvert(ax, scene.fullLayout);
|
|
1046
1084
|
ax.setScale = Lib.noop;
|
|
1047
1085
|
}
|
|
1048
1086
|
};
|
|
1049
1087
|
|
|
1050
1088
|
proto.make4thDimension = function() {
|
|
1051
|
-
var
|
|
1052
|
-
var gd =
|
|
1089
|
+
var scene = this;
|
|
1090
|
+
var gd = scene.graphDiv;
|
|
1053
1091
|
var fullLayout = gd._fullLayout;
|
|
1054
1092
|
|
|
1055
1093
|
// mock axis for hover formatting
|
|
1056
|
-
|
|
1094
|
+
scene._mockAxis = {
|
|
1057
1095
|
type: 'linear',
|
|
1058
1096
|
showexponent: 'all',
|
|
1059
1097
|
exponentformat: 'B'
|
|
1060
1098
|
};
|
|
1061
|
-
Axes.setConvert(
|
|
1099
|
+
Axes.setConvert(scene._mockAxis, fullLayout);
|
|
1062
1100
|
};
|
|
1063
1101
|
|
|
1064
1102
|
module.exports = Scene;
|