From e6fcbf51de4b41db470b7194835b20f57f06098f Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 14 Nov 2017 15:32:05 -0500 Subject: [PATCH 01/12] Introduce global contexts --- src/plot_api/plot_api.js | 56 ++++++++++++++- src/plots/cartesian/dragbox.js | 21 +++++- src/plots/cartesian/index.js | 9 +++ src/plots/gl2d/scene2d.js | 6 +- src/plots/plots.js | 19 ++++- src/traces/contourgl/index.js | 2 +- src/traces/heatmapgl/index.js | 2 +- src/traces/parcoords/base_plot.js | 18 ++--- src/traces/parcoords/index.js | 2 +- src/traces/parcoords/lines.js | 51 ++++++++++---- src/traces/parcoords/parcoords.js | 81 +++++++--------------- src/traces/parcoords/plot.js | 4 +- src/traces/pointcloud/index.js | 2 +- src/traces/scattergl/index.js | 2 +- test/image/baselines/gl2d_parcoords_2.png | Bin 37023 -> 29852 bytes 15 files changed, 176 insertions(+), 99 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index e4a1e83d9bb..feccc268771 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -42,6 +42,8 @@ var enforceAxisConstraints = axisConstraints.enforce; var cleanAxisConstraints = axisConstraints.clean; var axisIds = require('../plots/cartesian/axis_ids'); +var createRegl = require('regl'); + /** * Main plot-creation function @@ -195,6 +197,51 @@ Plotly.plot = function(gd, data, layout, config) { } } + if(!fullLayout._glcanvas && fullLayout._has('gl')) { + fullLayout._glcanvas = fullLayout._glcontainer.selectAll('.gl-canvas').data([{ + key: 'contextLayer', + context: true, + pick: false + }, { + key: 'focusLayer', + context: false, + pick: false + }, { + key: 'pickLayer', + context: false, + pick: true + }]); + + fullLayout._glcanvas.enter().append('canvas') + .each(function(d) { + d.regl = createRegl({ + canvas: this, + attributes: { + antialias: !d.pick, + preserveDrawingBuffer: true + }, + extensions: ['ANGLE_instanced_arrays', 'OES_element_index_uint'], + pixelRatio: gd._context.plotGlPixelRatio || global.devicePixelRatio + }); + }) + .attr('class', function(d) { + return 'gl-canvas gl-canvas-' + d.key.replace('Layer', ''); + }) + .style({ + 'position': 'absolute', + 'top': 0, + 'left': 0, + 'width': '100%', + 'height': '100%', + 'pointer-events': 'none', + 'overflow': 'visible' + }) + .attr('width', fullLayout.width) + .attr('height', fullLayout.height); + + fullLayout._glcanvas.exit().remove(); + } + return Lib.syncOrAsync([ subroutines.layoutStyles ], gd); @@ -1993,7 +2040,7 @@ function _relayout(gd, aobj) { else flags.plot = true; } else { - if(fullLayout._has('gl2d') && + if((fullLayout._has('gl2d') || fullLayout._has('regl')) && (ai === 'dragmode' && (vi === 'lasso' || vi === 'select') && !(vOld === 'lasso' || vOld === 'select')) @@ -2754,7 +2801,7 @@ function makePlotFramework(gd) { .classed('plotly', true); // Make the svg container - fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([0]); + fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([{}]); fullLayout._paperdiv.enter().append('div') .classed('svg-container', true) .style('position', 'relative'); @@ -2765,10 +2812,13 @@ function makePlotFramework(gd) { // TODO: sort out all the ordering so we don't have to // explicitly delete anything fullLayout._glcontainer = fullLayout._paperdiv.selectAll('.gl-container') - .data([0]); + .data([{}]); fullLayout._glcontainer.enter().append('div') .classed('gl-container', true); + // That is initialized in drawFramework if there are `gl` traces + fullLayout._glcanvas = null; + fullLayout._paperdiv.selectAll('.main-svg').remove(); fullLayout._paper = fullLayout._paperdiv.insert('svg', ':first-child') diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 4a81f4a625f..c895bbd8e48 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -711,14 +711,33 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) { return ax._length * (1 - scaleFactor) * FROM_TL[ax.constraintoward || 'middle']; } - for(i = 0; i < subplots.length; i++) { + // clear gl frame, if any, since we preserve drawing buffer + // FIXME: code duplication with cartesian.plot + if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { + fullLayout._glcanvas.each(function(d) { + d.regl.clear({ + color: true + }); + }); + } + for(i = 0; i < subplots.length; i++) { var subplot = plotinfos[subplots[i]], xa2 = subplot.xaxis, ya2 = subplot.yaxis, editX2 = editX && !xa2.fixedrange && (xa.indexOf(xa2) !== -1), editY2 = editY && !ya2.fixedrange && (ya.indexOf(ya2) !== -1); + // scattergl translate + if(subplot._scene && subplot._scene.update) { + // FIXME: possibly we could update axis internal _r and _rl here + var xaRange = Lib.simpleMap(xa2.range, xa2.r2l), + yaRange = Lib.simpleMap(ya2.range, ya2.r2l); + subplot._scene.update( + {range: [xaRange[0], yaRange[0], xaRange[1], yaRange[1]]} + ); + } + if(editX2) { xScaleFactor2 = xScaleFactor; clipDx = ew ? viewBox[0] : getShift(xa2, xScaleFactor2); diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 3ca43838d02..428cb89e25c 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -48,6 +48,15 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { } } + // clear gl frame, if any, since we preserve drawing buffer + if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { + fullLayout._glcanvas.each(function(d) { + d.regl.clear({ + color: true + }); + }); + } + for(i = 0; i < subplots.length; i++) { var subplot = subplots[i], subplotInfo = fullLayout._plots[subplot]; diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index e0db40f622a..0a190078452 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -112,7 +112,7 @@ proto.makeFramework = function() { this.gl = STATIC_CONTEXT; } else { - var liveCanvas = document.createElement('canvas'); + var liveCanvas = this.container.querySelector('.gl-canvas-focus'); var gl = getContext({ canvas: liveCanvas, @@ -140,7 +140,7 @@ proto.makeFramework = function() { // disabling user select on the canvas // sanitizes double-clicks interactions // ref: https://github.com/plotly/plotly.js/issues/744 - canvas.className += 'user-select-none'; + canvas.className += ' user-select-none'; // create SVG container for hover text var svgContainer = this.svgContainer = document.createElementNS( @@ -159,7 +159,6 @@ proto.makeFramework = function() { // append canvas, hover svg and mouse div to container var container = this.container; - container.appendChild(canvas); container.appendChild(svgContainer); container.appendChild(mouseContainer); @@ -370,7 +369,6 @@ proto.destroy = function() { this.glplot.dispose(); - if(!this.staticPlot) this.container.removeChild(this.canvas); this.container.removeChild(this.svgContainer); this.container.removeChild(this.mouseContainer); diff --git a/src/plots/plots.js b/src/plots/plots.js index 7e0973196f6..7525b0ac9eb 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -569,15 +569,29 @@ plots.createTransitionData = function(gd) { // helper function to be bound to fullLayout to check // whether a certain plot type is present on plot +// or trace has a category plots._hasPlotType = function(category) { + // check plot + var basePlotModules = this._basePlotModules || []; + var i; - for(var i = 0; i < basePlotModules.length; i++) { + for(i = 0; i < basePlotModules.length; i++) { var _module = basePlotModules[i]; if(_module.name === category) return true; } + // check trace + var modules = this._modules || []; + + for(i = 0; i < modules.length; i++) { + var _ = modules[i]; + if(_.categories && _.categories.indexOf(category) >= 0) { + return true; + } + } + return false; }; @@ -1319,6 +1333,9 @@ plots.purge = function(gd) { } } + // remove any planned throttles + Lib.clearThrottle(); + // data and layout delete gd.data; delete gd.layout; diff --git a/src/traces/contourgl/index.js b/src/traces/contourgl/index.js index 9dfb61d0de5..fdb89747810 100644 --- a/src/traces/contourgl/index.js +++ b/src/traces/contourgl/index.js @@ -23,7 +23,7 @@ ContourGl.plot = require('./convert'); ContourGl.moduleType = 'trace'; ContourGl.name = 'contourgl'; ContourGl.basePlotModule = require('../../plots/gl2d'); -ContourGl.categories = ['gl2d', '2dMap']; +ContourGl.categories = ['gl', 'gl2d', '2dMap']; ContourGl.meta = { description: [ 'WebGL contour (beta)' diff --git a/src/traces/heatmapgl/index.js b/src/traces/heatmapgl/index.js index 19ac6fe15f4..dca703e7f85 100644 --- a/src/traces/heatmapgl/index.js +++ b/src/traces/heatmapgl/index.js @@ -21,7 +21,7 @@ HeatmapGl.plot = require('./convert'); HeatmapGl.moduleType = 'trace'; HeatmapGl.name = 'heatmapgl'; HeatmapGl.basePlotModule = require('../../plots/gl2d'); -HeatmapGl.categories = ['gl2d', '2dMap']; +HeatmapGl.categories = ['gl', 'gl2d', '2dMap']; HeatmapGl.meta = { description: [ 'WebGL version of the heatmap trace type.' diff --git a/src/traces/parcoords/base_plot.js b/src/traces/parcoords/base_plot.js index e5be3285b75..c562787b289 100644 --- a/src/traces/parcoords/base_plot.js +++ b/src/traces/parcoords/base_plot.js @@ -12,7 +12,6 @@ var d3 = require('d3'); var Plots = require('../../plots/plots'); var parcoordsPlot = require('./plot'); var xmlnsNamespaces = require('../../constants/xmlns_namespaces'); -var c = require('./constants'); exports.name = 'parcoords'; @@ -28,9 +27,6 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) var hasParcoords = (newFullLayout._has && newFullLayout._has('parcoords')); if(hadParcoords && !hasParcoords) { - oldFullLayout._paperdiv.selectAll('.parcoords-line-layers').remove(); - oldFullLayout._paperdiv.selectAll('.parcoords-line-layers').remove(); - oldFullLayout._paperdiv.selectAll('.parcoords').remove(); oldFullLayout._paperdiv.selectAll('.parcoords').remove(); oldFullLayout._glimages.selectAll('*').remove(); } @@ -41,22 +37,20 @@ exports.toSVG = function(gd) { var imageRoot = gd._fullLayout._glimages; var root = d3.select(gd).selectAll('.svg-container'); var canvases = root.filter(function(d, i) {return i === root.size() - 1;}) - .selectAll('.parcoords-lines.context, .parcoords-lines.focus'); + .selectAll('.gl-canvas-context, .gl-canvas-focus'); - function canvasToImage(d) { + function canvasToImage() { var canvas = this; var imageData = canvas.toDataURL('image/png'); var image = imageRoot.append('svg:image'); - var size = gd._fullLayout._size; - var domain = gd._fullData[d.model.key].domain; image.attr({ xmlns: xmlnsNamespaces.svg, 'xlink:href': imageData, - x: size.l + size.w * domain.x[0] - c.overdrag, - y: size.t + size.h * (1 - domain.y[1]), - width: (domain.x[1] - domain.x[0]) * size.w + 2 * c.overdrag, - height: (domain.y[1] - domain.y[0]) * size.h, + x: 0, + y: 0, + width: canvas.width, + height: canvas.height, preserveAspectRatio: 'none' }); } diff --git a/src/traces/parcoords/index.js b/src/traces/parcoords/index.js index 920cec76473..fb71f73692d 100644 --- a/src/traces/parcoords/index.js +++ b/src/traces/parcoords/index.js @@ -19,7 +19,7 @@ Parcoords.colorbar = require('./colorbar'); Parcoords.moduleType = 'trace'; Parcoords.name = 'parcoords'; Parcoords.basePlotModule = require('./base_plot'); -Parcoords.categories = ['gl', 'noOpacity']; +Parcoords.categories = ['gl', 'regl', 'noOpacity']; Parcoords.meta = { description: [ 'Parallel coordinates for multidimensional exploratory data analysis.', diff --git a/src/traces/parcoords/lines.js b/src/traces/parcoords/lines.js index 92776dabf0a..7e20a6b65d4 100644 --- a/src/traces/parcoords/lines.js +++ b/src/traces/parcoords/lines.js @@ -8,9 +8,8 @@ 'use strict'; -var createREGL = require('regl'); var glslify = require('glslify'); -var verticalPadding = require('./constants').verticalPadding; +var c = require('./constants'); var vertexShaderSource = glslify('./shaders/vertex.glsl'); var pickVertexShaderSource = glslify('./shaders/pick_vertex.glsl'); var fragmentShaderSource = glslify('./shaders/fragment.glsl'); @@ -165,7 +164,19 @@ function valid(i, offset, panelCount) { return i + offset <= panelCount; } -module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDimensions, initialPanels, unitToColor, context, pick, scatter) { +module.exports = module.exports = function(canvasGL, d, scatter) { + var model = d.model, + vm = d.viewModel, + domain = model.domain; + + var lines = model.lines, + canvasWidth = model.canvasWidth, + canvasHeight = model.canvasHeight, + initialDimensions = vm.dimensions, + initialPanels = vm.panels, + unitToColor = model.unitToColor, + context = d.context, + pick = d.pick; var renderState = { currentRafs: {}, @@ -189,13 +200,7 @@ module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDim var points = makePoints(sampleCount, dimensionCount, initialDims, color); var attributes = makeAttributes(sampleCount, points); - var regl = createREGL({ - canvas: canvasGL, - attributes: { - preserveDrawingBuffer: true, - antialias: !pick - } - }); + var regl = d.regl; var paletteTexture = regl.texture({ shape: [256, 1], @@ -248,6 +253,13 @@ module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDim } }, + viewport: { + x: regl.prop('viewportX'), + y: regl.prop('viewportY'), + width: regl.prop('viewportWidth'), + height: regl.prop('viewportHeight') + }, + dither: false, vert: pick ? pickVertexShaderSource : vertexShaderSource, @@ -297,7 +309,7 @@ module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDim function makeItem(i, ii, x, y, panelSizeX, canvasPanelSizeY, crossfilterDimensionIndex, scatter, I, leftmost, rightmost) { var loHi, abcd, d, index; var leftRight = [i, ii]; - var filterEpsilon = verticalPadding / canvasPanelSizeY; + var filterEpsilon = c.verticalPadding / canvasPanelSizeY; var dims = [0, 1].map(function() {return [0, 1, 2, 3].map(function() {return new Float32Array(16);});}); var lims = [0, 1].map(function() {return [0, 1, 2, 3].map(function() {return new Float32Array(16);});}); @@ -341,10 +353,15 @@ module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDim colorClamp: colorClamp, scatter: scatter || 0, - scissorX: I === leftmost ? 0 : x + overdrag, + scissorX: (I === leftmost ? 0 : x + overdrag) + (model.pad.l - overdrag) + model.layoutWidth * domain.x[0], scissorWidth: (I === rightmost ? canvasWidth - x + overdrag : panelSizeX + 0.5) + (I === leftmost ? x + overdrag : 0), - scissorY: y, - scissorHeight: canvasPanelSizeY + scissorY: y + model.pad.b + model.layoutHeight * domain.y[0], + scissorHeight: canvasPanelSizeY, + + viewportX: model.pad.l - overdrag + model.layoutWidth * domain.x[0], + viewportY: model.pad.b + model.layoutHeight * domain.y[0], + viewportWidth: canvasWidth, + viewportHeight: canvasHeight }; } @@ -413,11 +430,15 @@ module.exports = function(canvasGL, lines, canvasWidth, canvasHeight, initialDim return pixelArray; } + function destroy() { + paletteTexture.destroy(); + } + return { setColorDomain: setColorDomain, render: renderGLParcoords, readPixel: readPixel, readPixels: readPixels, - destroy: regl.destroy + destroy: destroy }; }; diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index 602d3ddf121..82ad148f704 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -161,6 +161,9 @@ function model(layout, d, i) { labelFont: labelFont, tickFont: tickFont, rangeFont: rangeFont, + layoutWidth: width, + layoutHeight: layout.height, + domain: domain, translateX: domain.x[0] * width, translateY: layout.height - domain.y[1] * layout.height, pad: pad, @@ -228,18 +231,6 @@ function viewModel(model) { return viewModel; } -function lineLayerModel(vm) { - return c.layers.map(function(key) { - return { - key: key, - context: key === 'contextLineLayer', - pick: key === 'pickLineLayer', - viewModel: vm, - model: vm.model - }; - }); -} - function styleExtentTexts(selection) { selection .classed(c.cn.axisExtentText, true) @@ -248,8 +239,7 @@ function styleExtentTexts(selection) { .style('user-select', 'none'); } -module.exports = function(root, svg, styledData, layout, callbacks) { - +module.exports = function(root, svg, parcoordsLineLayers, styledData, layout, callbacks) { var domainBrushing = false; var linePickActive = true; @@ -296,37 +286,22 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .map(model.bind(0, layout)) .map(viewModel); - root.selectAll('.' + c.cn.parcoordsLineLayers).remove(); - - var parcoordsLineLayers = root.selectAll('.' + c.cn.parcoordsLineLayers) - .data(vm, keyFun); - - parcoordsLineLayers.enter() - .insert('div', '.' + svg.attr('class').split(' ').join(' .')) // not hardcoding .main-svg - .classed(c.cn.parcoordsLineLayers, true) - .style('box-sizing', 'content-box'); + parcoordsLineLayers.each(function(d, i) { + return Lib.extendFlat(d, vm[i]); + }); - parcoordsLineLayers - .style('transform', function(d) { - return 'translate(' + (d.model.translateX - c.overdrag) + 'px,' + d.model.translateY + 'px)'; + var parcoordsLineLayer = parcoordsLineLayers.selectAll('.gl-canvas') + .each(function(d) { + // FIXME: figure out how to handle multiple instances + d.viewModel = vm[0]; + d.model = vm[0].model; }); - var parcoordsLineLayer = parcoordsLineLayers.selectAll('.' + c.cn.parcoordsLineLayer) - .data(lineLayerModel, keyFun); - var tweakables = {renderers: [], dimensions: []}; var lastHovered = null; - parcoordsLineLayer.enter() - .append('canvas') - .attr('class', function(d) {return c.cn.parcoordsLineLayer + ' ' + (d.context ? 'context' : d.pick ? 'pick' : 'focus');}) - .style('box-sizing', 'content-box') - .style('float', 'left') - .style('clear', 'both') - .style('left', 0) - .style('overflow', 'visible') - .style('position', 'absolute') + parcoordsLineLayer .filter(function(d) {return d.pick;}) .on('mousemove', function(d) { if(linePickActive && d.lineLayer && callbacks && callbacks.hover) { @@ -364,14 +339,6 @@ module.exports = function(root, svg, styledData, layout, callbacks) { }); parcoordsLineLayer - .style('margin', function(d) { - var p = d.model.pad; - return p.t + 'px ' + p.r + 'px ' + p.b + 'px ' + p.l + 'px'; - }) - .attr('width', function(d) {return d.model.canvasWidth;}) - .attr('height', function(d) {return d.model.canvasHeight;}) - .style('width', function(d) {return (d.model.width + 2 * c.overdrag) + 'px';}) - .style('height', function(d) {return d.model.height + 'px';}) .style('opacity', function(d) {return d.pick ? 0.01 : 1;}); svg.style('background', 'rgba(255, 255, 255, 0)'); @@ -474,7 +441,7 @@ module.exports = function(root, svg, styledData, layout, callbacks) { parcoordsLineLayer .each(function(d) { - d.lineLayer = lineLayerMaker(this, d.model.lines, d.model.canvasWidth, d.model.canvasHeight, d.viewModel.dimensions, d.viewModel.panels, d.model.unitToColor, d.context, d.pick, c.scatter); + d.lineLayer = lineLayerMaker(this, d, c.scatter); d.viewModel[d.key] = d.lineLayer; tweakables.renderers.push(function() {d.lineLayer.render(d.viewModel.panels, true);}); d.lineLayer.render(d.viewModel.panels, !d.context); @@ -508,8 +475,8 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .attr('transform', function(d) {return 'translate(' + d.xScale(d.xIndex) + ', 0)';}); d3.select(this).attr('transform', 'translate(' + d.x + ', 0)'); yAxis.each(function(dd, i, ii) {if(ii === d.parent.key) p.dimensions[i] = dd;}); - p.contextLineLayer && p.contextLineLayer.render(p.panels, false, !someFiltersActive(p)); - p.focusLineLayer.render && p.focusLineLayer.render(p.panels); + p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p)); + p.focusLayer.render && p.focusLayer.render(p.panels); }) .on('dragend', function(d) { var p = d.parent; @@ -524,9 +491,9 @@ module.exports = function(root, svg, styledData, layout, callbacks) { updatePanelLayout(yAxis, p); d3.select(this) .attr('transform', function(d) {return 'translate(' + d.x + ', 0)';}); - p.contextLineLayer && p.contextLineLayer.render(p.panels, false, !someFiltersActive(p)); - p.focusLineLayer && p.focusLineLayer.render(p.panels); - p.pickLineLayer && p.pickLineLayer.render(p.panels, true); + p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p)); + p.focusLayer && p.focusLayer.render(p.panels); + p.pickLayer && p.pickLayer.render(p.panels, true); linePickActive = true; if(callbacks && callbacks.axesMoved) { @@ -737,13 +704,13 @@ module.exports = function(root, svg, styledData, layout, callbacks) { var newExtent = reset ? [0, 1] : extent.slice(); if(newExtent[0] !== filter[0] || newExtent[1] !== filter[1]) { dimensions[dimension.xIndex].filter = newExtent; - p.focusLineLayer && p.focusLineLayer.render(p.panels, true); + p.focusLayer && p.focusLayer.render(p.panels, true); var filtersActive = someFiltersActive(p); if(!contextShown && filtersActive) { - p.contextLineLayer && p.contextLineLayer.render(p.panels, true); + p.contextLayer && p.contextLayer.render(p.panels, true); contextShown = true; } else if(contextShown && !filtersActive) { - p.contextLineLayer && p.contextLineLayer.render(p.panels, true, true); + p.contextLayer && p.contextLayer.render(p.panels, true, true); contextShown = false; } } @@ -764,9 +731,9 @@ module.exports = function(root, svg, styledData, layout, callbacks) { f[1] = Math.min(1, f[1] + 0.05); } d3.select(this).transition().duration(150).call(dimension.brush.extent(f)); - p.focusLineLayer.render(p.panels, true); + p.focusLayer.render(p.panels, true); } - p.pickLineLayer && p.pickLineLayer.render(p.panels, true); + p.pickLayer && p.pickLayer.render(p.panels, true); linePickActive = true; domainBrushing = 'ending'; if(callbacks && callbacks.filterChanged) { diff --git a/src/traces/parcoords/plot.js b/src/traces/parcoords/plot.js index 90cc3353846..8abee427202 100644 --- a/src/traces/parcoords/plot.js +++ b/src/traces/parcoords/plot.js @@ -13,8 +13,9 @@ var parcoords = require('./parcoords'); module.exports = function plot(gd, cdparcoords) { var fullLayout = gd._fullLayout; - var svg = fullLayout._paper; + var svg = fullLayout._toppaper; var root = fullLayout._paperdiv; + var container = fullLayout._glcontainer; var gdDimensions = {}; var gdDimensionsOriginalOrder = {}; @@ -98,6 +99,7 @@ module.exports = function plot(gd, cdparcoords) { parcoords( root, svg, + container, cdparcoords, { width: size.w, diff --git a/src/traces/pointcloud/index.js b/src/traces/pointcloud/index.js index b5cef7bdd2c..dd710caafad 100644 --- a/src/traces/pointcloud/index.js +++ b/src/traces/pointcloud/index.js @@ -20,7 +20,7 @@ pointcloud.plot = require('./convert'); pointcloud.moduleType = 'trace'; pointcloud.name = 'pointcloud'; pointcloud.basePlotModule = require('../../plots/gl2d'); -pointcloud.categories = ['gl2d', 'showLegend']; +pointcloud.categories = ['gl', 'gl2d', 'showLegend']; pointcloud.meta = { description: [ 'The data visualized as a point cloud set in `x` and `y`', diff --git a/src/traces/scattergl/index.js b/src/traces/scattergl/index.js index 35d292f1c90..6ad0666d16a 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', 'scatter-like']; +ScatterGl.categories = ['gl', '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/test/image/baselines/gl2d_parcoords_2.png b/test/image/baselines/gl2d_parcoords_2.png index 2b19d3c107f9cb935cd88f5570d0ed84c5ba1c33..91d01c98f600993ce93b564bfb91672d85871f18 100644 GIT binary patch literal 29852 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 DdOSk} literal 37023 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 T$TsT(@J~TTRk{LV7V^IUZU~0z From f711cf1d9bb99614b1c7de5a68a5bdc8637dbb75 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 14 Nov 2017 16:16:09 -0500 Subject: [PATCH 02/12] Fix canvas counts --- test/jasmine/tests/gl_plot_interact_test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jasmine/tests/gl_plot_interact_test.js b/test/jasmine/tests/gl_plot_interact_test.js index 8d2cf6a11c3..bb316537f83 100644 --- a/test/jasmine/tests/gl_plot_interact_test.js +++ b/test/jasmine/tests/gl_plot_interact_test.js @@ -1290,7 +1290,7 @@ describe('Test gl plot side effects', function() { return Plotly.plot(gd, data); }).then(function() { - countCanvases(1); + countCanvases(3); return Plotly.purge(gd); }).then(function() { @@ -1298,11 +1298,11 @@ describe('Test gl plot side effects', function() { return Plotly.plot(gd, data); }).then(function() { - countCanvases(1); + countCanvases(3); return Plotly.deleteTraces(gd, [0]); }).then(function() { - countCanvases(0); + countCanvases(3); return Plotly.purge(gd); }).then(done); From 0838c31c42345b4709c96c5d25bff5b66016acbe Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 15 Nov 2017 16:40:34 -0500 Subject: [PATCH 03/12] Scope regl creation by trace --- src/plot_api/plot_api.js | 13 ------------- src/traces/parcoords/plot.js | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index feccc268771..2bce2e4020f 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -42,8 +42,6 @@ var enforceAxisConstraints = axisConstraints.enforce; var cleanAxisConstraints = axisConstraints.clean; var axisIds = require('../plots/cartesian/axis_ids'); -var createRegl = require('regl'); - /** * Main plot-creation function @@ -213,17 +211,6 @@ Plotly.plot = function(gd, data, layout, config) { }]); fullLayout._glcanvas.enter().append('canvas') - .each(function(d) { - d.regl = createRegl({ - canvas: this, - attributes: { - antialias: !d.pick, - preserveDrawingBuffer: true - }, - extensions: ['ANGLE_instanced_arrays', 'OES_element_index_uint'], - pixelRatio: gd._context.plotGlPixelRatio || global.devicePixelRatio - }); - }) .attr('class', function(d) { return 'gl-canvas gl-canvas-' + d.key.replace('Layer', ''); }) diff --git a/src/traces/parcoords/plot.js b/src/traces/parcoords/plot.js index 8abee427202..433938ec1b9 100644 --- a/src/traces/parcoords/plot.js +++ b/src/traces/parcoords/plot.js @@ -9,6 +9,7 @@ 'use strict'; var parcoords = require('./parcoords'); +var createRegl = require('regl'); module.exports = function plot(gd, cdparcoords) { @@ -17,6 +18,19 @@ module.exports = function plot(gd, cdparcoords) { var root = fullLayout._paperdiv; var container = fullLayout._glcontainer; + // make sure proper regl instances are created + fullLayout._glcanvas.each(function(d) { + if(d.regl) return; + d.regl = createRegl({ + canvas: this, + attributes: { + antialias: !d.pick, + preserveDrawingBuffer: true + }, + pixelRatio: gd._context.plotGlPixelRatio || global.devicePixelRatio + }); + }); + var gdDimensions = {}; var gdDimensionsOriginalOrder = {}; From 348e170b1f1c3947db9b50ffa33bfae7758eae63 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 15 Nov 2017 17:16:35 -0500 Subject: [PATCH 04/12] Fix interaction/image tests --- src/plots/cartesian/dragbox.js | 8 +++++--- src/plots/cartesian/index.js | 8 +++++--- test/image/baselines/gl2d_parcoords_2.png | Bin 29852 -> 29860 bytes 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index c895bbd8e48..3397af1ecce 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -715,9 +715,11 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) { // FIXME: code duplication with cartesian.plot if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { fullLayout._glcanvas.each(function(d) { - d.regl.clear({ - color: true - }); + if (d.regl) { + d.regl.clear({ + color: true + }); + } }); } diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 428cb89e25c..e2926961b37 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -51,9 +51,11 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { // clear gl frame, if any, since we preserve drawing buffer if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { fullLayout._glcanvas.each(function(d) { - d.regl.clear({ - color: true - }); + if (d.regl) { + d.regl.clear({ + color: true + }); + } }); } diff --git a/test/image/baselines/gl2d_parcoords_2.png b/test/image/baselines/gl2d_parcoords_2.png index 91d01c98f600993ce93b564bfb91672d85871f18..a31ada489358a3bcfbf4eea7ecb1ddf9a7b20b7d 100644 GIT binary patch literal 29860 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 DdOSk} From 07ea3842b320345cbddd60177e83ba5d01100b99 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 15 Nov 2017 17:49:49 -0500 Subject: [PATCH 05/12] Lintify --- src/plots/cartesian/dragbox.js | 2 +- src/plots/cartesian/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 3397af1ecce..ea379190b0d 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -715,7 +715,7 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) { // FIXME: code duplication with cartesian.plot if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { fullLayout._glcanvas.each(function(d) { - if (d.regl) { + if(d.regl) { d.regl.clear({ color: true }); diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index e2926961b37..a9db08dd172 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -51,7 +51,7 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { // clear gl frame, if any, since we preserve drawing buffer if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { fullLayout._glcanvas.each(function(d) { - if (d.regl) { + if(d.regl) { d.regl.clear({ color: true }); From 1517ece6d40e95d262768a784f85faab8a4d2acf Mon Sep 17 00:00:00 2001 From: Dmitry Date: Thu, 16 Nov 2017 13:57:15 -0500 Subject: [PATCH 06/12] Remove data obj --- src/plot_api/plot_api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 2bce2e4020f..10cf5fdbe9d 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -2788,7 +2788,7 @@ function makePlotFramework(gd) { .classed('plotly', true); // Make the svg container - fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([{}]); + fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([0]); fullLayout._paperdiv.enter().append('div') .classed('svg-container', true) .style('position', 'relative'); From 384b5772278083aa3aa4ca63f798144a4df3a4b9 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 22 Nov 2017 20:21:28 -0500 Subject: [PATCH 07/12] Recycle global canvases properly --- src/plot_api/helpers.js | 1 + src/plot_api/plot_api.js | 4 +--- src/plots/plots.js | 16 ++++++++++++- src/traces/parcoords/parcoords.js | 2 +- test/jasmine/tests/gl_plot_interact_test.js | 26 ++++++++++++++++++++- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/plot_api/helpers.js b/src/plot_api/helpers.js index e27eff1cb9b..66baee79534 100644 --- a/src/plot_api/helpers.js +++ b/src/plot_api/helpers.js @@ -154,6 +154,7 @@ exports.cleanLayout = function(layout) { // clean old Camera coords var cameraposition = scene.cameraposition; + if(Array.isArray(cameraposition) && cameraposition[0].length === 4) { var rotation = cameraposition[0], center = cameraposition[1], diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 10cf5fdbe9d..d3a9a0c7edf 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -208,7 +208,7 @@ Plotly.plot = function(gd, data, layout, config) { key: 'pickLayer', context: false, pick: true - }]); + }], function(d) { return d.key; }); fullLayout._glcanvas.enter().append('canvas') .attr('class', function(d) { @@ -225,8 +225,6 @@ Plotly.plot = function(gd, data, layout, config) { }) .attr('width', fullLayout.width) .attr('height', fullLayout.height); - - fullLayout._glcanvas.exit().remove(); } return Lib.syncOrAsync([ diff --git a/src/plots/plots.js b/src/plots/plots.js index 1eaa4bfef01..04a63ac4cb3 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -609,6 +609,16 @@ plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayou var hasPaper = !!oldFullLayout._paper; var hasInfoLayer = !!oldFullLayout._infolayer; + var hadGl = oldFullLayout._has && oldFullLayout._has('gl'); + var hasGl = newFullLayout._has && newFullLayout._has('gl'); + + if(hadGl && !hasGl) { + if(oldFullLayout._glcontainer !== undefined) { + oldFullLayout._glcontainer.selectAll('.gl-canvas').data([]).exit().remove(); + oldFullLayout._glcontainer.remove(); + oldFullLayout._glcanvas = null; + } + } oldLoop: for(i = 0; i < oldFullData.length; i++) { @@ -1322,7 +1332,11 @@ plots.purge = function(gd) { // a new plot, and may have been set outside of our scope. var fullLayout = gd._fullLayout || {}; - if(fullLayout._glcontainer !== undefined) fullLayout._glcontainer.remove(); + if(fullLayout._glcontainer !== undefined) { + fullLayout._glcontainer.selectAll('.gl-canvas').data([]).exit().remove(); + fullLayout._glcontainer.remove(); + fullLayout._glcanvas = null; + } if(fullLayout._geocontainer !== undefined) fullLayout._geocontainer.remove(); // remove modebar diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index 82ad148f704..b3c9338006f 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -294,7 +294,7 @@ module.exports = function(root, svg, parcoordsLineLayers, styledData, layout, ca .each(function(d) { // FIXME: figure out how to handle multiple instances d.viewModel = vm[0]; - d.model = vm[0].model; + d.model = d.viewModel ? d.viewModel.model : null; }); var tweakables = {renderers: [], dimensions: []}; diff --git a/test/jasmine/tests/gl_plot_interact_test.js b/test/jasmine/tests/gl_plot_interact_test.js index bb316537f83..f52f2d80485 100644 --- a/test/jasmine/tests/gl_plot_interact_test.js +++ b/test/jasmine/tests/gl_plot_interact_test.js @@ -1302,11 +1302,35 @@ describe('Test gl plot side effects', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - countCanvases(3); + countCanvases(0); return Plotly.purge(gd); }).then(done); }); + + it('should be able to switch trace type', function(done) { + Plotly.newPlot(gd, [{ + type: 'parcoords', + x: [1, 2, 3], + y: [2, 1, 2], + dimensions: [ + { + constraintrange: [200, 700], + label: 'Block height', + values: [321, 534, 542, 674, 31, 674, 124, 246, 456, 743] + } + ] + }]) + .then(function() { + expect(d3.selectAll('canvas').size()).toEqual(3); + + return Plotly.restyle(gd, 'type', 'scatter'); + }) + .then(function() { + expect(d3.selectAll('canvas').size()).toEqual(0); + }) + .then(done); + }); }); describe('Test gl2d interactions', function() { From 8346ce409f47d70c1e94600669f6dd154b39db94 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 22 Nov 2017 21:24:43 -0500 Subject: [PATCH 08/12] Fix container test --- src/plots/plots.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index 04a63ac4cb3..b1803416af3 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -615,7 +615,6 @@ plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayou if(hadGl && !hasGl) { if(oldFullLayout._glcontainer !== undefined) { oldFullLayout._glcontainer.selectAll('.gl-canvas').data([]).exit().remove(); - oldFullLayout._glcontainer.remove(); oldFullLayout._glcanvas = null; } } From b8b89511e496f5083518b2aa785320af6b1b8ca6 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 24 Nov 2017 14:03:54 -0500 Subject: [PATCH 09/12] Simplify canvas removal --- src/plots/plots.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index b1803416af3..4fc9200d599 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -614,7 +614,7 @@ plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayou if(hadGl && !hasGl) { if(oldFullLayout._glcontainer !== undefined) { - oldFullLayout._glcontainer.selectAll('.gl-canvas').data([]).exit().remove(); + oldFullLayout._glcontainer.selectAll('.gl-canvas').remove(); oldFullLayout._glcanvas = null; } } From 4efe21ea79a970256bfac237c7d0d2d344395916 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 24 Nov 2017 17:10:41 -0500 Subject: [PATCH 10/12] Minor fixes --- src/plot_api/plot_api.js | 1 + src/plots/plots.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index d3a9a0c7edf..6b684ce7df0 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -2796,6 +2796,7 @@ function makePlotFramework(gd) { // right, rather than enter/exit which can muck up the order // TODO: sort out all the ordering so we don't have to // explicitly delete anything + // FIXME: parcoords reuses this object, not the best pattern fullLayout._glcontainer = fullLayout._paperdiv.selectAll('.gl-container') .data([{}]); fullLayout._glcontainer.enter().append('div') diff --git a/src/plots/plots.js b/src/plots/plots.js index 4fc9200d599..5d0515a0a42 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1332,7 +1332,7 @@ plots.purge = function(gd) { var fullLayout = gd._fullLayout || {}; if(fullLayout._glcontainer !== undefined) { - fullLayout._glcontainer.selectAll('.gl-canvas').data([]).exit().remove(); + fullLayout._glcontainer.selectAll('.gl-canvas').remove(); fullLayout._glcontainer.remove(); fullLayout._glcanvas = null; } From 83b7589f7be93ba1a52ac9394af711cee9b34763 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 24 Nov 2017 18:51:31 -0500 Subject: [PATCH 11/12] Fix parcoords tests --- src/plot_api/plot_api.js | 1 - src/traces/parcoords/lines.js | 2 +- src/traces/parcoords/parcoords.js | 5 ++++- test/jasmine/tests/parcoords_test.js | 25 ++++++++++++------------- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 6b684ce7df0..74079012bae 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -220,7 +220,6 @@ Plotly.plot = function(gd, data, layout, config) { 'left': 0, 'width': '100%', 'height': '100%', - 'pointer-events': 'none', 'overflow': 'visible' }) .attr('width', fullLayout.width) diff --git a/src/traces/parcoords/lines.js b/src/traces/parcoords/lines.js index 7e20a6b65d4..b63b14b13f8 100644 --- a/src/traces/parcoords/lines.js +++ b/src/traces/parcoords/lines.js @@ -164,7 +164,7 @@ function valid(i, offset, panelCount) { return i + offset <= panelCount; } -module.exports = module.exports = function(canvasGL, d, scatter) { +module.exports = function(canvasGL, d, scatter) { var model = d.model, vm = d.viewModel, domain = model.domain; diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index b3c9338006f..96b83392650 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -302,7 +302,9 @@ module.exports = function(root, svg, parcoordsLineLayers, styledData, layout, ca var lastHovered = null; parcoordsLineLayer - .filter(function(d) {return d.pick;}) + .filter(function(d) { + return d.pick; + }) .on('mousemove', function(d) { if(linePickActive && d.lineLayer && callbacks && callbacks.hover) { var event = d3.event; @@ -440,6 +442,7 @@ module.exports = function(root, svg, parcoordsLineLayers, styledData, layout, ca }); parcoordsLineLayer + .filter(function(d) {return !!d.viewModel;}) .each(function(d) { d.lineLayer = lineLayerMaker(this, d, c.scatter); d.viewModel[d.key] = d.lineLayer; diff --git a/test/jasmine/tests/parcoords_test.js b/test/jasmine/tests/parcoords_test.js index 66efc5b3df0..a632a4d21d2 100644 --- a/test/jasmine/tests/parcoords_test.js +++ b/test/jasmine/tests/parcoords_test.js @@ -788,7 +788,7 @@ describe('@noCI parcoords', function() { expect(gd.data.length).toEqual(1); Plotly.deleteTraces(gd, 0).then(function() { - expect(d3.selectAll('.parcoords-line-layers').node()).toEqual(null); + expect(d3.selectAll('.gl-canvas').node(0)).toEqual(null); expect(gd.data.length).toEqual(0); done(); }); @@ -815,13 +815,13 @@ describe('@noCI parcoords', function() { return Plotly.deleteTraces(gd, [0]); }) .then(function() { - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(1); + expect(document.querySelectorAll('.gl-canvas').length).toEqual(3); expect(document.querySelectorAll('.y-axis').length).toEqual(7); expect(gd.data.length).toEqual(1); return Plotly.deleteTraces(gd, 0); }) .then(function() { - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(0); + expect(document.querySelectorAll('.gl-canvas').length).toEqual(0); expect(document.querySelectorAll('.y-axis').length).toEqual(0); expect(gd.data.length).toEqual(0); done(); @@ -869,13 +869,13 @@ describe('@noCI parcoords', function() { mockCopy2.data[0].domain = {x: [0.55, 1]}; mockCopy2.data[0].dimensions.splice(3, 4); - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(0); + expect(document.querySelectorAll('.gl-container').length).toEqual(0); Plotly.plot(gd, mockCopy) .then(function() { expect(1).toEqual(1); - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(1); + expect(document.querySelectorAll('.gl-container').length).toEqual(1); expect(gd.data.length).toEqual(1); return Plotly.plot(gd, mockCopy2); @@ -883,7 +883,7 @@ describe('@noCI parcoords', function() { .then(function() { expect(1).toEqual(1); - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(2); + expect(document.querySelectorAll('.gl-container').length).toEqual(1); expect(gd.data.length).toEqual(2); done(); @@ -899,19 +899,18 @@ describe('@noCI parcoords', function() { mockCopy2.data[0].domain = {y: [0.65, 1]}; mockCopy2.data[0].dimensions.splice(3, 4); - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(0); + expect(document.querySelectorAll('.gl-container').length).toEqual(0); Plotly.plot(gd, mockCopy) .then(function() { - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(1); + expect(document.querySelectorAll('.gl-container').length).toEqual(1); expect(gd.data.length).toEqual(1); return Plotly.addTraces(gd, [mockCopy2.data[0]]); }) .then(function() { - - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(2); + expect(document.querySelectorAll('.gl-container').length).toEqual(1); expect(gd.data.length).toEqual(2); done(); @@ -945,12 +944,12 @@ describe('@noCI parcoords', function() { mockCopy2.data[0].dimensions[2].tickvals = [0, 1, 2, 2.5, 3]; mockCopy2.data[0].dimensions[2].values = mockCopy2.data[0].dimensions[2].values.map(numberUpdater); - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(0); + expect(document.querySelectorAll('.gl-container').length).toEqual(0); Plotly.plot(gd, mockCopy) .then(function() { - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(1); + expect(document.querySelectorAll('.gl-container').length).toEqual(1); expect(gd.data.length).toEqual(1); return Plotly.restyle(gd, { @@ -960,7 +959,7 @@ describe('@noCI parcoords', function() { }) .then(function() { - expect(document.querySelectorAll('.parcoords-line-layers').length).toEqual(1); + expect(document.querySelectorAll('.gl-container').length).toEqual(1); expect(gd.data.length).toEqual(1); done(); From de9b1aa21cbf72d0022dae427ea93b8dbd2f32fe Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 27 Nov 2017 18:55:00 -0500 Subject: [PATCH 12/12] Fix noCI tests --- src/plot_api/plot_api.js | 6 ++++++ src/plots/cartesian/select.js | 1 - src/plots/gl2d/scene2d.js | 5 +++++ test/jasmine/tests/gl2d_click_test.js | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 74079012bae..205994bf1a6 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -224,6 +224,12 @@ Plotly.plot = function(gd, data, layout, config) { }) .attr('width', fullLayout.width) .attr('height', fullLayout.height); + + fullLayout._glcanvas.filter(function(d) { + return !d.pick; + }).style({ + 'pointer-events': 'none' + }); } return Lib.syncOrAsync([ diff --git a/src/plots/cartesian/select.js b/src/plots/cartesian/select.js index be7226e5590..e1429f6e911 100644 --- a/src/plots/cartesian/select.js +++ b/src/plots/cartesian/select.js @@ -262,7 +262,6 @@ module.exports = function prepSelect(e, startX, startY, dragOptions, mode) { throttle.done(throttleID).then(function() { throttle.clear(throttleID); - if(!dragged && numclicks === 2) { // clear selection on doubleclick outlines.remove(); diff --git a/src/plots/gl2d/scene2d.js b/src/plots/gl2d/scene2d.js index 0a190078452..2d8b3a74ffb 100644 --- a/src/plots/gl2d/scene2d.js +++ b/src/plots/gl2d/scene2d.js @@ -157,6 +157,9 @@ proto.makeFramework = function() { mouseContainer.style.position = 'absolute'; mouseContainer.style['pointer-events'] = 'auto'; + this.pickCanvas = this.container.querySelector('.gl-canvas-pick'); + + // append canvas, hover svg and mouse div to container var container = this.container; container.appendChild(svgContainer); @@ -531,8 +534,10 @@ proto.updateTraces = function(fullData, calcData) { proto.updateFx = function(dragmode) { // switch to svg interactions in lasso/select mode if(dragmode === 'lasso' || dragmode === 'select') { + this.pickCanvas.style['pointer-events'] = 'none'; this.mouseContainer.style['pointer-events'] = 'none'; } else { + this.pickCanvas.style['pointer-events'] = 'auto'; this.mouseContainer.style['pointer-events'] = 'auto'; } diff --git a/test/jasmine/tests/gl2d_click_test.js b/test/jasmine/tests/gl2d_click_test.js index 54dd23ee1aa..70609851a15 100644 --- a/test/jasmine/tests/gl2d_click_test.js +++ b/test/jasmine/tests/gl2d_click_test.js @@ -491,7 +491,7 @@ describe('@noCI Test gl2d lasso/select:', function() { function select(path) { return new Promise(function(resolve, reject) { gd.once('plotly_selected', resolve); - setTimeout(function() { reject('did not trigger *plotly_selected*');}, 100); + setTimeout(function() { reject('did not trigger *plotly_selected*');}, 200); drag(path); }); }