From bf9b5bf9473588b846a63bafc97a11e26b021d7d Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 20 Nov 2015 14:47:05 +0100 Subject: [PATCH 1/3] 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 --- client/app/scripts/charts/node.js | 2 +- client/app/scripts/components/node-details.js | 2 +- client/app/scripts/mixins/node-color-mixin.js | 49 ++++++++++++++----- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/client/app/scripts/charts/node.js b/client/app/scripts/charts/node.js index 59023a745..81eeb5033 100644 --- a/client/app/scripts/charts/node.js +++ b/client/app/scripts/charts/node.js @@ -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; diff --git a/client/app/scripts/components/node-details.js b/client/app/scripts/components/node-details.js index fba553293..954b21c99 100644 --- a/client/app/scripts/components/node-details.js +++ b/client/app/scripts/components/node-details.js @@ -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) diff --git a/client/app/scripts/mixins/node-color-mixin.js b/client/app/scripts/mixins/node-color-mixin.js index 525005d88..51f958ba0 100644 --- a/client/app/scripts/mixins/node-color-mixin.js +++ b/client/app/scripts/mixins/node-color-mixin.js @@ -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 From 104f1574c8a217e3180d9ee0860fa7c19a98ee35 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 20 Nov 2015 15:23:44 +0100 Subject: [PATCH 2/3] Exclude red and green from color generation --- client/app/scripts/mixins/node-color-mixin.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/client/app/scripts/mixins/node-color-mixin.js b/client/app/scripts/mixins/node-color-mixin.js index 51f958ba0..1e88b9dbd 100644 --- a/client/app/scripts/mixins/node-color-mixin.js +++ b/client/app/scripts/mixins/node-color-mixin.js @@ -1,8 +1,10 @@ const d3 = require('d3'); const PSEUDO_COLOR = '#b1b1cb'; -const hueScale = d3.scale.linear().range([0, 359]); -const lightnessScale = d3.scale.linear().domain([0, 359]).range([0.3, 0.7]); +const hueRange = [20, 330]; // exclude red +const hueScale = d3.scale.linear().range(hueRange); +// map hues to lightness +const lightnessScale = d3.scale.linear().domain(hueRange).range([0.3, 0.7]); const startLetterRange = 'A'.charCodeAt(); const endLetterRange = 'Z'.charCodeAt(); const letterRange = endLetterRange - startLetterRange; @@ -23,8 +25,12 @@ function text2degree(text) { } function colors(text, secondText) { - const hue = text2degree(text); - const saturation = 0.8; + let hue = text2degree(text); + // skip green and shift to the end of the color wheel + if (hue > 70 && hue < 150) { + hue += 80; + } + const saturation = 0.7; let lightness = 0.5; if (secondText) { // reuse text2degree and feed degree to lightness scale From d0cea36b3f81e873957fc5d86ea4ddb1248615a8 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 20 Nov 2015 16:27:02 +0100 Subject: [PATCH 3/3] tweak saturation and lightness --- client/app/scripts/mixins/node-color-mixin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/app/scripts/mixins/node-color-mixin.js b/client/app/scripts/mixins/node-color-mixin.js index 1e88b9dbd..3773bc950 100644 --- a/client/app/scripts/mixins/node-color-mixin.js +++ b/client/app/scripts/mixins/node-color-mixin.js @@ -4,7 +4,7 @@ const PSEUDO_COLOR = '#b1b1cb'; const hueRange = [20, 330]; // exclude red const hueScale = d3.scale.linear().range(hueRange); // map hues to lightness -const lightnessScale = d3.scale.linear().domain(hueRange).range([0.3, 0.7]); +const lightnessScale = d3.scale.linear().domain(hueRange).range([0.5, 0.7]); const startLetterRange = 'A'.charCodeAt(); const endLetterRange = 'Z'.charCodeAt(); const letterRange = endLetterRange - startLetterRange; @@ -30,7 +30,7 @@ function colors(text, secondText) { if (hue > 70 && hue < 150) { hue += 80; } - const saturation = 0.7; + const saturation = 0.6; let lightness = 0.5; if (secondText) { // reuse text2degree and feed degree to lightness scale