diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index e81be8142f3..8ee86a6da09 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -353,6 +353,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; } @@ -362,7 +394,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); @@ -370,10 +408,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 @@ -382,7 +416,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, @@ -493,6 +526,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_relayouting', updates); return; } @@ -565,6 +600,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_relayouting', updates); } // Draw ticks and annotations (and other components) when ranges change. 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/gl3d/scene.js b/src/plots/gl3d/scene.js index af02713a09c..a5a5f4954cc 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -215,7 +215,15 @@ function initializeGLPlot(scene, fullLayout, canvas, gl) { scene.saveCamera(scene.graphDiv.layout); scene.graphDiv.emit('plotly_relayout', update); }; + 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); 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/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); } diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js index 436397bc5aa..627abbbc0c1 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); }