diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index feaccfbdc56..bf054ecefb9 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -559,11 +559,12 @@ proto.destroy = function() { // for reset camera button in mode bar proto.setCameraToDefault = function setCameraToDefault() { // as in Gl3d.layoutAttributes - this.glplot.camera.lookAt( - [1.25, 1.25, 1.25], - [0, 0, 0], - [0, 0, 1] - ); + + this.setCamera({ + eye: { x: 1.25, y: 1.25, z: 1.25 }, + center: { x: 0, y: 0, z: 0 }, + up: { x: 0, y: 0, z: 1 } + }); }; // get camera position in plotly coords from 'orbit-camera' coords @@ -583,14 +584,22 @@ proto.getCamera = function getCamera() { // set camera position with a set of plotly coords proto.setCamera = function setCamera(cameraData) { - var up = cameraData.up; - var center = cameraData.center; - var eye = cameraData.eye; - this.glplot.camera.lookAt( - [eye.x, eye.y, eye.z], - [center.x, center.y, center.z], - [up.x, up.y, up.z] - ); + + // getOrbitCamera :: plotly_coords -> orbit_camera_coords + function getOrbitCamera(camera) { + return [ + [camera.eye.x, camera.eye.y, camera.eye.z], + [camera.center.x, camera.center.y, camera.center.z], + [camera.up.x, camera.up.y, camera.up.z] + ]; + } + + var update = {}; + + update[this.id] = cameraData; + + this.glplot.camera.lookAt.apply(this, getOrbitCamera(cameraData)); + this.graphDiv.emit('plotly_relayout', update); }; // save camera to user layout (i.e. gd.layout) diff --git a/test/jasmine/tests/gl_plot_interact_test.js b/test/jasmine/tests/gl_plot_interact_test.js index d0fa3ddd278..f59a84f3875 100644 --- a/test/jasmine/tests/gl_plot_interact_test.js +++ b/test/jasmine/tests/gl_plot_interact_test.js @@ -229,7 +229,7 @@ describe('Test gl plot interactions', function() { }); describe('gl3d modebar click handlers', function() { - var modeBar; + var modeBar, relayoutCallback; beforeEach(function(done) { var mockData = [{ @@ -245,8 +245,13 @@ describe('Test gl plot interactions', function() { gd = createGraphDiv(); Plotly.plot(gd, mockData, mockLayout).then(function() { + modeBar = gd._fullLayout._modeBar; + relayoutCallback = jasmine.createSpy('relayoutCallback'); + + gd.on('plotly_relayout', relayoutCallback); + delay(done); }); }); @@ -342,7 +347,26 @@ describe('Test gl plot interactions', function() { .toEqual({x: 2.5, y: 2.5, z: 2.5}); selectButton(modeBar, 'resetCameraDefault3d').click(); + setTimeout(function() { + + expect(relayoutCallback).toHaveBeenCalledTimes(2); // initiator: resetCameraDefault3d; 2 scenes + expect(relayoutCallback).toHaveBeenCalledWith({ + scene: { + eye: { x: 1.25, y: 1.25, z: 1.25 }, + center: { x: 0, y: 0, z: 0 }, + up: { x: 0, y: 0, z: 1 } + } + }); + expect(relayoutCallback).toHaveBeenCalledWith({ + scene2: { + center: { x: 0, y: 0, z: 0 }, + eye: { x: 1.25, y: 1.25, z: 1.25 }, + up: { x: 0, y: 0, z: 1 } + } + }); + relayoutCallback.calls.reset(); + expect(sceneLayout.camera.eye) .toEqual({x: 0.1, y: 0.1, z: 1}, 'does not change the layout objects'); expect(scene.camera.eye) @@ -353,7 +377,25 @@ describe('Test gl plot interactions', function() { .toBeCloseToArray([1.25, 1.25, 1.25], 4); selectButton(modeBar, 'resetCameraLastSave3d').click(); + setTimeout(function() { + + expect(relayoutCallback).toHaveBeenCalledTimes(2); // initiator: resetCameraLastSave3d; 2 scenes + expect(relayoutCallback).toHaveBeenCalledWith({ + scene: { + center: { x: 0, y: 0, z: 0 }, + eye: { x: 0.1, y: 0.1, z: 1 }, + up: { x: 0, y: 0, z: 1 } + } + }); + expect(relayoutCallback).toHaveBeenCalledWith({ + scene2: { + center: { x: 0, y: 0, z: 0 }, + eye: { x: 2.5, y: 2.5, z: 2.5 }, + up: { x: 0, y: 0, z: 1 } + } + }); + expect(sceneLayout.camera.eye) .toEqual({x: 0.1, y: 0.1, z: 1}, 'does not change the layout objects'); expect(scene.camera.eye) @@ -364,7 +406,9 @@ describe('Test gl plot interactions', function() { .toBeCloseToArray([2.5, 2.5, 2.5], 4); done(); + }, MODEBAR_DELAY); + }, MODEBAR_DELAY); }); });