From aa1ec8a1d774105f8d70fb5607d2c7abdc9bba4f Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Wed, 2 May 2018 20:08:27 -0400 Subject: [PATCH 1/7] Generate events while dragging. --- src/plots/gl3d/scene.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index 2729b8d72f2..403ecf48311 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -192,6 +192,7 @@ function initializeGLPlot(scene, fullLayout, canvas, gl) { }; scene.glplot.canvas.addEventListener('mouseup', relayoutCallback.bind(null, scene)); + scene.glplot.canvas.addEventListener('mousemove', relayoutCallback.bind(null, scene)); scene.glplot.canvas.addEventListener('wheel', relayoutCallback.bind(null, scene), passiveSupported ? {passive: false} : false); if(!scene.staticMode) { From 3460248dfb278fb7cca1715ee8e3e846fb3e69fc Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Mon, 28 May 2018 13:38:07 -0400 Subject: [PATCH 2/7] Adding relayouting and relayout events for cartesian plots. --- src/plots/cartesian/dragbox.js | 47 ++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index ebd542fdbdb..78d4719dce6 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -349,6 +349,38 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { gd._dragged = zoomDragged; updateZoombox(zb, corners, box, path0, dimmed, lum); + // what event data do we emit here? In gl3d, camera location is emitted. + // what is needed for relayouting a cartesian plot? + // for plotly_relayout, the payload is always 'updates' + // updates[ax._name + '.range[0]'] = ax.range[0]; + // updates[ax._name + '.range[1]'] = ax.range[1]; + // For plotly_relayout, the event is emitted at the end of zoomDone. The payload is not + // computed until zoomAxRanges is called. + // Actual drawing is spread out in several functions + // updateSubplots + // ticksAndAnnotations + // relayout() in plot_api.js + // zoom + // zoomMove + // no drawing + // zoomDone + // zoomAxRanges + // no drawing but modifying updates + // dragtail + // updateSubplots + // drawing subplots + // relayout() in plot_api.js + // zoomwheel + // zoomwheel + // updateSubplots + // ticksandannotations + // this modifies the updates + // dragtail on delay + // updateSubplots + // relayout() in plot_api.js + // + computeZoomUpdates(); + gd.emit('plotly_relayouting', updates); dimmed = true; } @@ -358,7 +390,13 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { if(Math.min(box.h, box.w) < MINDRAG * 2) { return removeZoombox(gd); } + computeZoomUpdates(); + removeZoombox(gd); + dragTail(); + showDoubleClickNotifier(gd); + } + function computeZoomUpdates() { // TODO: edit linked axes in zoomAxRanges and in dragTail if(zoomMode === 'xy' || zoomMode === 'x') { zoomAxRanges(xaxes, box.l / pw, box.r / pw, updates, links.xaxes); @@ -366,10 +404,6 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { if(zoomMode === 'xy' || zoomMode === 'y') { zoomAxRanges(yaxes, (ph - box.b) / ph, (ph - box.t) / ph, updates, links.yaxes); } - - removeZoombox(gd); - dragTail(); - showDoubleClickNotifier(gd); } // scroll zoom, on all draggers except corners @@ -378,7 +412,6 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { var redrawTimer = null; var REDRAWDELAY = constants.REDRAWDELAY; var mainplot = plotinfo.mainplot ? gd._fullLayout._plots[plotinfo.mainplot] : plotinfo; - function zoomWheel(e) { // deactivate mousewheel scrolling on embedded graphs // devs can override this with layout._enablescrollzoom, @@ -489,6 +522,8 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { if(yActive) dragAxList(yaxes, dy); updateSubplots([xActive ? -dx : 0, yActive ? -dy : 0, pw, ph]); ticksAndAnnotations(yActive, xActive); + // updates computed in ticksAndAnnotations + gd.emit('plotly_relayout', updates); return; } @@ -561,6 +596,8 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { updateSubplots([x0, y0, pw - dx, ph - dy]); ticksAndAnnotations(yActive, xActive); + // updates computed in ticksAndAnnotations + gd.emit('plotly_relayout', updates); } // Draw ticks and annotations (and other components) when ranges change. From d88f24e17ad724168c6c4f33bed95b258f03004d Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Mon, 28 May 2018 13:39:57 -0400 Subject: [PATCH 3/7] Emit plotly_relayout on mousemove for gl3d. --- src/plots/gl3d/scene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index af02713a09c..953e5116db3 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -216,7 +216,7 @@ function initializeGLPlot(scene, fullLayout, canvas, gl) { scene.graphDiv.emit('plotly_relayout', update); }; - scene.glplot.canvas.addEventListener('mouseup', relayoutCallback.bind(null, scene)); + scene.glplot.canvas.addEventListener('mousemove', relayoutCallback.bind(null, scene)); scene.glplot.canvas.addEventListener('wheel', relayoutCallback.bind(null, scene), passiveSupported ? {passive: false} : false); if(!scene.staticMode) { From 98f28a242d31888f661e5d6a31d1872c4dea19e1 Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Mon, 28 May 2018 13:47:58 -0400 Subject: [PATCH 4/7] Adding relayouting event for polar plots. --- src/plots/polar/polar.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/plots/polar/polar.js b/src/plots/polar/polar.js index 5b8264194a3..89f1f89b940 100644 --- a/src/plots/polar/polar.js +++ b/src/plots/polar/polar.js @@ -680,24 +680,30 @@ proto.updateMainDrag = function(fullLayout, polarLayout) { zb.attr('d', path1); corners.attr('d', cpath); dragBox.transitionZoombox(zb, corners, dimmed, lum); + var updateObj = {}; + computeZoomUpdates(updateObj); + gd.emit('plotly_relayouting', updateObj); dimmed = true; } - function zoomDone() { - dragBox.removeZoombox(gd); - - if(r0 === null || r1 === null) return; - - dragBox.showDoubleClickNotifier(gd); - + function computeZoomUpdates(update) { var radialAxis = _this.radialAxis; var radialRange = radialAxis.range; var drange = radialRange[1] - radialRange[0]; - var updateObj = {}; - updateObj[_this.id + '.radialaxis.range'] = [ + update[_this.id + '.radialaxis.range'] = [ radialRange[0] + r0 * drange / radius, radialRange[0] + r1 * drange / radius ]; + } + + function zoomDone() { + dragBox.removeZoombox(gd); + + if(r0 === null || r1 === null) return; + var updateObj = {}; + computeZoomUpdates(updateObj); + + dragBox.showDoubleClickNotifier(gd); Registry.call('relayout', gd, updateObj); } From 13c69fc898fb7ceeee7bfec04985812f2a4a81a4 Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Mon, 28 May 2018 17:18:15 -0400 Subject: [PATCH 5/7] Add relayouting events for geo, mapbox and ternary plots. --- src/plots/geo/zoom.js | 3 ++- src/plots/mapbox/mapbox.js | 6 ++++++ src/plots/ternary/ternary.js | 24 +++++++++++++++++------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/plots/geo/zoom.js b/src/plots/geo/zoom.js index ac5d234e9b1..b4212d03df5 100644 --- a/src/plots/geo/zoom.js +++ b/src/plots/geo/zoom.js @@ -80,6 +80,7 @@ function zoomScoped(geo, projection) { .scale(d3.event.scale) .translate(d3.event.translate); geo.render(); + geo.graphDiv.emit('plotly_relayouting', {'projection.scale': projection.scale() / geo.fitScale}); } function syncCb(set) { @@ -153,8 +154,8 @@ function zoomNonClipped(geo, projection) { } geo.render(); + geo.graphDiv.emit('plotly_relayouting', {'projection.scale': projection.scale() / geo.fitScale}); } - function handleZoomend() { d3.select(this).style(zoomendStyle); sync(geo, projection, syncCb); diff --git a/src/plots/mapbox/mapbox.js b/src/plots/mapbox/mapbox.js index 18db3935a4d..0bbb20a735f 100644 --- a/src/plots/mapbox/mapbox.js +++ b/src/plots/mapbox/mapbox.js @@ -169,6 +169,12 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) { self.yaxis.p2c = function() { return evt.lngLat.lat; }; Fx.hover(gd, evt, self.id); + + var update = {}; + var view = self.getView(); + update[self.id] = Lib.extendFlat({}, view); + gd.emit('plotly_relayouting', update); + }); map.on('click', function(evt) { diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js index 436397bc5aa..80d83258924 100644 --- a/src/plots/ternary/ternary.js +++ b/src/plots/ternary/ternary.js @@ -587,17 +587,22 @@ proto.initInteractions = function() { .duration(200); dimmed = true; } + var updates = {}; + computeZoomUpdates(updates); + gd.emit('plotly_relayouting', updates); } + function computeZoomUpdates(attrs) { + attrs[_this.id + '.aaxis.min'] = mins.a; + attrs[_this.id + '.baxis.min'] = mins.b; + attrs[_this.id + '.caxis.min'] = mins.c; + } function zoomDone() { removeZoombox(gd); if(mins === mins0) return; - var attrs = {}; - attrs[_this.id + '.aaxis.min'] = mins.a; - attrs[_this.id + '.baxis.min'] = mins.b; - attrs[_this.id + '.caxis.min'] = mins.c; + computeZoomUpdates(attrs); Registry.call('relayout', gd, attrs); @@ -670,14 +675,19 @@ proto.initInteractions = function() { .select('.scatterlayer').selectAll('.trace') .call(Drawing.hideOutsideRangePoints, _this); } - } - - function dragDone() { var attrs = {}; + computeDragUpdates(attrs); + gd.emit('plotly_relayout', attrs); + } + function computeDragUpdates(attrs) { attrs[_this.id + '.aaxis.min'] = mins.a; attrs[_this.id + '.baxis.min'] = mins.b; attrs[_this.id + '.caxis.min'] = mins.c; + } + function dragDone() { + var attrs = {}; + computeDragUpdates(attrs) Registry.call('relayout', gd, attrs); } From a4c7ab0bb7da7d700d6128acf6c00c56a7e51459 Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Mon, 28 May 2018 18:11:18 -0400 Subject: [PATCH 6/7] fix semicolon --- src/plots/ternary/ternary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js index 80d83258924..627abbbc0c1 100644 --- a/src/plots/ternary/ternary.js +++ b/src/plots/ternary/ternary.js @@ -687,7 +687,7 @@ proto.initInteractions = function() { function dragDone() { var attrs = {}; - computeDragUpdates(attrs) + computeDragUpdates(attrs); Registry.call('relayout', gd, attrs); } From 2f0d6332aadba4a4f72b301fbd6a5e0fe825a859 Mon Sep 17 00:00:00 2001 From: "Chen, Zhihua" <13683070+zhihua-chen@users.noreply.github.com> Date: Tue, 29 May 2018 15:15:39 -0400 Subject: [PATCH 7/7] Switching to relayouting for plotdrag and gl3d rotations. --- src/plots/cartesian/dragbox.js | 4 ++-- src/plots/gl3d/scene.js | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 792a779baef..8ee86a6da09 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -527,7 +527,7 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { updateSubplots([xActive ? -dx : 0, yActive ? -dy : 0, pw, ph]); ticksAndAnnotations(yActive, xActive); // updates computed in ticksAndAnnotations - gd.emit('plotly_relayout', updates); + gd.emit('plotly_relayouting', updates); return; } @@ -601,7 +601,7 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { updateSubplots([x0, y0, pw - dx, ph - dy]); ticksAndAnnotations(yActive, xActive); // updates computed in ticksAndAnnotations - gd.emit('plotly_relayout', updates); + gd.emit('plotly_relayouting', updates); } // Draw ticks and annotations (and other components) when ranges change. diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index b793339929a..a5a5f4954cc 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -215,7 +215,16 @@ function initializeGLPlot(scene, fullLayout, canvas, gl) { scene.saveCamera(scene.graphDiv.layout); scene.graphDiv.emit('plotly_relayout', update); }; - scene.glplot.canvas.addEventListener('mousemove', relayoutCallback.bind(null, scene)); + var relayoutingCallback = function(scene) { + if(scene.fullSceneLayout.dragmode === false) return; + var update = {}; + update[scene.id + '.camera'] = getLayoutCamera(scene.camera); + // scene.saveCamera(scene.graphDiv.layout); + scene.graphDiv.emit('plotly_relayouting', update); + }; + + scene.glplot.canvas.addEventListener('mousemove', relayoutingCallback.bind(null, scene)); + scene.glplot.canvas.addEventListener('mouseup', relayoutCallback.bind(null, scene)); scene.glplot.canvas.addEventListener('wheel', relayoutCallback.bind(null, scene), passiveSupported ? {passive: false} : false); if(!scene.staticMode) {