Skip to content

Commit

Permalink
Merge pull request #1831 from plotly/fix-scatterternary-lasso
Browse files Browse the repository at this point in the history
Fix scatterternary lasso/select drag modes
  • Loading branch information
etpinard committed Jun 28, 2017
2 parents d47ace6 + 5a48568 commit 70de159
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 39 deletions.
6 changes: 3 additions & 3 deletions src/plots/cartesian/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var MINSELECT = constants.MINSELECT;
function getAxId(ax) { return ax._id; }

module.exports = function prepSelect(e, startX, startY, dragOptions, mode) {
var plot = dragOptions.gd._fullLayout._zoomlayer,
var zoomLayer = dragOptions.gd._fullLayout._zoomlayer,
dragBBox = dragOptions.element.getBoundingClientRect(),
xs = dragOptions.plotinfo.xaxis._offset,
ys = dragOptions.plotinfo.yaxis._offset,
Expand All @@ -43,15 +43,15 @@ module.exports = function prepSelect(e, startX, startY, dragOptions, mode) {
pts = filteredPolygon([[x0, y0]], constants.BENDPX);
}

var outlines = plot.selectAll('path.select-outline').data([1, 2]);
var outlines = zoomLayer.selectAll('path.select-outline').data([1, 2]);

outlines.enter()
.append('path')
.attr('class', function(d) { return 'select-outline select-outline-' + d; })
.attr('transform', 'translate(' + xs + ', ' + ys + ')')
.attr('d', path0 + 'Z');

var corners = plot.append('path')
var corners = zoomLayer.append('path')
.attr('class', 'zoombox-corners')
.style({
fill: color.background,
Expand Down
4 changes: 4 additions & 0 deletions src/plots/ternary/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,8 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
oldTernary.clipDef.remove();
}
}

if(oldFullLayout._zoomlayer) {
oldFullLayout._zoomlayer.selectAll('.select-outline').remove();
}
};
22 changes: 13 additions & 9 deletions src/plots/ternary/ternary.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ proto.makeFramework = function() {
'backplot',
'grids',
'frontplot',
'zoom',
'aaxis', 'baxis', 'caxis', 'axlines'
];
var toplevel = _this.plotContainer.selectAll('g.toplevel')
Expand Down Expand Up @@ -123,10 +122,6 @@ proto.makeFramework = function() {

_this.plotContainer.selectAll('.backplot,.frontplot,.grids')
.call(Drawing.setClipUrl, clipId);

if(!_this.graphDiv._context.staticPlot) {
_this.initInteractions();
}
};

var w_over_h = Math.sqrt(4 / 3);
Expand Down Expand Up @@ -263,7 +258,7 @@ proto.adjustLayout = function(ternaryLayout, graphSize) {
_this.layers.plotbg.select('path').attr('d', triangleClip);

var plotTransform = 'translate(' + x0 + ',' + y0 + ')';
_this.plotContainer.selectAll('.scatterlayer,.maplayer,.zoom')
_this.plotContainer.selectAll('.scatterlayer,.maplayer')
.attr('transform', plotTransform);

// TODO: shift axes to accommodate linewidth*sin(30) tick mark angle
Expand Down Expand Up @@ -303,6 +298,10 @@ proto.adjustLayout = function(ternaryLayout, graphSize) {
'M' + (x0 + w / 2) + ',' + y0 + 'l' + (w / 2) + ',' + h : 'M0,0')
.call(Color.stroke, caxis.linecolor || '#000')
.style('stroke-width', (caxis.linewidth || 0) + 'px');

if(!_this.graphDiv._context.staticPlot) {
_this.initInteractions();
}
};

