Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable text for scattergl trace #2737

Merged
merged 50 commits into from
Jul 5, 2018
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
8ec98b9
Enable text-related attributes
dy Jun 14, 2018
862905c
Basic font rendering
dy Jun 15, 2018
d1a06c0
Make correct render output
dy Jun 15, 2018
cbc7f3f
Fix alignment
dy Jun 15, 2018
cc2cca1
use github 'regl-text'
etpinard Jun 18, 2018
e5a771c
Avoid double update
dy Jun 18, 2018
349b551
Fix image width
dy Jun 18, 2018
71c1acb
Add proper vertical alignment
dy Jun 20, 2018
4fe4e3a
Add textgl mocks
dy Jun 20, 2018
ff1d4fc
Use published gl-text package
dy Jun 20, 2018
95a3d1a
Compare license ignoring trailing spaces
dy Jun 20, 2018
ed7e0a0
Update deps
dy Jun 20, 2018
fa96cc7
Fix es5 word
dy Jun 20, 2018
9653fcf
Bump gl-util
dy Jun 21, 2018
17c1b0b
Add mocks
dy Jun 21, 2018
0154571
Fix mocks
dy Jun 21, 2018
c47d258
Unroll redundant change
dy Jun 21, 2018
79eae53
Bump gl-text deps
dy Jun 21, 2018
bd4491c
is isNumeric instead of typeof === 'number'
etpinard Jun 21, 2018
741bfb1
Rename mocks
dy Jun 21, 2018
4d67fa4
Fix panning
dy Jun 21, 2018
90479a7
Make text selection work
dy Jun 21, 2018
6def5e4
Fix text tests
dy Jun 21, 2018
47cf7e2
Make fast batch rendering
dy Jun 27, 2018
a53baf6
Make selection work
dy Jun 27, 2018
b3fb445
Bump gl-text
dy Jun 27, 2018
e09a4e1
Tmp fix
dy Jun 27, 2018
668d7ee
Fix undefined offsets/baseline
dy Jun 27, 2018
a41ea35
Bump gl-text
dy Jun 27, 2018
1702b30
Make selection work better
dy Jun 27, 2018
62bf263
Add baselines
dy Jun 27, 2018
65f97f3
Fix dep
dy Jun 27, 2018
55906cc
fixup package-lock
etpinard Jun 28, 2018
46bc623
clean up export names for scattergl/convert.js
etpinard Jun 28, 2018
7d75169
rename [un]selectedOptions -> marker{Unselected|Selected}Options
etpinard Jun 28, 2018
1a64005
cleanup scattergl text convert / select logic
etpinard Jun 28, 2018
bdc8f4a
apply [un]selected.textfont.color on plot
etpinard Jun 29, 2018
959a555
add & :lock: `hovertext` support for scattergl
etpinard Jun 29, 2018
431c564
fix & :lock: scattergl text visible toggles
etpinard Jun 29, 2018
9f3827c
add gl text chart select test
etpinard Jun 29, 2018
3af4d2f
use glText[0].regl to clear viewport during selection when `mode: 'te…
etpinard Jun 29, 2018
a83077b
Merge pull request #2770 from plotly/textgl-etienne
etpinard Jul 3, 2018
29fa2ef
Bump gl-text, fix safari
dy Jul 3, 2018
e462eda
fixup package-lock
etpinard Jul 4, 2018
52614d1
fix and :lock: selections + array textfont.color
etpinard Jul 4, 2018
143a61e
fixup selected textfont.color logic + add a few more tests
etpinard Jul 4, 2018
fb08f55
Bump gl-text
dy Jul 4, 2018
a5637dd
Update baselines
dy Jul 4, 2018
6aedaa6
Round texture shape
dy Jul 4, 2018
235f1ac
fixup package-lock
etpinard Jul 5, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,519 changes: 2,346 additions & 2,173 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"gl-select-box": "^1.0.2",
"gl-spikes2d": "^1.0.1",
"gl-surface3d": "^1.3.5",
"gl-text": "^1.1.1",
"glslify": "^6.1.1",
"has-hover": "^1.0.1",
"has-passive-events": "^1.0.0",
Expand Down
6 changes: 4 additions & 2 deletions src/components/drawing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,9 @@ drawing.tryColorscale = function(marker, prefix) {
else return Lib.identity;
};

var TEXTOFFSETSIGN = {start: 1, end: -1, middle: 0, bottom: 1, top: -1};
var TEXTOFFSETSIGN = {
start: 1, end: -1, middle: 0, bottom: 1, top: -1
};

function textPointPosition(s, textPosition, fontSize, markerRadius) {
var group = d3.select(s.node().parentNode);
Expand All @@ -623,7 +625,7 @@ function textPointPosition(s, textPosition, fontSize, markerRadius) {
var numLines = (svgTextUtils.lineCount(s) - 1) * LINE_SPACING + 1;
var dx = TEXTOFFSETSIGN[h] * r;
var dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r +
(TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2;
(TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2;

// fix the overall text group position
s.attr('text-anchor', h);
Expand Down
14 changes: 11 additions & 3 deletions src/traces/scattergl/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ var attrs = module.exports = overrideAll({
'this trace\'s (x,y) coordinates.'
].join(' ')
}),

hovertext: scatterAttrs.hovertext,

textposition: scatterAttrs.textposition,
textfont: scatterAttrs.textfont,

mode: {
valType: 'flaglist',
flags: ['lines', 'markers'],
flags: ['lines', 'markers', 'text'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that scattergl supports on-graph, we can add hovertext like in svg scatter traces:

hovertext: {
valType: 'string',
role: 'info',
dflt: '',
arrayOk: true,
editType: 'style',
description: [
'Sets hover text elements associated with each (x,y) pair.',
'If a single string, the same string appears over',
'all the data points.',
'If an array of string, the items are mapped in order to the',
'this trace\'s (x,y) coordinates.',
'To be seen, trace `hoverinfo` must contain a *text* flag.'
].join(' ')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 959a555

extras: ['none'],
role: 'info',
description: [
Expand Down Expand Up @@ -77,10 +83,12 @@ var attrs = module.exports = overrideAll({
hoveron: scatterAttrs.hoveron,

selected: {
marker: scatterAttrs.selected.marker
marker: scatterAttrs.selected.marker,
textfont: scatterAttrs.selected.textfont
},
unselected: {
marker: scatterAttrs.unselected.marker
marker: scatterAttrs.unselected.marker,
textfont: scatterAttrs.unselected.textfont
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? And what about selected.textfont?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed. selected.textfont.color and unselected.textfont.color do not work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly done in 1a64005

},

opacity: plotAttrs.opacity
Expand Down
145 changes: 145 additions & 0 deletions src/traces/scattergl/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ var makeBubbleSizeFn = require('../scatter/make_bubble_size_func');
var constants = require('./constants');
var DESELECTDIM = require('../../constants/interactions').DESELECTDIM;

var TEXTOFFSETSIGN = {
start: 1, left: 1, end: -1, right: -1, middle: 0, center: 0, bottom: 1, top: -1
};

function convertStyle(gd, trace) {
var i;

var opts = {
text: undefined,
marker: undefined,
line: undefined,
fill: undefined,
Expand All @@ -40,6 +45,10 @@ function convertStyle(gd, trace) {

if(trace.visible !== true) return opts;

if(subTypes.hasText(trace)) {
opts.text = convertTextfont(trace, trace.textfont);
}

if(subTypes.hasMarkers(trace)) {
opts.marker = convertMarkerStyle(trace);
opts.selected = convertMarkerSelection(trace, trace.selected);
Expand Down Expand Up @@ -88,6 +97,138 @@ function convertStyle(gd, trace) {
return opts;
}

function convertTextfont(trace, textfont) {
var textOptions = {}, i;

textOptions.color = textfont.color;

textOptions.align = [];
textOptions.baseline = [];

var textposition = Array.isArray(trace.textposition) ? trace.textposition : [trace.textposition];

for(i = 0.0; i < textposition.length; i++) {
var textpos = textposition[i].split(/\s+/);

switch(textpos[1]) {
case 'left':
textOptions.align.push('right');
break;
case 'right':
textOptions.align.push('left');
break;
default:
textOptions.align.push(textpos[1]);
}

switch(textpos[0]) {
case 'top':
textOptions.baseline.push('bottom');
break;
case 'bottom':
textOptions.baseline.push('top');
break;
default:
textOptions.baseline.push(textpos[0]);
}
}

// [{family, color, size}, {family, color, size}, ...] →
// {family: [], color: [], size: []}
if(Array.isArray(textfont)) {
textOptions.font = [];
textOptions.color = [];
for(i = 0; i < textfont.length; i++) {
textOptions.font.push({
family: textfont[i].family,
size: textfont[i].size
});
textOptions.color.push(textfont[i].color);
}
}
else {
// if any textfont param is array - make render a batch
if(Array.isArray(textfont.family) || Array.isArray(textfont.size)) {
textOptions.font = Array(Math.max(
textfont.family && textfont.family.length || 1,
textfont.size && textfont.size.length || 1
));

for(i = 0; i < textOptions.font.length; i++) {
textOptions.font[i] = {
family: textfont.family[i] || textfont.family,
size: textfont.size[i] || textfont.size
};
}
}
// if both are single values, make render fast single-value
else {
textOptions.font = {
family: textfont.family,
size: textfont.size
};
}
textOptions.color = textfont.color;
}

// corresponds to textPointPosition from component.drawing
if(trace.marker) {
var sizes = [];
if(Array.isArray(trace.marker.size)) {
for(i = 0; i < trace.marker.size.length; i++) {
sizes.push(trace.marker.size[i]);
}
}
else if(Array.isArray(trace.marker)) {
for(i = 0; i < trace.marker.length; i++) {
sizes.push(trace.marker[i].size);
}
}
else {
sizes.push(trace.marker.size);
}

textOptions.offset = [];
for(i = 0; i < Math.max(trace.x.length, trace.y.length); i++) {
var size = sizes.length > 1 ? sizes[i] : sizes[0];
var markerRadius = size / 2;
var fontSize = Array.isArray(textOptions.font) ? textOptions.font[i].size : textOptions.font.size;
var align = Array.isArray(textOptions.align) ? textOptions.align.length > 1 ? textOptions.align[i] : textOptions.align[0] : textOptions.align;
var baseline = Array.isArray(textOptions.baseline) ? textOptions.baseline.length > 1 ? textOptions.baseline[i] : textOptions.baseline[0] : textOptions.baseline;
var hSign = TEXTOFFSETSIGN[align];
var vSign = TEXTOFFSETSIGN[baseline];
var xPad = markerRadius ? markerRadius / 0.8 + 1 : 0;
var yPad = - vSign * xPad - vSign * 0.5;
textOptions.offset.push(
[hSign * xPad / fontSize, yPad / fontSize]
);
}
}

textOptions.position = [];
for(i = 0; i < trace.x.length; i++) {
textOptions.position.push(trace.x[i], trace.y[i]);
}
textOptions.text = trace.text;

// filter out bad font sizes
if(Array.isArray(textOptions.font)) {
for(i = 0; i < textOptions.font.length; i++) {
if(!isNumeric(textOptions.font[i].size)) {
textOptions.font[i].size = 0;
}
}
}
else {
if(!isNumeric(textOptions.font.size)) {
textOptions.font.size = 0;
}
}

return textOptions;
}


function convertMarkerStyle(trace) {
var count = trace._length;
var optsIn = trace.marker;
Expand Down Expand Up @@ -224,6 +365,10 @@ function convertMarkerSelection(trace, target) {
if(target.marker.opacity !== undefined) optsOut.opacity = target.marker.opacity;
}

if(target.textfont) {
optsOut.textfont = convertTextfont(trace, target.textfont);
}

return optsOut;
}

Expand Down
8 changes: 7 additions & 1 deletion src/traces/scattergl/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var handleXYDefaults = require('../scatter/xy_defaults');
var handleMarkerDefaults = require('../scatter/marker_defaults');
var handleLineDefaults = require('../scatter/line_defaults');
var handleFillColorDefaults = require('../scatter/fillcolor_defaults');
var handleTextDefaults = require('../scatter/text_defaults');

module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
function coerce(attr, dflt) {
Expand All @@ -32,9 +33,10 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
traceOut.visible = false;
return;
}
var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines';

coerce('text');
coerce('mode', len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines');
coerce('mode', defaultMode);

if(subTypes.hasLines(traceOut)) {
coerce('connectgaps');
Expand All @@ -49,6 +51,10 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
dfltHoverOn.push('points');
}

if(subTypes.hasText(traceOut)) {
handleTextDefaults(traceIn, traceOut, layout, coerce);
}

coerce('fill');
if(traceOut.fill !== 'none') {
handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce);
Expand Down
Loading