From 746ec7e66a24d30872f10a238eb6658082685fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 13:36:24 -0400 Subject: [PATCH 01/10] add lassoPoints assertions --- test/jasmine/tests/select_test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index 86d0825700c..b9c7e6f4862 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -284,6 +284,11 @@ describe('select box and lasso', function() { y: 2.75, }], 'with the correct selected points (2)'); + expect(selectedData.lassoPoints.x).toBeCloseToArray( + [0.084, 0.087, 0.115, 0.103], 'lasso points x coords'); + expect(selectedData.lassoPoints.y).toBeCloseToArray( + [4.648, 1.342, 1.247, 4.821], 'lasso points y coords'); + doubleClick(250, 200).then(function() { expect(doubleClickData).toBe(null, 'with the correct deselect data'); done(); From 7d3dd3502e43de47e0518148304b8b0aad8963fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 15:54:15 -0400 Subject: [PATCH 02/10] implement arrayOk for marker.opacity in scattermapbox traces --- src/traces/scattermapbox/attributes.js | 4 +- src/traces/scattermapbox/convert.js | 62 ++++++++++++++---- test/image/baselines/mapbox_bubbles.png | Bin 59410 -> 45498 bytes test/image/mocks/mapbox_bubbles.json | 76 +++++------------------ test/jasmine/tests/scattermapbox_test.js | 40 +++++++++++- 5 files changed, 108 insertions(+), 74 deletions(-) diff --git a/src/traces/scattermapbox/attributes.js b/src/traces/scattermapbox/attributes.js index c061f1141aa..5085eeb48fe 100644 --- a/src/traces/scattermapbox/attributes.js +++ b/src/traces/scattermapbox/attributes.js @@ -82,9 +82,7 @@ module.exports = { 'are only available for *circle* symbols.' ].join(' ') }, - opacity: extendFlat({}, markerAttrs.opacity, { - arrayOk: false - }), + opacity: markerAttrs.opacity, size: markerAttrs.size, sizeref: markerAttrs.sizeref, sizemin: markerAttrs.sizemin, diff --git a/src/traces/scattermapbox/convert.js b/src/traces/scattermapbox/convert.js index 01312110dae..a6879db4ae7 100644 --- a/src/traces/scattermapbox/convert.js +++ b/src/traces/scattermapbox/convert.js @@ -9,6 +9,8 @@ 'use strict'; +var isNumeric = require('fast-isnumeric'); + var Lib = require('../../lib'); var BADNUM = require('../../constants/numerical').BADNUM; var geoJsonUtils = require('../../lib/geojson_utils'); @@ -20,7 +22,7 @@ var convertTextOpts = require('../../plots/mapbox/convert_text_opts'); var COLOR_PROP = 'circle-color'; var SIZE_PROP = 'circle-radius'; - +var OPACITY_PROP = 'circle-opacity'; module.exports = function convert(calcTrace) { var trace = calcTrace[0].trace; @@ -80,12 +82,13 @@ module.exports = function convert(calcTrace) { var hash = {}; hash[COLOR_PROP] = {}; hash[SIZE_PROP] = {}; + hash[OPACITY_PROP] = {}; circle.geojson = makeCircleGeoJSON(calcTrace, hash); circle.layout.visibility = 'visible'; Lib.extendFlat(circle.paint, { - 'circle-opacity': trace.opacity * trace.marker.opacity, + 'circle-opacity': calcCircleOpacity(trace, hash), 'circle-color': calcCircleColor(trace, hash), 'circle-radius': calcCircleRadius(trace, hash) }); @@ -179,8 +182,18 @@ function makeCircleGeoJSON(calcTrace, hash) { var sizeFn; if(subTypes.isBubble(trace)) { sizeFn = makeBubbleSizeFn(trace); - } else if(Array.isArray(marker.size)) { - sizeFn = Lib.identity; + } + + function combineOpacities(d, mo) { + return trace.opacity * mo; + } + + var opacityFn; + if(Array.isArray(marker.opacity)) { + opacityFn = function(d) { + var mo = isNumeric(d.mo) ? +Lib.constrain(d.mo, 0, 1) : 0; + return combineOpacities(d, mo); + }; } // Translate vals in trace arrayOk containers @@ -204,7 +217,12 @@ function makeCircleGeoJSON(calcTrace, hash) { var mcc = calcPt.mcc = colorFn(calcPt.mc); translate(props, COLOR_PROP, mcc, i); } - if(sizeFn) translate(props, SIZE_PROP, sizeFn(calcPt.ms), i); + if(sizeFn) { + translate(props, SIZE_PROP, sizeFn(calcPt.ms), i); + } + if(opacityFn) { + translate(props, OPACITY_PROP, opacityFn(calcPt), i); + } features.push({ type: 'Feature', @@ -304,14 +322,9 @@ function calcCircleRadius(trace, hash) { stops.push([ hash[SIZE_PROP][val], +val ]); } - // stops indices must be sorted - stops.sort(function(a, b) { - return a[0] - b[0]; - }); - out = { property: SIZE_PROP, - stops: stops + stops: stops.sort(ascending) }; } else { @@ -321,6 +334,31 @@ function calcCircleRadius(trace, hash) { return out; } +function calcCircleOpacity(trace, hash) { + var marker = trace.marker; + var out; + + if(Array.isArray(marker.opacity) || trace._hasDimmedPts) { + var vals = Object.keys(hash[OPACITY_PROP]); + var stops = []; + + for(var i = 0; i < vals.length; i++) { + var val = vals[i]; + stops.push([hash[OPACITY_PROP][val], +val]); + } + + out = { + property: OPACITY_PROP, + stops: stops.sort(ascending) + }; + } + else { + out = trace.opacity * marker.opacity; + } + + return out; +} + function getFillFunc(attr) { if(Array.isArray(attr)) { return function(v) { return v; }; @@ -335,6 +373,8 @@ function getFillFunc(attr) { function blankFillFunc() { return ''; } +function ascending(a, b) { return a[0] - b[0]; } + // only need to check lon (OR lat) function isBADNUM(lonlat) { return lonlat[0] === BADNUM; diff --git a/test/image/baselines/mapbox_bubbles.png b/test/image/baselines/mapbox_bubbles.png index 11b5e21aa7096ab3c2c1a497f74233878d8b2e5c..e0544baa69a7de144a8be5aaeb0e1362b47f2729 100644 GIT binary patch literal 45498 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 N*S>r%|Eyi;e*su;^WFde diff --git a/test/image/mocks/mapbox_bubbles.json b/test/image/mocks/mapbox_bubbles.json index 756ec774227..3f72cc2dbce 100644 --- a/test/image/mocks/mapbox_bubbles.json +++ b/test/image/mocks/mapbox_bubbles.json @@ -2,72 +2,30 @@ "data": [ { "type": "scattermapbox", - "lon": [ - 10, - 20, - 30 - ], - "lat": [ - 10, - 20, - 30 - ], + "lon": [10, 20, 30], + "lat": [10, 20, 30], "marker": { - "size": [ - 20, - 10, - 40 - ], - "color": [ - "red", - "blue", - "orange" - ] - } + "size": [20, 10, 40], + "color": ["red", "blue", "orange"], + "opacity": [0.3, 0.5, 1] + }, + "opacity": 0.7 }, { "type": "scattermapbox", - "lon": [ - -75, - -120, - 100 - ], - "lat": [ - 45, - 20, - -40 - ], + "lon": [-75, -120, 100], + "lat": [45, 20, -40], "marker": { - "size": [ - 60, - 20, - 40 - ], - "color": [ - 0, - 20, - 30 - ], + "size": [60, 20, 40], + "color": [0, 20, 30], "colorbar": {}, "cmin": 0, "cmax": 30, "colorscale": [ - [ - 0, - "rgb(220,220,220)" - ], - [ - 0.2, - "rgb(245,195,157)" - ], - [ - 0.4, - "rgb(245,160,105)" - ], - [ - 1, - "rgb(178,10,28)" - ] + [0, "rgb(220,220,220)"], + [0.2, "rgb(245,195,157)"], + [0.4, "rgb(245,160,105)"], + [1, "rgb(178,10,28)"] ] } } @@ -79,7 +37,7 @@ }, "showlegend": false, "height": 450, - "width": 1100, - "autosize": true + "width": 600, + "margin": {"l": 10} } } diff --git a/test/jasmine/tests/scattermapbox_test.js b/test/jasmine/tests/scattermapbox_test.js index 5045fd8532d..8b83201cfac 100644 --- a/test/jasmine/tests/scattermapbox_test.js +++ b/test/jasmine/tests/scattermapbox_test.js @@ -155,6 +155,8 @@ describe('scattermapbox convert', function() { stops: [ [0, 5], [1, 10], [2, 0] ] }, 'circle-radius stops'); + expect(opts.circle.paint['circle-opacity']).toBe(0.7, 'circle-opacity'); + var circleProps = opts.circle.geojson.features.map(function(f) { return f.properties; }); @@ -169,6 +171,43 @@ describe('scattermapbox convert', function() { ], 'geojson feature properties'); }); + it('should fill circle-opacity correctly', function() { + var opts = _convert(Lib.extendFlat({}, base, { + mode: 'markers', + marker: { + symbol: 'circle', + size: 10, + color: 'red', + opacity: [1, null, 0.5, '0.5', '1', 0, 0.8] + }, + opacity: 0.5 + })); + + assertVisibility(opts, ['none', 'none', 'visible', 'none']); + expect(opts.circle.paint['circle-color']).toBe('red', 'circle-color'); + expect(opts.circle.paint['circle-radius']).toBe(5, 'circle-radius'); + + expect(opts.circle.paint['circle-opacity']).toEqual({ + property: 'circle-opacity', + stops: [ [0, 0.5], [1, 0], [2, 0.25], [6, 0.4] ] + }, 'circle-opacity stops'); + + var circleProps = opts.circle.geojson.features.map(function(f) { + return f.properties; + }); + + + expect(circleProps).toEqual([ + { 'circle-opacity': 0 }, + { 'circle-opacity': 1 }, + { 'circle-opacity': 2 }, + // lat === null + // lon === null + { 'circle-opacity': 1 }, + { 'circle-opacity': 6 }, + ], 'geojson feature properties'); + }); + it('should generate correct output for fill + markers + lines traces', function() { var opts = _convert(Lib.extendFlat({}, base, { mode: 'markers+lines', @@ -510,7 +549,6 @@ describe('@noCI scattermapbox hover', function() { }); }); - describe('@noCI Test plotly events on a scattermapbox plot:', function() { var mock = require('@mocks/mapbox_0.json'); From 1d0b29ec291e6df053336b56a88a8034f6001334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 12:00:00 -0400 Subject: [PATCH 03/10] run mapbox image test with --queue options - `npm run test-image -- mapbox_*` sometimes blows up --- tasks/noci_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/noci_test.sh b/tasks/noci_test.sh index b4a2283b673..17d7dfc4c50 100755 --- a/tasks/noci_test.sh +++ b/tasks/noci_test.sh @@ -8,7 +8,7 @@ EXIT_STATE=0 npm run test-jasmine -- --tags=noCI --nowatch || EXIT_STATE=$? # mapbox image tests take too much resources on CI -npm run test-image -- mapbox_* || EXIT_STATE=$? +npm run test-image -- mapbox_* --queue || EXIT_STATE=$? # run gl2d image test again (some mocks are skipped on CI) npm run test-image-gl2d || EXIT_STATE=$? From e8b86240a793906ae061695a5aeb050621e0044a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 12:09:52 -0400 Subject: [PATCH 04/10] add 'scatter-like' category - to easily combine logic for scatter* trace types that use scatter/subtypes.js --- src/components/modebar/manage.js | 4 ++-- src/traces/scatter/index.js | 2 +- src/traces/scattergl/index.js | 2 +- src/traces/scattermapbox/index.js | 2 +- src/traces/scatterternary/index.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/modebar/manage.js b/src/components/modebar/manage.js index a97a86eb37d..4d8a0cb7fe8 100644 --- a/src/components/modebar/manage.js +++ b/src/components/modebar/manage.js @@ -121,7 +121,7 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) { if(((hasCartesian || hasGL2D) && !allAxesFixed) || hasTernary) { dragModeGroup = ['zoom2d', 'pan2d']; } - if((hasCartesian || hasTernary || hasGL2D) && isSelectable(fullData)) { + if(isSelectable(fullData)) { dragModeGroup.push('select2d'); dragModeGroup.push('lasso2d'); } @@ -173,7 +173,7 @@ function isSelectable(fullData) { if(!trace._module || !trace._module.selectPoints) continue; - if(trace.type === 'scatter' || trace.type === 'scatterternary' || trace.type === 'scattergl') { + if(Registry.traceIs(trace, 'scatter-like')) { if(scatterSubTypes.hasMarkers(trace) || scatterSubTypes.hasText(trace)) { selectable = true; } diff --git a/src/traces/scatter/index.js b/src/traces/scatter/index.js index 197b540e8d2..6817e4c8162 100644 --- a/src/traces/scatter/index.js +++ b/src/traces/scatter/index.js @@ -34,7 +34,7 @@ Scatter.animatable = true; Scatter.moduleType = 'trace'; Scatter.name = 'scatter'; Scatter.basePlotModule = require('../../plots/cartesian'); -Scatter.categories = ['cartesian', 'symbols', 'markerColorscale', 'errorBarsOK', 'showLegend']; +Scatter.categories = ['cartesian', 'symbols', 'markerColorscale', 'errorBarsOK', 'showLegend', 'scatter-like']; Scatter.meta = { description: [ 'The scatter trace type encompasses line charts, scatter charts, text charts, and bubble charts.', diff --git a/src/traces/scattergl/index.js b/src/traces/scattergl/index.js index 551e9adad7d..35d292f1c90 100644 --- a/src/traces/scattergl/index.js +++ b/src/traces/scattergl/index.js @@ -23,7 +23,7 @@ ScatterGl.selectPoints = require('./select'); ScatterGl.moduleType = 'trace'; ScatterGl.name = 'scattergl'; ScatterGl.basePlotModule = require('../../plots/gl2d'); -ScatterGl.categories = ['gl2d', 'symbols', 'errorBarsOK', 'markerColorscale', 'showLegend']; +ScatterGl.categories = ['gl2d', 'symbols', 'errorBarsOK', 'markerColorscale', 'showLegend', 'scatter-like']; ScatterGl.meta = { description: [ 'The data visualized as scatter point or lines is set in `x` and `y`', diff --git a/src/traces/scattermapbox/index.js b/src/traces/scattermapbox/index.js index 6de4241ed82..f8c939d42df 100644 --- a/src/traces/scattermapbox/index.js +++ b/src/traces/scattermapbox/index.js @@ -22,7 +22,7 @@ ScatterMapbox.plot = require('./plot'); ScatterMapbox.moduleType = 'trace'; ScatterMapbox.name = 'scattermapbox'; ScatterMapbox.basePlotModule = require('../../plots/mapbox'); -ScatterMapbox.categories = ['mapbox', 'gl', 'symbols', 'markerColorscale', 'showLegend']; +ScatterMapbox.categories = ['mapbox', 'gl', 'symbols', 'markerColorscale', 'showLegend', 'scatterlike']; ScatterMapbox.meta = { hrName: 'scatter_mapbox', description: [ diff --git a/src/traces/scatterternary/index.js b/src/traces/scatterternary/index.js index e7e75c4ddfc..abbdc7f06b1 100644 --- a/src/traces/scatterternary/index.js +++ b/src/traces/scatterternary/index.js @@ -22,7 +22,7 @@ ScatterTernary.selectPoints = require('./select'); ScatterTernary.moduleType = 'trace'; ScatterTernary.name = 'scatterternary'; ScatterTernary.basePlotModule = require('../../plots/ternary'); -ScatterTernary.categories = ['ternary', 'symbols', 'markerColorscale', 'showLegend']; +ScatterTernary.categories = ['ternary', 'symbols', 'markerColorscale', 'showLegend', 'scatter-like']; ScatterTernary.meta = { hrName: 'scatter_ternary', description: [ From 1f4eabb8e7d036fd33d23f43e5e0ea5adf310f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 13:47:15 -0400 Subject: [PATCH 05/10] allow prepSelect callers to set own fillRangeItems routine - e.g. to allow mapbox subplot convert px coords to lon/lat w/o hackely mocking too many things --- src/plots/cartesian/select.js | 64 +++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/plots/cartesian/select.js b/src/plots/cartesian/select.js index 045585cdbac..d8542f5c090 100644 --- a/src/plots/cartesian/select.js +++ b/src/plots/cartesian/select.js @@ -25,8 +25,9 @@ function getAxId(ax) { return ax._id; } module.exports = function prepSelect(e, startX, startY, dragOptions, mode) { var zoomLayer = dragOptions.gd._fullLayout._zoomlayer, dragBBox = dragOptions.element.getBoundingClientRect(), - xs = dragOptions.plotinfo.xaxis._offset, - ys = dragOptions.plotinfo.yaxis._offset, + plotinfo = dragOptions.plotinfo, + xs = plotinfo.xaxis._offset, + ys = plotinfo.yaxis._offset, x0 = startX - dragBBox.left, y0 = startY - dragBBox.top, x1 = x0, @@ -71,6 +72,7 @@ module.exports = function prepSelect(e, startX, startY, dragOptions, mode) { searchInfo, selection = [], eventData; + for(i = 0; i < gd.calcdata.length; i++) { cd = gd.calcdata[i]; trace = cd[0].trace; @@ -106,9 +108,41 @@ module.exports = function prepSelect(e, startX, startY, dragOptions, mode) { function ascending(a, b) { return a - b; } + // allow subplots to override fillRangeItems routine + var fillRangeItems; + + if(plotinfo.fillRangeItems) { + fillRangeItems = plotinfo.fillRangeItems; + } else { + if(mode === 'select') { + fillRangeItems = function(eventData, poly) { + var ranges = eventData.range = {}; + + for(i = 0; i < allAxes.length; i++) { + var ax = allAxes[i]; + var axLetter = ax._id.charAt(0); + + ranges[ax._id] = [ + ax.p2d(poly[axLetter + 'min']), + ax.p2d(poly[axLetter + 'max']) + ].sort(ascending); + } + }; + } else { + fillRangeItems = function(eventData, poly, pts) { + var dataPts = eventData.lassoPoints = {}; + + for(i = 0; i < allAxes.length; i++) { + var ax = allAxes[i]; + dataPts[ax._id] = pts.filtered.map(axValue(ax)); + } + }; + } + } + dragOptions.moveFn = function(dx0, dy0) { - var poly, - ax; + var poly; + x1 = Math.max(0, Math.min(pw, dx0 + x0)); y1 = Math.max(0, Math.min(ph, dy0 + y0)); @@ -158,27 +192,7 @@ module.exports = function prepSelect(e, startX, startY, dragOptions, mode) { } eventData = {points: selection}; - - if(mode === 'select') { - var ranges = eventData.range = {}, - axLetter; - - for(i = 0; i < allAxes.length; i++) { - ax = allAxes[i]; - axLetter = ax._id.charAt(0); - ranges[ax._id] = [ - ax.p2d(poly[axLetter + 'min']), - ax.p2d(poly[axLetter + 'max'])].sort(ascending); - } - } - else { - var dataPts = eventData.lassoPoints = {}; - - for(i = 0; i < allAxes.length; i++) { - ax = allAxes[i]; - dataPts[ax._id] = pts.filtered.map(axValue(ax)); - } - } + fillRangeItems(eventData, poly, pts); dragOptions.gd.emit('plotly_selecting', eventData); }; From 294e5f6c9d2e352c208d355b0e78ba7010afa90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 15:38:51 -0400 Subject: [PATCH 06/10] implement select/lasso dragmode for scattermapbox - create dragElement on mapbox subplot
when dragmode is set to select or lasso, - undo dragElement onmousedown handle for other dragmode values - keep ref to scattermapbox/plot instance in calcdata to call its update method directly in select - must keep track of trace with dimmed pts to go through arrayOk logic in scatter/convert --- src/plot_api/subroutines.js | 16 ++- src/plots/mapbox/mapbox.js | 82 +++++++++++++- src/traces/scattermapbox/convert.js | 7 +- src/traces/scattermapbox/index.js | 3 +- src/traces/scattermapbox/plot.js | 3 + src/traces/scattermapbox/select.js | 57 ++++++++++ test/jasmine/tests/scattermapbox_test.js | 66 +++++++++++- test/jasmine/tests/select_test.js | 132 +++++++++++++++++++++++ 8 files changed, 354 insertions(+), 12 deletions(-) create mode 100644 src/traces/scattermapbox/select.js diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js index 64d1663910d..a007e9ea940 100644 --- a/src/plot_api/subroutines.js +++ b/src/plot_api/subroutines.js @@ -378,21 +378,27 @@ exports.doTicksRelayout = function(gd) { exports.doModeBar = function(gd) { var fullLayout = gd._fullLayout; - var subplotIds, scene, i; + var subplotIds, subplotObj, i; ModeBar.manage(gd); initInteractions(gd); subplotIds = Plots.getSubplotIds(fullLayout, 'gl3d'); for(i = 0; i < subplotIds.length; i++) { - scene = fullLayout[subplotIds[i]]._scene; - scene.updateFx(fullLayout.dragmode, fullLayout.hovermode); + subplotObj = fullLayout[subplotIds[i]]._scene; + subplotObj.updateFx(fullLayout.dragmode, fullLayout.hovermode); } subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d'); for(i = 0; i < subplotIds.length; i++) { - scene = fullLayout._plots[subplotIds[i]]._scene2d; - scene.updateFx(fullLayout.dragmode); + subplotObj = fullLayout._plots[subplotIds[i]]._scene2d; + subplotObj.updateFx(fullLayout.dragmode); + } + + subplotIds = Plots.getSubplotIds(fullLayout, 'mapbox'); + for(i = 0; i < subplotIds.length; i++) { + subplotObj = fullLayout[subplotIds[i]]._subplot; + subplotObj.updateFx(fullLayout); } return Plots.previousPromises(gd); diff --git a/src/plots/mapbox/mapbox.js b/src/plots/mapbox/mapbox.js index 30e28eace91..b2212b01af9 100644 --- a/src/plots/mapbox/mapbox.js +++ b/src/plots/mapbox/mapbox.js @@ -13,6 +13,8 @@ var mapboxgl = require('mapbox-gl'); var Fx = require('../../components/fx'); var Lib = require('../../lib'); +var dragElement = require('../../components/dragelement'); +var prepSelect = require('../cartesian/select'); var constants = require('./constants'); var layoutAttributes = require('./layout_attributes'); var createMapboxLayer = require('./layers'); @@ -86,9 +88,9 @@ proto.plot = function(calcData, fullLayout, promises) { }; proto.createMap = function(calcData, fullLayout, resolve, reject) { - var self = this, - gd = self.gd, - opts = self.opts; + var self = this; + var gd = self.gd; + var opts = self.opts; // store style id and URL or object var styleObj = self.styleObj = getStyleObj(opts.style); @@ -107,7 +109,9 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) { pitch: opts.pitch, interactive: !self.isStatic, - preserveDrawingBuffer: self.isStatic + preserveDrawingBuffer: self.isStatic, + + boxZoom: false }); // clear navigation container @@ -128,6 +132,8 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) { self.resolveOnRender(resolve); }); + if(self.isStatic) return; + // keep track of pan / zoom in user layout and emit relayout event map.on('moveend', function(eventData) { if(!self.map) return; @@ -261,6 +267,7 @@ proto.updateLayout = function(fullLayout) { this.updateLayers(); this.updateFramework(fullLayout); + this.updateFx(fullLayout); this.map.resize(); }; @@ -314,6 +321,73 @@ proto.createFramework = function(fullLayout) { self.updateFramework(fullLayout); }; +proto.updateFx = function(fullLayout) { + var self = this; + var map = self.map; + var gd = self.gd; + + if(self.isStatic) return; + + function clearSelect() { + fullLayout._zoomlayer.selectAll('.select-outline').remove(); + } + + function invert(pxpy) { + var obj = self.map.unproject(pxpy); + return [obj.lng, obj.lat]; + } + + var dragMode = fullLayout.dragmode; + var fillRangeItems; + + if(dragMode === 'select') { + fillRangeItems = function(eventData, poly) { + var ranges = eventData.range = {}; + ranges[self.id] = [ + invert([poly.xmin, poly.ymin]), + invert([poly.xmax, poly.ymax]) + ]; + }; + } else { + fillRangeItems = function(eventData, poly, pts) { + var dataPts = eventData.lassoPoints = {}; + dataPts[self.id] = pts.filtered.map(invert); + }; + } + + if(dragMode === 'select' || dragMode === 'lasso') { + map.dragPan.disable(); + + var dragOptions = { + element: self.div, + gd: gd, + plotinfo: { + xaxis: self.xaxis, + yaxis: self.yaxis, + fillRangeItems: fillRangeItems + }, + xaxes: [self.xaxis], + yaxes: [self.yaxis], + subplot: self.id + }; + + dragOptions.prepFn = function(e, startX, startY) { + prepSelect(e, startX, startY, dragOptions, dragMode); + }; + + dragOptions.doneFn = function(dragged, numClicks) { + if(numClicks === 2) clearSelect(); + }; + + dragElement.init(dragOptions); + } else { + map.dragPan.enable(); + self.div.onmousedown = null; + } + + clearSelect(); +}; + proto.updateFramework = function(fullLayout) { var domain = fullLayout[this.id].domain, size = fullLayout._size; diff --git a/src/traces/scattermapbox/convert.js b/src/traces/scattermapbox/convert.js index a6879db4ae7..fbb70f08957 100644 --- a/src/traces/scattermapbox/convert.js +++ b/src/traces/scattermapbox/convert.js @@ -23,6 +23,7 @@ var convertTextOpts = require('../../plots/mapbox/convert_text_opts'); var COLOR_PROP = 'circle-color'; var SIZE_PROP = 'circle-radius'; var OPACITY_PROP = 'circle-opacity'; +var DESELECTDIM = 0.2; module.exports = function convert(calcTrace) { var trace = calcTrace[0].trace; @@ -185,7 +186,7 @@ function makeCircleGeoJSON(calcTrace, hash) { } function combineOpacities(d, mo) { - return trace.opacity * mo; + return trace.opacity * mo * (d.dim ? DESELECTDIM : 1); } var opacityFn; @@ -194,6 +195,10 @@ function makeCircleGeoJSON(calcTrace, hash) { var mo = isNumeric(d.mo) ? +Lib.constrain(d.mo, 0, 1) : 0; return combineOpacities(d, mo); }; + } else if(trace._hasDimmedPts) { + opacityFn = function(d) { + return combineOpacities(d, marker.opacity); + }; } // Translate vals in trace arrayOk containers diff --git a/src/traces/scattermapbox/index.js b/src/traces/scattermapbox/index.js index f8c939d42df..251432a82ff 100644 --- a/src/traces/scattermapbox/index.js +++ b/src/traces/scattermapbox/index.js @@ -15,9 +15,10 @@ ScatterMapbox.attributes = require('./attributes'); ScatterMapbox.supplyDefaults = require('./defaults'); ScatterMapbox.colorbar = require('../scatter/colorbar'); ScatterMapbox.calc = require('../scattergeo/calc'); +ScatterMapbox.plot = require('./plot'); ScatterMapbox.hoverPoints = require('./hover'); ScatterMapbox.eventData = require('./event_data'); -ScatterMapbox.plot = require('./plot'); +ScatterMapbox.selectPoints = require('./select'); ScatterMapbox.moduleType = 'trace'; ScatterMapbox.name = 'scattermapbox'; diff --git a/src/traces/scattermapbox/plot.js b/src/traces/scattermapbox/plot.js index f7cc4040a2f..0a4391371cf 100644 --- a/src/traces/scattermapbox/plot.js +++ b/src/traces/scattermapbox/plot.js @@ -92,6 +92,9 @@ proto.update = function update(calcTrace) { mapbox.setSourceData(this.idSourceSymbol, opts.symbol.geojson); mapbox.setOptions(this.idLayerSymbol, 'setPaintProperty', opts.symbol.paint); } + + // link ref for quick update during selections + calcTrace[0].trace._glTrace = this; }; proto.dispose = function dispose() { diff --git a/src/traces/scattermapbox/select.js b/src/traces/scattermapbox/select.js new file mode 100644 index 00000000000..5ceb57b51a4 --- /dev/null +++ b/src/traces/scattermapbox/select.js @@ -0,0 +1,57 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var subtypes = require('../scatter/subtypes'); + +module.exports = function selectPoints(searchInfo, polygon) { + var cd = searchInfo.cd; + var xa = searchInfo.xaxis; + var ya = searchInfo.yaxis; + var selection = []; + var trace = cd[0].trace; + + var di, lonlat, x, y, i; + + // flag used in ./convert.js + // to not insert data-driven 'circle-opacity' when we don't need to + trace._hasDimmedPts = false; + + if(trace.visible !== true || !subtypes.hasMarkers(trace)) return; + + if(polygon === false) { + for(i = 0; i < cd.length; i++) { + cd[i].dim = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + di = cd[i]; + lonlat = di.lonlat; + x = xa.c2p(lonlat); + y = ya.c2p(lonlat); + + if(polygon.contains([x, y])) { + trace._hasDimmedPts = true; + selection.push({ + pointNumber: i, + lon: lonlat[0], + lat: lonlat[1] + }); + di.dim = 0; + } else { + di.dim = 1; + } + } + } + + trace._glTrace.update(cd); + + return selection; +}; diff --git a/test/jasmine/tests/scattermapbox_test.js b/test/jasmine/tests/scattermapbox_test.js index 8b83201cfac..938f96cd445 100644 --- a/test/jasmine/tests/scattermapbox_test.js +++ b/test/jasmine/tests/scattermapbox_test.js @@ -114,7 +114,7 @@ describe('scattermapbox convert', function() { jasmine.addMatchers(customMatchers); }); - function _convert(trace) { + function _convert(trace, selected) { var gd = { data: [trace] }; Plots.supplyDefaults(gd); @@ -122,6 +122,18 @@ describe('scattermapbox convert', function() { Plots.doCalcdata(gd, fullTrace); var calcTrace = gd.calcdata[0]; + + if(selected) { + var hasDimmedPts = false; + + selected.forEach(function(v, i) { + if(v) hasDimmedPts = true; + calcTrace[i].dim = v; + }); + + fullTrace._hasDimmedPts = hasDimmedPts; + } + return convert(calcTrace); } @@ -208,6 +220,58 @@ describe('scattermapbox convert', function() { ], 'geojson feature properties'); }); + it('should fill circle-opacity correctly during selections', function() { + var _base = { + type: 'scattermapbox', + mode: 'markers', + lon: [-10, 30, 20], + lat: [45, 90, 180], + marker: {symbol: 'circle'} + }; + + var specs = [{ + patch: {}, + selected: [0, 1, 1], + expected: {stops: [[0, 1], [1, 0.2]], props: [0, 1, 1]} + }, { + patch: {opacity: 0.5}, + selected: [0, 1, 1], + expected: {stops: [[0, 0.5], [1, 0.1]], props: [0, 1, 1]} + }, { + patch: { + marker: {opacity: 0.6} + }, + selected: [1, 0, 1], + expected: {stops: [[0, 0.12], [1, 0.6]], props: [0, 1, 0]} + }, { + patch: { + marker: {opacity: [0.5, 1, 0.6]} + }, + selected: [1, 0, 1], + expected: {stops: [[0, 0.1], [1, 1], [2, 0.12]], props: [0, 1, 2]} + }, { + patch: { + marker: {opacity: [2, null, -0.6]} + }, + selected: [1, 1, 1], + expected: {stops: [[0, 0.2], [1, 0]], props: [0, 1, 1]} + }]; + + specs.forEach(function(s, i) { + var msg0 = '- case ' + i + ' '; + var opts = _convert(Lib.extendDeep({}, _base, s.patch), s.selected); + + expect(opts.circle.paint['circle-opacity'].stops) + .toEqual(s.expected.stops, msg0 + 'stops'); + + var props = opts.circle.geojson.features.map(function(f) { + return f.properties['circle-opacity']; + }); + + expect(props).toEqual(s.expected.props, msg0 + 'props'); + }); + }); + it('should generate correct output for fill + markers + lines traces', function() { var opts = _convert(Lib.extendFlat({}, base, { mode: 'markers+lines', diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index b9c7e6f4862..ac26eccb435 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -10,6 +10,8 @@ var fail = require('../assets/fail_test'); var mouseEvent = require('../assets/mouse_event'); var customMatchers = require('../assets/custom_matchers'); +var LONG_TIMEOUT_INTERVAL = 5 * jasmine.DEFAULT_TIMEOUT_INTERVAL; + describe('select box and lasso', function() { var mock = require('@mocks/14.json'); @@ -465,4 +467,134 @@ describe('select box and lasso', function() { .catch(fail) .then(done); }); + + it('@noCI should work on scattermapbox traces', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/mapbox_bubbles-text')); + var gd = createGraphDiv(); + var eventData; + + fig.layout.dragmode = 'select'; + fig.config = { + mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN + }; + + function assertPoints(expected) { + var pts = eventData.points || []; + + expect(pts.length).toBe(expected.length, 'selected points length'); + + pts.forEach(function(p, i) { + var e = expected[i]; + expect(p.lon).toBe(e.lon, 'selected pt lon val'); + expect(p.lat).toBe(e.lat, 'selected pt lat val'); + }); + } + + function assertRanges(expected) { + var ranges = (eventData.range || {}).mapbox || []; + expect(ranges).toBeCloseTo2DArray(expected, 1, 'select box range (in lon/lat)'); + } + + function assertLassoPoints(expected) { + var lassoPoints = (eventData.lassoPoints || {}).mapbox || []; + expect(lassoPoints).toBeCloseTo2DArray(expected, 1, 'lasso points (in lon/lat)'); + } + + Plotly.plot(gd, fig).then(function() { + var selectingCnt = 0; + var selectedCnt = 0; + var deselectCnt = 0; + + gd.once('plotly_selecting', function() { + assertSelectionNodes(1, 2); + selectingCnt++; + }); + + gd.once('plotly_selected', function(d) { + assertSelectionNodes(0, 2); + selectedCnt++; + eventData = d; + }); + + gd.once('plotly_deselect', function() { + deselectCnt++; + assertSelectionNodes(0, 0); + }); + + drag([[370, 120], [500, 200]]); + assertPoints([{lon: 30, lat: 30}]); + assertRanges([[21.99, 34.55], [38.14, 25.98]]); + + return doubleClick(250, 200).then(function() { + expect(selectingCnt).toBe(1, 'plotly_selecting call count'); + expect(selectedCnt).toBe(1, 'plotly_selected call count'); + expect(deselectCnt).toBe(1, 'plotly_deselect call count'); + }); + }) + .then(function() { + return Plotly.relayout(gd, 'dragmode', 'lasso'); + }) + .then(function() { + var selectingCnt = 0; + var selectedCnt = 0; + var deselectCnt = 0; + + gd.once('plotly_selecting', function() { + assertSelectionNodes(1, 2); + selectingCnt++; + }); + + gd.once('plotly_selected', function(d) { + assertSelectionNodes(0, 2); + selectedCnt++; + eventData = d; + }); + + gd.once('plotly_deselect', function() { + deselectCnt++; + assertSelectionNodes(0, 0); + }); + + drag([[300, 200], [300, 300], [400, 300], [400, 200], [300, 200]]); + assertPoints([{lon: 20, lat: 20}]); + assertLassoPoints([ + [13.28, 25.97], [13.28, 14.33], [25.71, 14.33], [25.71, 25.97], [13.28, 25.97] + ]); + + return doubleClick(250, 200).then(function() { + expect(selectingCnt).toBe(1, 'plotly_selecting call count'); + expect(selectedCnt).toBe(1, 'plotly_selected call count'); + expect(deselectCnt).toBe(1, 'plotly_deselect call count'); + }); + }) + .then(function() { + // make selection handlers don't get called in 'pan' dragmode + return Plotly.relayout(gd, 'dragmode', 'pan'); + }) + .then(function() { + var selectingCnt = 0; + var selectedCnt = 0; + var deselectCnt = 0; + + gd.once('plotly_selecting', function() { + selectingCnt++; + }); + + gd.once('plotly_selected', function() { + selectedCnt++; + }); + + gd.once('plotly_deselect', function() { + deselectCnt++; + }); + + return doubleClick(250, 200).then(function() { + expect(selectingCnt).toBe(0, 'plotly_selecting call count'); + expect(selectedCnt).toBe(0, 'plotly_selected call count'); + expect(deselectCnt).toBe(0, 'plotly_deselect call count'); + }); + }) + .catch(fail) + .then(done); + }, LONG_TIMEOUT_INTERVAL); }); From 744f3c8d8c80dda9e03086d5df13d04d24a625e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 15:41:11 -0400 Subject: [PATCH 07/10] rename glTrace ref on scattergl fullTrace to _glTrace - ... as it should have been all along, non-attribute keys in fullTrace (and fullLayout for that matter) should be named with a leading underscore. - scattergl glTrace ref is now consistent with the scattermapbox version --- src/lib/index.js | 2 +- src/traces/scattergl/convert.js | 4 ++-- src/traces/scattergl/select.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/index.js b/src/lib/index.js index 25eff611e5c..8518d176d1d 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -451,7 +451,7 @@ lib.minExtend = function(obj1, obj2) { for(i = 0; i < keys.length; i++) { k = keys[i]; v = obj1[k]; - if(k.charAt(0) === '_' || typeof v === 'function' || k === 'glTrace') continue; + if(k.charAt(0) === '_' || typeof v === 'function') continue; else if(k === 'module') objOut[k] = v; else if(Array.isArray(v)) objOut[k] = v.slice(0, arrayLen); else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]); diff --git a/src/traces/scattergl/convert.js b/src/traces/scattergl/convert.js index f99a4a73a62..eae12e53298 100644 --- a/src/traces/scattergl/convert.js +++ b/src/traces/scattergl/convert.js @@ -322,8 +322,8 @@ proto.update = function(options, cdscatter) { this.color = getTraceColor(options, {}); // provide reference for selecting points - if(cdscatter && cdscatter[0] && !cdscatter[0].glTrace) { - cdscatter[0].glTrace = this; + if(cdscatter && cdscatter[0] && !cdscatter[0]._glTrace) { + cdscatter[0]._glTrace = this; } }; diff --git a/src/traces/scattergl/select.js b/src/traces/scattergl/select.js index 548824ad740..f594c69dd74 100644 --- a/src/traces/scattergl/select.js +++ b/src/traces/scattergl/select.js @@ -22,8 +22,8 @@ module.exports = function selectPoints(searchInfo, polygon) { x, y; - var scattergl = cd[0].glTrace; - var scene = cd[0].glTrace.scene; + var glTrace = cd[0]._glTrace; + var scene = glTrace.scene; var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace)); if(trace.visible !== true || hasOnlyLines) return; @@ -53,7 +53,7 @@ module.exports = function selectPoints(searchInfo, polygon) { // highlight selected points here trace.selection = selection; - scattergl.update(trace, cd); + glTrace.update(trace, cd); scene.glplot.setDirty(); return selection; From e3aa07da0176a915369586114ce226edf8d20109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 15:47:42 -0400 Subject: [PATCH 08/10] add dragmode pan button to mapbox modebar - and set dragmode to 'pan' in fullLayout when its value is coerced to 'zoom' so the corresponding modebar button is correctly highlighted. - do this until dragmode 'zoom' (i.e. a zoombox like behavior) is implemented. --- src/components/fx/layout_defaults.js | 8 ++++++++ src/components/modebar/manage.js | 7 ++++++- test/jasmine/tests/mapbox_test.js | 13 ++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/components/fx/layout_defaults.js b/src/components/fx/layout_defaults.js index 13d5d631919..a4800d094f0 100644 --- a/src/components/fx/layout_defaults.js +++ b/src/components/fx/layout_defaults.js @@ -28,6 +28,14 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { else hovermodeDflt = 'closest'; coerce('hovermode', hovermodeDflt); + + // if only mapbox subplots is present on graph, + // reset 'zoom' dragmode to 'pan' until 'zoom' is implemented, + // so that the correct modebar button is active + if(layoutOut._has('mapbox') && layoutOut._basePlotModules.length === 1 && + layoutOut.dragmode === 'zoom') { + layoutOut.dragmode = 'pan'; + } }; function isHoriz(fullData) { diff --git a/src/components/modebar/manage.js b/src/components/modebar/manage.js index 4d8a0cb7fe8..5cb86a9eea2 100644 --- a/src/components/modebar/manage.js +++ b/src/components/modebar/manage.js @@ -11,6 +11,7 @@ var Axes = require('../../plots/cartesian/axes'); var scatterSubTypes = require('../../traces/scatter/subtypes'); +var Registry = require('../../registry'); var createModeBar = require('./modebar'); var modeBarButtons = require('./buttons'); @@ -78,7 +79,8 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) { hasGeo = fullLayout._has('geo'), hasPie = fullLayout._has('pie'), hasGL2D = fullLayout._has('gl2d'), - hasTernary = fullLayout._has('ternary'); + hasTernary = fullLayout._has('ternary'), + hasMapbox = fullLayout._has('mapbox'); var groups = []; @@ -121,6 +123,9 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) { if(((hasCartesian || hasGL2D) && !allAxesFixed) || hasTernary) { dragModeGroup = ['zoom2d', 'pan2d']; } + if(hasMapbox) { + dragModeGroup = ['pan2d']; + } if(isSelectable(fullData)) { dragModeGroup.push('select2d'); dragModeGroup.push('lasso2d'); diff --git a/test/jasmine/tests/mapbox_test.js b/test/jasmine/tests/mapbox_test.js index 49b4583ff7f..050605b2494 100644 --- a/test/jasmine/tests/mapbox_test.js +++ b/test/jasmine/tests/mapbox_test.js @@ -1,4 +1,5 @@ var Plotly = require('@lib'); +var Plots = require('@src/plots/plots'); var Lib = require('@src/lib'); var constants = require('@src/plots/mapbox/constants'); @@ -31,7 +32,7 @@ describe('mapbox defaults', function() { beforeEach(function() { layoutOut = { font: { color: 'red' } }; - // needs a ternary-ref in a trace in order to be detected + // needs a mapbox-ref in a trace in order to be detected fullData = [{ type: 'scattermapbox', subplot: 'mapbox' }]; }); @@ -170,6 +171,16 @@ describe('mapbox defaults', function() { expect(layoutOut.mapbox.layers[3].fill).toBeUndefined(); expect(layoutOut.mapbox.layers[3].circle).toBeUndefined(); }); + + it('should set *layout.dragmode* to pan while zoom is not available', function() { + var gd = { + data: fullData, + layout: {} + }; + + Plots.supplyDefaults(gd); + expect(gd._fullLayout.dragmode).toBe('pan'); + }); }); describe('mapbox credentials', function() { From a376817ede86fc1c0e7e868cd3e33c79a415b00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 30 Jun 2017 16:41:27 -0400 Subject: [PATCH 09/10] clear all selection outlines in one place - during supplyDefaults --- src/plots/cartesian/index.js | 5 ----- src/plots/mapbox/mapbox.js | 10 +++------- src/plots/plots.js | 4 ++++ src/plots/ternary/index.js | 4 ---- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 883acb4d0d8..0649a155296 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -184,11 +184,6 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) oldFullLayout._infolayer.select('.' + axIds[i] + 'title').remove(); } } - - // clean selection - if(oldFullLayout._zoomlayer) { - oldFullLayout._zoomlayer.selectAll('.select-outline').remove(); - } }; exports.drawFramework = function(gd) { diff --git a/src/plots/mapbox/mapbox.js b/src/plots/mapbox/mapbox.js index b2212b01af9..e2c923421b6 100644 --- a/src/plots/mapbox/mapbox.js +++ b/src/plots/mapbox/mapbox.js @@ -328,10 +328,6 @@ proto.updateFx = function(fullLayout) { if(self.isStatic) return; - function clearSelect() { - fullLayout._zoomlayer.selectAll('.select-outline').remove(); - } - function invert(pxpy) { var obj = self.map.unproject(pxpy); return [obj.lng, obj.lat]; @@ -376,7 +372,9 @@ proto.updateFx = function(fullLayout) { }; dragOptions.doneFn = function(dragged, numClicks) { - if(numClicks === 2) clearSelect(); + if(numClicks === 2) { + fullLayout._zoomlayer.selectAll('.select-outline').remove(); + } }; dragElement.init(dragOptions); @@ -384,8 +382,6 @@ proto.updateFx = function(fullLayout) { map.dragPan.enable(); self.div.onmousedown = null; } - - clearSelect(); }; proto.updateFramework = function(fullLayout) { diff --git a/src/plots/plots.js b/src/plots/plots.js index 38416678886..de398f4353b 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -624,6 +624,10 @@ plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayou .selectAll(query).remove(); } } + + if(oldFullLayout._zoomlayer) { + oldFullLayout._zoomlayer.selectAll('.select-outline').remove(); + } }; plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { diff --git a/src/plots/ternary/index.js b/src/plots/ternary/index.js index 2b24ed0938a..e1da80af7b1 100644 --- a/src/plots/ternary/index.js +++ b/src/plots/ternary/index.js @@ -69,8 +69,4 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) oldTernary.clipDef.remove(); } } - - if(oldFullLayout._zoomlayer) { - oldFullLayout._zoomlayer.selectAll('.select-outline').remove(); - } }; From 882e8e39c4e0d2ed4fc1735121705191f608bb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Etienne=20T=C3=A9treault-Pinard?= Date: Mon, 10 Jul 2017 18:09:48 -0400 Subject: [PATCH 10/10] put DESELECTDIM in interactions constants file --- src/constants/interactions.js | 5 ++++- src/traces/scatter/select.js | 3 +-- src/traces/scattergl/convert.js | 2 +- src/traces/scattermapbox/convert.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/constants/interactions.js b/src/constants/interactions.js index 3e56a09f434..20044ea85f9 100644 --- a/src/constants/interactions.js +++ b/src/constants/interactions.js @@ -18,5 +18,8 @@ module.exports = { // ms between first mousedown and 2nd mouseup to constitute dblclick... // we don't seem to have access to the system setting - DBLCLICKDELAY: 300 + DBLCLICKDELAY: 300, + + // opacity dimming fraction for points that are not in selection + DESELECTDIM: 0.2 }; diff --git a/src/traces/scatter/select.js b/src/traces/scatter/select.js index 127179a790c..22aedd1685b 100644 --- a/src/traces/scatter/select.js +++ b/src/traces/scatter/select.js @@ -10,8 +10,7 @@ 'use strict'; var subtypes = require('./subtypes'); - -var DESELECTDIM = 0.2; +var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; module.exports = function selectPoints(searchInfo, polygon) { var cd = searchInfo.cd, diff --git a/src/traces/scattergl/convert.js b/src/traces/scattergl/convert.js index eae12e53298..5b7be4466d9 100644 --- a/src/traces/scattergl/convert.js +++ b/src/traces/scattergl/convert.js @@ -27,9 +27,9 @@ var makeBubbleSizeFn = require('../scatter/make_bubble_size_func'); var getTraceColor = require('../scatter/get_trace_color'); var MARKER_SYMBOLS = require('../../constants/gl2d_markers'); var DASHES = require('../../constants/gl2d_dashes'); +var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; var AXES = ['xaxis', 'yaxis']; -var DESELECTDIM = 0.2; var TRANSPARENT = [0, 0, 0, 0]; function LineWithMarkers(scene, uid) { diff --git a/src/traces/scattermapbox/convert.js b/src/traces/scattermapbox/convert.js index fbb70f08957..7b88ee647d6 100644 --- a/src/traces/scattermapbox/convert.js +++ b/src/traces/scattermapbox/convert.js @@ -19,11 +19,11 @@ var Colorscale = require('../../components/colorscale'); var makeBubbleSizeFn = require('../scatter/make_bubble_size_func'); var subTypes = require('../scatter/subtypes'); var convertTextOpts = require('../../plots/mapbox/convert_text_opts'); +var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; var COLOR_PROP = 'circle-color'; var SIZE_PROP = 'circle-radius'; var OPACITY_PROP = 'circle-opacity'; -var DESELECTDIM = 0.2; module.exports = function convert(calcTrace) { var trace = calcTrace[0].trace;