Procedural color creation for nodes

* color hue is based on the first 2 letters of node rank
* color lightness is based on the first 2 letters of node label
This commit is contained in:
David Kaltschmidt
2015-11-20 14:47:05 +01:00
parent 0cae3541fa
commit bf9b5bf947
3 changed files with 38 additions and 15 deletions

View File

@@ -23,7 +23,7 @@ const Node = React.createClass({
let labelOffsetY = 18;
let subLabelOffsetY = 35;
const isPseudo = !!this.props.pseudo;
const color = isPseudo ? '' : this.getNodeColor(this.props.rank);
const color = isPseudo ? '' : this.getNodeColor(this.props.rank, this.props.label);
const onMouseEnter = this.handleMouseEnter;
const onMouseLeave = this.handleMouseLeave;
const onMouseClick = this.handleMouseClick;

View File

@@ -61,7 +61,7 @@ const NodeDetails = React.createClass({
return this.renderLoading();
}
const nodeColor = this.getNodeColorDark(details.rank);
const nodeColor = this.getNodeColorDark(details.rank, details.label_major);
const styles = {
controls: {
'backgroundColor': this.brightenColor(nodeColor)

View File

@@ -1,25 +1,48 @@
const d3 = require('d3');
const colors = d3.scale.category20();
const PSEUDO_COLOR = '#b1b1cb';
let colorIndex = 0;
const hueScale = d3.scale.linear().range([0, 359]);
const lightnessScale = d3.scale.linear().domain([0, 359]).range([0.3, 0.7]);
const startLetterRange = 'A'.charCodeAt();
const endLetterRange = 'Z'.charCodeAt();
const letterRange = endLetterRange - startLetterRange;
/**
* Converts a text to a 360 degree value
*/
function text2degree(text) {
const input = text.substr(0, 2).toUpperCase();
let num = 0;
let charCode;
for (let i = 0; i < input.length; i++) {
charCode = Math.max(Math.min(input[i].charCodeAt(), endLetterRange), startLetterRange);
num += Math.pow(letterRange, input.length - i - 1) * (charCode - startLetterRange);
}
hueScale.domain([0, Math.pow(letterRange, input.length)]);
return hueScale(num);
}
function colors(text, secondText) {
const hue = text2degree(text);
const saturation = 0.8;
let lightness = 0.5;
if (secondText) {
// reuse text2degree and feed degree to lightness scale
lightness = lightnessScale(text2degree(secondText));
}
const color = d3.hsl(hue, saturation, lightness);
return color;
}
const NodeColorMixin = {
getNodeColor: function(text) {
colorIndex++;
// skip green and red (index 5-8 in d3.scale.category20)
if (colorIndex > 4 && colorIndex < 9) {
colors('_' + colorIndex);
return this.getNodeColor(text);
}
return colors(text);
getNodeColor: function(text, secondText) {
return colors(text, secondText);
},
getNodeColorDark: function(text) {
getNodeColorDark: function(text, secondText) {
if (text === undefined) {
return PSEUDO_COLOR;
}
const color = d3.rgb(colors(text));
const color = d3.rgb(colors(text, secondText));
let hsl = color.hsl();
// ensure darkness