proto.drawAxes = function(doTitles) {
Expand Down Expand Up @@ -382,13 +381,16 @@ proto.initInteractions = function() {
var _this = this,
dragger = _this.layers.plotbg.select('path').node(),
gd = _this.graphDiv,
zoomContainer = _this.layers.zoom;
zoomContainer = gd._fullLayout._zoomlayer;

// use plotbg for the main interactions
var dragOptions = {
element: dragger,
gd: gd,
plotinfo: {plot: zoomContainer},
plotinfo: {
xaxis: _this.xaxis,
yaxis: _this.yaxis
},
doubleclick: doubleClick,
subplot: _this.id,
prepFn: function(e, startX, startY) {
Expand Down Expand Up @@ -441,6 +443,7 @@ proto.initInteractions = function() {

zb = zoomContainer.append('path')
.attr('class', 'zoombox')
.attr('transform', 'translate(' + _this.x0 + ', ' + _this.y0 + ')')
.style({
'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)',
'stroke-width': 0
Expand All @@ -449,6 +452,7 @@ proto.initInteractions = function() {

corners = zoomContainer.append('path')
.attr('class', 'zoombox-corners')
.attr('transform', 'translate(' + _this.x0 + ', ' + _this.y0 + ')')
.style({
fill: Color.background,
stroke: Color.defaultLine,
Expand Down Expand Up @@ -603,7 +607,7 @@ proto.initInteractions = function() {
// until we get around to persistent selections, remove the outline
// here. The selection itself will be removed when the plot redraws
// at the end.
_this.plotContainer.selectAll('.select-outline').remove();
zoomContainer.selectAll('.select-outline').remove();
}

function doubleClick() {
Expand Down
135 changes: 108 additions & 27 deletions test/jasmine/tests/select_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var doubleClick = require('../assets/double_click');

var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
var fail = require('../assets/fail_test');
var mouseEvent = require('../assets/mouse_event');
var customMatchers = require('../assets/custom_matchers');

Expand All @@ -16,7 +17,7 @@ describe('select box and lasso', function() {
var selectPath = [[93, 193], [143, 193]];
var lassoPath = [[316, 171], [318, 239], [335, 243], [328, 169]];

beforeEach(function() {
beforeAll(function() {
jasmine.addMatchers(customMatchers);
});

Expand Down Expand Up @@ -59,6 +60,13 @@ describe('select box and lasso', function() {
});
}

function assertSelectionNodes(cornerCnt, outlineCnt) {
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toBe(cornerCnt, 'selection corner count');
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toBe(outlineCnt, 'selection outline count');
}

describe('select elements', function() {
var mockCopy = Lib.extendDeep({}, mock);
mockCopy.layout.dragmode = 'select';
Expand All @@ -80,30 +88,21 @@ describe('select box and lasso', function() {
y2 = 50;

gd.once('plotly_selecting', function() {
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toEqual(1);
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toEqual(2);
assertSelectionNodes(1, 2);
});

gd.once('plotly_selected', function() {
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toEqual(0);
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toEqual(2);
assertSelectionNodes(0, 2);
});

gd.once('plotly_deselect', function() {
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toEqual(0);
assertSelectionNodes(0, 0);
});

mouseEvent('mousemove', x0, y0);
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toEqual(0);
assertSelectionNodes(0, 0);

drag([[x0, y0], [x1, y1]]);

doubleClick(x2, y2).then(done);
});
});
Expand All @@ -129,30 +128,21 @@ describe('select box and lasso', function() {
y2 = 50;

gd.once('plotly_selecting', function() {
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toEqual(1);
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toEqual(2);
assertSelectionNodes(1, 2);
});

gd.once('plotly_selected', function() {
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toEqual(0);
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toEqual(2);
assertSelectionNodes(0, 2);
});

gd.once('plotly_deselect', function() {
expect(d3.selectAll('.zoomlayer > .select-outline').size())
.toEqual(0);
assertSelectionNodes(0, 0);
});

mouseEvent('mousemove', x0, y0);
expect(d3.selectAll('.zoomlayer > .zoombox-corners').size())
.toEqual(0);
assertSelectionNodes(0, 0);

drag([[x0, y0], [x1, y1]]);

doubleClick(x2, y2).then(done);
});
});
Expand Down Expand Up @@ -379,4 +369,95 @@ describe('select box and lasso', function() {
})
.then(done);
});

it('should work on scatterternary traces', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/ternary_simple'));
var gd = createGraphDiv();
var pts = [];

fig.layout.width = 800;
fig.layout.dragmode = 'select';

function assertPoints(expected) {
expect(pts.length).toBe(expected.length, 'selected points length');

pts.forEach(function(p, i) {
var e = expected[i];
expect(p.a).toBe(e.a, 'selected pt a val');
expect(p.b).toBe(e.b, 'selected pt b val');
expect(p.c).toBe(e.c, 'selected pt c val');
});
pts = [];
}

Plotly.plot(gd, fig).then(function() {
gd.on('plotly_selected', function(data) {
pts = data.points;
});

assertSelectionNodes(0, 0);
drag([[400, 200], [445, 235]]);
assertSelectionNodes(0, 2);
assertPoints([{ a: 0.5, b: 0.25, c: 0.25 }]);

return Plotly.relayout(gd, 'dragmode', 'lasso');
})
.then(function() {
assertSelectionNodes(0, 0);
drag([[400, 200], [445, 200], [445, 235], [400, 235], [400, 200]]);
assertSelectionNodes(0, 2);
assertPoints([{ a: 0.5, b: 0.25, c: 0.25 }]);

// should work after a relayout too
return Plotly.relayout(gd, 'width', 400);
})
.then(function() {
assertSelectionNodes(0, 0);
drag([[200, 200], [230, 200], [230, 230], [200, 230], [200, 200]]);
assertSelectionNodes(0, 2);
assertPoints([{ a: 0.5, b: 0.25, c: 0.25 }]);
})
.catch(fail)
.then(done);
});

it('should work on scattercarpet traces', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/scattercarpet'));
var gd = createGraphDiv();
var pts = [];

fig.layout.dragmode = 'select';

function assertPoints(expected) {
expect(pts.length).toBe(expected.length, 'selected points length');

pts.forEach(function(p, i) {
var e = expected[i];
expect(p.a).toBe(e.a, 'selected pt a val');
expect(p.b).toBe(e.b, 'selected pt b val');
});
pts = [];
}

Plotly.plot(gd, fig).then(function() {
gd.on('plotly_selected', function(data) {
pts = data.points;
});

assertSelectionNodes(0, 0);
drag([[300, 200], [400, 250]]);
assertSelectionNodes(0, 2);
assertPoints([{ a: 0.2, b: 1.5 }]);

return Plotly.relayout(gd, 'dragmode', 'lasso');
})
.then(function() {
assertSelectionNodes(0, 0);
drag([[300, 200], [400, 200], [400, 250], [300, 250], [300, 200]]);
assertSelectionNodes(0, 2);
assertPoints([{ a: 0.2, b: 1.5 }]);
})
.catch(fail)
.then(done);
});
});

0 comments on commit 70de159

Please sign in to comment.