Skip to content

Commit 078c007

Browse files
committed
allow activation of editable shapes using opaque fill
1 parent 3e96a40 commit 078c007

File tree

3 files changed

+131
-18
lines changed

3 files changed

+131
-18
lines changed

src/components/shapes/draw.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function drawOne(gd, index) {
120120
var lineWidth = options.line.width;
121121
var lineDash = options.line.dash;
122122
if(!lineWidth && options.editable === true) {
123-
// ensure invisible border to active the shape
123+
// ensure invisible border to activate the shape
124124
lineWidth = 5;
125125
lineDash = 'solid';
126126
}
@@ -168,10 +168,10 @@ function drawOne(gd, index) {
168168
} else {
169169
if(gd._context.edits.shapePosition) {
170170
setupDragElement(gd, path, options, index, shapeLayer, editHelpers);
171-
} else {
172-
if(options.editable === true) {
173-
path.style('pointer-events', 'stroke');
174-
}
171+
} else if(options.editable === true) {
172+
path.style('pointer-events',
173+
(isOpen || Color.opacity(fillColor) * opacity <= 0.5) ? 'stroke' : 'all'
174+
);
175175
}
176176
}
177177

src/components/shapes/draw_newshape/attributes.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ module.exports = {
4444
dflt: 'rgba(0,0,0,0)',
4545
role: 'info',
4646
editType: 'none',
47-
description: 'Sets the color filling new shapes\' interior.'
47+
description: [
48+
'Sets the color filling new shapes\' interior.',
49+
'Please note that if using a fillcolor with alpha greater than half,',
50+
'drag inside the active shape starts moving the shape underneath,',
51+
'otherwise a new shape could be started over.'
52+
].join(' ')
4853
},
4954
fillrule: {
5055
valType: 'enumerated',
@@ -94,10 +99,6 @@ module.exports = {
9499
},
95100

96101
activeshape: {
97-
description: [
98-
'An \'editable`\' shape can be \'activated\' by clicking on its border line.'
99-
].join(' '),
100-
101102
fillcolor: {
102103
valType: 'color',
103104
dflt: 'rgb(255,0,255)',

test/jasmine/tests/draw_newshape_test.js

+120-8
Original file line numberDiff line numberDiff line change
@@ -1447,29 +1447,88 @@ describe('Activate and edit editable shapes', function() {
14471447
layout: {
14481448
shapes: [
14491449
{
1450+
editable: false,
14501451
x0: 1.5,
1452+
x1: 2,
1453+
y0: 1.5,
1454+
y1: 2,
1455+
opacity: 0.5,
1456+
fillcolor: 'blue',
1457+
line: {
1458+
width: 0,
1459+
dash: 'dash',
1460+
color: 'black'
1461+
}
1462+
}, {
1463+
editable: false,
1464+
x0: 2,
14511465
x1: 2.5,
14521466
y0: 1.5,
1467+
y1: 2,
1468+
opacity: 0.7,
1469+
fillcolor: 'rgba(255,0,0,0.7)', // N.B. 0.7 * 0.7 = 0.49 <= 0.5 is quite transparent
1470+
line: {
1471+
width: 0,
1472+
dash: 'dash',
1473+
color: 'black'
1474+
}
1475+
}, {
1476+
editable: false,
1477+
x0: 1.5,
1478+
x1: 2,
1479+
y0: 2,
14531480
y1: 2.5,
1454-
fillcolor: 'blue'
1481+
fillcolor: 'red',
1482+
line: {
1483+
width: 3,
1484+
dash: 'dash',
1485+
color: 'green'
1486+
}
1487+
}, {
1488+
editable: false,
1489+
path: 'M2,2H2.5,V2.5', // open path
1490+
fillcolor: 'rgba(0,0,0,0)',
1491+
line: {
1492+
width: 3,
1493+
dash: 'dash',
1494+
color: 'green'
1495+
}
14551496
}
14561497
]
14571498
}
14581499
})
14591500

14601501
.then(function() {
14611502
var el = Plotly.d3.selectAll('.shapelayer path')[0][0];
1462-
var pointerEvents = el.style['pointer-events'];
1463-
expect(pointerEvents).not.toBe('all');
1464-
expect(pointerEvents).not.toBe('stroke');
1465-
expect(pointerEvents).toBe('');
1503+
expect(el.style['pointer-events']).toBe('');
1504+
expect(el.style.stroke).toBe('rgb(0, 0, 0)'); // no color
1505+
expect(el.style['stroke-opacity']).toBe('0'); // invisible
1506+
expect(el.style['stroke-width']).toBe('0px'); // no pixel
1507+
1508+
el = Plotly.d3.selectAll('.shapelayer path')[0][1];
1509+
expect(el.style['pointer-events']).toBe('');
1510+
expect(el.style.stroke).toBe('rgb(0, 0, 0)'); // no color
1511+
expect(el.style['stroke-opacity']).toBe('0'); // invisible
1512+
expect(el.style['stroke-width']).toBe('0px'); // no pixel
1513+
1514+
el = Plotly.d3.selectAll('.shapelayer path')[0][2];
1515+
expect(el.style['pointer-events']).toBe('');
1516+
expect(el.style.stroke).toBe('rgb(0, 128, 0)'); // custom color
1517+
expect(el.style['stroke-opacity']).toBe('1'); // visible
1518+
expect(el.style['stroke-width']).toBe('3px'); // custom pixel
1519+
1520+
el = Plotly.d3.selectAll('.shapelayer path')[0][3];
1521+
expect(el.style['pointer-events']).toBe('');
1522+
expect(el.style.stroke).toBe('rgb(0, 128, 0)'); // custom color
1523+
expect(el.style['stroke-opacity']).toBe('1'); // visible
1524+
expect(el.style['stroke-width']).toBe('3px'); // custom pixel
14661525
})
14671526

14681527
.catch(failTest)
14691528
.then(done);
14701529
});
14711530

1472-
it('should provide invisible border & set pointer-events to "stroke" for editable shapes i.e. to allow shape activation', function(done) {
1531+
it('should provide invisible border & set pointer-events (depending on fill transparency) for editable shapes i.e. to allow shape activation', function(done) {
14731532
Plotly.newPlot(gd, {
14741533
data: [{
14751534
mode: 'markers',
@@ -1481,15 +1540,50 @@ describe('Activate and edit editable shapes', function() {
14811540
{
14821541
editable: true,
14831542
x0: 1.5,
1484-
x1: 2.5,
1543+
x1: 2,
14851544
y0: 1.5,
1486-
y1: 2.5,
1545+
y1: 2,
1546+
opacity: 0.5,
14871547
fillcolor: 'blue',
14881548
line: {
14891549
width: 0,
14901550
dash: 'dash',
14911551
color: 'black'
14921552
}
1553+
}, {
1554+
editable: true,
1555+
x0: 2,
1556+
x1: 2.5,
1557+
y0: 1.5,
1558+
y1: 2,
1559+
opacity: 0.7,
1560+
fillcolor: 'rgba(255,0,0,0.7)', // N.B. 0.7 * 0.7 = 0.49 <= 0.5 is quite transparent
1561+
line: {
1562+
width: 0,
1563+
dash: 'dash',
1564+
color: 'black'
1565+
}
1566+
}, {
1567+
editable: true,
1568+
x0: 1.5,
1569+
x1: 2,
1570+
y0: 2,
1571+
y1: 2.5,
1572+
fillcolor: 'red',
1573+
line: {
1574+
width: 3,
1575+
dash: 'dash',
1576+
color: 'green'
1577+
}
1578+
}, {
1579+
editable: true,
1580+
path: 'M2,2H2.5,V2.5', // open path
1581+
fillcolor: 'rgba(0,0,0,0)',
1582+
line: {
1583+
width: 3,
1584+
dash: 'dash',
1585+
color: 'green'
1586+
}
14931587
}
14941588
]
14951589
}
@@ -1501,6 +1595,24 @@ describe('Activate and edit editable shapes', function() {
15011595
expect(el.style.stroke).toBe('rgb(0, 0, 0)'); // no color
15021596
expect(el.style['stroke-opacity']).toBe('0'); // invisible
15031597
expect(el.style['stroke-width']).toBe('5px'); // some pixels to activate shape
1598+
1599+
el = Plotly.d3.selectAll('.shapelayer path')[0][1];
1600+
expect(el.style['pointer-events']).toBe('stroke');
1601+
expect(el.style.stroke).toBe('rgb(0, 0, 0)'); // no color
1602+
expect(el.style['stroke-opacity']).toBe('0'); // invisible
1603+
expect(el.style['stroke-width']).toBe('5px'); // some pixels to activate shape
1604+
1605+
el = Plotly.d3.selectAll('.shapelayer path')[0][2];
1606+
expect(el.style['pointer-events']).toBe('all');
1607+
expect(el.style.stroke).toBe('rgb(0, 128, 0)'); // custom color
1608+
expect(el.style['stroke-opacity']).toBe('1'); // visible
1609+
expect(el.style['stroke-width']).toBe('3px'); // custom pixel
1610+
1611+
el = Plotly.d3.selectAll('.shapelayer path')[0][3];
1612+
expect(el.style['pointer-events']).toBe('stroke');
1613+
expect(el.style.stroke).toBe('rgb(0, 128, 0)'); // custom color
1614+
expect(el.style['stroke-opacity']).toBe('1'); // visible
1615+
expect(el.style['stroke-width']).toBe('3px'); // custom pixel
15041616
})
15051617

15061618
.catch(failTest)

0 commit comments

Comments
 (0)