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

2951 contrasting pie and bar inside text #3130

Merged
merged 17 commits into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
15 changes: 14 additions & 1 deletion src/traces/bar/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,21 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout

if(hasInside || hasOutside) {
var textFont = coerceFont(coerce, 'textfont', layout.font);
if(hasInside) coerceFont(coerce, 'insidetextfont', textFont);

// Note that coercing `insidetextfont` is always needed –
// even if `textposition` is `outside` for each trace – since
// an outside label can become an inside one, for example because
// of a bar being stacked on top of it.
var insideTextFontDefault = Lib.extendFlat({}, textFont);
var isTraceTextfontColorSet = traceIn.textfont && traceIn.textfont.color;
var isColorInheritedFromLayoutFont = !isTraceTextfontColorSet;
if(isColorInheritedFromLayoutFont) {
delete insideTextFontDefault.color;
}
coerceFont(coerce, 'insidetextfont', insideTextFontDefault);

if(hasOutside) coerceFont(coerce, 'outsidetextfont', textFont);

coerce('constraintext');
coerce('selected.textfont.color');
coerce('unselected.textfont.color');
Expand Down
67 changes: 67 additions & 0 deletions src/traces/bar/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Copyright 2012-2018, 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 isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');

exports.coerceString = function(attributeDefinition, value, defaultValue) {
if(typeof value === 'string') {
if(value || !attributeDefinition.noBlank) return value;
}
else if(typeof value === 'number') {
if(!attributeDefinition.strict) return String(value);
}

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
};

exports.coerceNumber = function(attributeDefinition, value, defaultValue) {
if(isNumeric(value)) {
value = +value;

var min = attributeDefinition.min,
max = attributeDefinition.max,
isOutOfBounds = (min !== undefined && value < min) ||
(max !== undefined && value > max);

if(!isOutOfBounds) return value;
}

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
};

exports.coerceColor = function(attributeDefinition, value, defaultValue) {
if(tinycolor(value).isValid()) return value;

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
};

exports.coerceEnumerated = function(attributeDefinition, value, defaultValue) {
if(attributeDefinition.coerceNumber) value = +value;

if(attributeDefinition.values.indexOf(value) !== -1) return value;

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
};

exports.getValue = function(arrayOrScalar, index) {
var value;
if(!Array.isArray(arrayOrScalar)) value = arrayOrScalar;
else if(index < arrayOrScalar.length) value = arrayOrScalar[index];
return value;
};
110 changes: 11 additions & 99 deletions src/traces/bar/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

var d3 = require('d3');
var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');

var Lib = require('../../lib');
var svgTextUtils = require('../../lib/svg_text_utils');
Expand All @@ -22,10 +21,9 @@ var Registry = require('../../registry');

var attributes = require('./attributes'),
attributeText = attributes.text,
attributeTextPosition = attributes.textposition,
attributeTextFont = attributes.textfont,
attributeInsideTextFont = attributes.insidetextfont,
attributeOutsideTextFont = attributes.outsidetextfont;
attributeTextPosition = attributes.textposition;
var helpers = require('./helpers');
var style = require('./style');

// padding in pixels around text
var TEXTPAD = 3;
Expand Down Expand Up @@ -177,9 +175,10 @@ function appendBarText(gd, bar, calcTrace, i, x0, x1, y0, y1) {
return;
}

var textFont = getTextFont(trace, i, gd._fullLayout.font),
insideTextFont = getInsideTextFont(trace, i, textFont),
outsideTextFont = getOutsideTextFont(trace, i, textFont);
var layoutFont = gd._fullLayout.font;
var barColor = style.getBarColor(calcTrace[i], trace);
var insideTextFont = style.getInsideTextFont(trace, i, layoutFont, barColor);
var outsideTextFont = style.getOutsideTextFont(trace, i, layoutFont);

// compute text position
var barmode = gd._fullLayout.barmode,
Expand Down Expand Up @@ -429,98 +428,11 @@ function getTransform(textX, textY, targetX, targetY, scale, rotate) {
}

function getText(trace, index) {
var value = getValue(trace.text, index);
return coerceString(attributeText, value);
var value = helpers.getValue(trace.text, index);
return helpers.coerceString(attributeText, value);
}

function getTextPosition(trace, index) {
var value = getValue(trace.textposition, index);
return coerceEnumerated(attributeTextPosition, value);
}

function getTextFont(trace, index, defaultValue) {
return getFontValue(
attributeTextFont, trace.textfont, index, defaultValue);
}

function getInsideTextFont(trace, index, defaultValue) {
return getFontValue(
attributeInsideTextFont, trace.insidetextfont, index, defaultValue);
}

function getOutsideTextFont(trace, index, defaultValue) {
return getFontValue(
attributeOutsideTextFont, trace.outsidetextfont, index, defaultValue);
}

function getFontValue(attributeDefinition, attributeValue, index, defaultValue) {
attributeValue = attributeValue || {};

var familyValue = getValue(attributeValue.family, index),
sizeValue = getValue(attributeValue.size, index),
colorValue = getValue(attributeValue.color, index);

return {
family: coerceString(
attributeDefinition.family, familyValue, defaultValue.family),
size: coerceNumber(
attributeDefinition.size, sizeValue, defaultValue.size),
color: coerceColor(
attributeDefinition.color, colorValue, defaultValue.color)
};
}

function getValue(arrayOrScalar, index) {
var value;
if(!Array.isArray(arrayOrScalar)) value = arrayOrScalar;
else if(index < arrayOrScalar.length) value = arrayOrScalar[index];
return value;
}

function coerceString(attributeDefinition, value, defaultValue) {
if(typeof value === 'string') {
if(value || !attributeDefinition.noBlank) return value;
}
else if(typeof value === 'number') {
if(!attributeDefinition.strict) return String(value);
}

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
}

function coerceEnumerated(attributeDefinition, value, defaultValue) {
if(attributeDefinition.coerceNumber) value = +value;

if(attributeDefinition.values.indexOf(value) !== -1) return value;

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
}

function coerceNumber(attributeDefinition, value, defaultValue) {
if(isNumeric(value)) {
value = +value;

var min = attributeDefinition.min,
max = attributeDefinition.max,
isOutOfBounds = (min !== undefined && value < min) ||
(max !== undefined && value > max);

if(!isOutOfBounds) return value;
}

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
}

function coerceColor(attributeDefinition, value, defaultValue) {
if(tinycolor(value).isValid()) return value;

return (defaultValue !== undefined) ?
defaultValue :
attributeDefinition.dflt;
var value = helpers.getValue(trace.textposition, index);
return helpers.coerceEnumerated(attributeTextPosition, value);
}
122 changes: 104 additions & 18 deletions src/traces/bar/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,17 @@
'use strict';

var d3 = require('d3');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var Lib = require('../../lib');
var Registry = require('../../registry');

var attributes = require('./attributes'),
attributeTextFont = attributes.textfont,
attributeInsideTextFont = attributes.insidetextfont,
attributeOutsideTextFont = attributes.outsidetextfont;
var helpers = require('./helpers');

function style(gd, cd) {
var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.bars');
var barcount = s.size();
Expand Down Expand Up @@ -50,21 +58,8 @@ function stylePoints(sel, trace, gd) {

txs.each(function(d) {
var tx = d3.select(this);
var textFont;

if(tx.classed('bartext-inside')) {
textFont = trace.insidetextfont;
} else if(tx.classed('bartext-outside')) {
textFont = trace.outsidetextfont;
}
if(!textFont) textFont = trace.textfont;

function cast(k) {
var cont = textFont[k];
return Array.isArray(cont) ? cont[d.i] : cont;
}

Drawing.font(tx, cast('family'), cast('size'), cast('color'));
var font = determineFont(tx, d, trace, gd);
Drawing.font(tx, font);
});
}

Expand All @@ -73,14 +68,105 @@ function styleOnSelect(gd, cd) {
var trace = cd[0].trace;

if(trace.selectedpoints) {
Drawing.selectedPointStyle(s.selectAll('path'), trace);
Drawing.selectedTextStyle(s.selectAll('text'), trace);
stylePointsInSelectionMode(s, trace, gd);
} else {
stylePoints(s, trace, gd);
}
}

function stylePointsInSelectionMode(s, trace, gd) {
Drawing.selectedPointStyle(s.selectAll('path'), trace);
styleTextInSelectionMode(s.selectAll('text'), trace, gd);
}

function styleTextInSelectionMode(txs, trace, gd) {
txs.each(function(d) {
var tx = d3.select(this);
var font;

if(d.selected) {
font = Lib.extendFlat({}, determineFont(tx, d, trace, gd));

var selectedFontColor = trace.selected.textfont && trace.selected.textfont.color;
if(selectedFontColor) {
font.color = selectedFontColor;
}

Drawing.font(tx, font);
} else {
Drawing.selectedTextStyle(tx, trace);
}
});
}

function determineFont(tx, d, trace, gd) {
var layoutFont = gd._fullLayout.font;
var textFont = trace.textfont;

if(tx.classed('bartext-inside')) {
var barColor = getBarColor(d, trace);
textFont = getInsideTextFont(trace, d.i, layoutFont, barColor);
} else if(tx.classed('bartext-outside')) {
textFont = getOutsideTextFont(trace, d.i, layoutFont);
}

return textFont;
}

function getTextFont(trace, index, defaultValue) {
return getFontValue(
attributeTextFont, trace.textfont, index, defaultValue);
}

function getInsideTextFont(trace, index, layoutFont, barColor) {
var defaultFont = getTextFont(trace, index, layoutFont);

var wouldFallBackToLayoutFont =
(trace._input.textfont === undefined || trace._input.textfont.color === undefined) ||
(Array.isArray(trace.textfont.color) && trace.textfont.color[index] === undefined);
if(wouldFallBackToLayoutFont) {
defaultFont = {
color: Color.contrast(barColor),
family: defaultFont.family,
size: defaultFont.size
};
}

return getFontValue(
attributeInsideTextFont, trace.insidetextfont, index, defaultFont);
}

function getOutsideTextFont(trace, index, layoutFont) {
var defaultFont = getTextFont(trace, index, layoutFont);
return getFontValue(
attributeOutsideTextFont, trace.outsidetextfont, index, defaultFont);
}

function getFontValue(attributeDefinition, attributeValue, index, defaultValue) {
attributeValue = attributeValue || {};

var familyValue = helpers.getValue(attributeValue.family, index),
sizeValue = helpers.getValue(attributeValue.size, index),
colorValue = helpers.getValue(attributeValue.color, index);

return {
family: helpers.coerceString(
attributeDefinition.family, familyValue, defaultValue.family),
size: helpers.coerceNumber(
attributeDefinition.size, sizeValue, defaultValue.size),
color: helpers.coerceColor(
attributeDefinition.color, colorValue, defaultValue.color)
};
}

function getBarColor(cd, trace) {
return cd.mc || trace.marker.color;
}

module.exports = {
style: style,
styleOnSelect: styleOnSelect
styleOnSelect: styleOnSelect,
getInsideTextFont: getInsideTextFont,
getOutsideTextFont: getOutsideTextFont,
getBarColor: getBarColor
};
Loading