2012-08-31 3 views
9

私はヒートマップを実装しています。ヒートマップでは、セルの背景色がd3カラースケールで決定されます。値の一部はカテゴリに分類されます。それらの値は、["6TH"、 "7TH"、 "5TH"、 "4TH"のようなN個の異なる任意の文字列タイプのカテゴリにすることができます。文字列の離散領域からの連続カラースケール?

開始色d3.rgb( "blue")と終了色d3.rgb( "red")を指定すると、文字列の離散領域を連続した色範囲にマップするカラースケールを構築する方法はありますか?

私は明らかに動作しません

var scale = d3.scale.ordinal() 
    .domain(["6TH", "7TH", "5TH", "4TH"]) 
    .rangeBands([ d3.rgb("blue"), d3.rgb("red") ]); 

を試してみました。

答えて

29

まず、簡単に入手できるColorbrewerスケールの1つを使用することを検討します。 colorbrewer2.orgを参照してください。これらは、D3のgitリポジトリのJavaScriptおよびCSSファイルとしても利用できます。 lib/colorbrewerを参照してください。あなたは、ドメインの4つの離散的な値を持っている、とあなたは赤青の発散規模をしたい場合たとえば、あなたが言うことができる:

var color = d3.scale.ordinal() 
    .domain(["6TH", "7TH", "5TH", "4TH"]) 
    .range(colorbrewer.RdBu[4]); 

を(あなたも、この前<script src="colorbrewer.js"></script>どこかが必要です。)Colorbrewerがありさまざまなうまく設計された逐次的、発散的、分類的なカラースケールがあります。

独自のカラースケールを使用することをお勧めする場合は、正確な認識のためにL*a*b* or HCL color spaceで補間することを強くお勧めします。 d3.interpolateLabまたはd3.interpolateHclを使用してこれを行うことができます。たとえば、d3.interpolateLab("red", "blue")(.5)は赤と青の中間の色を返します。

尺度の範囲の色を計算するには、補間器を使用するか、一時的な線形尺度を使用すると便利です。例:

var categories = ["6TH", "7TH", "5TH", "4TH"]; 

var color = d3.scale.ordinal() 
    .domain(categories) 
    .range(d3.range(categories.length).map(d3.scale.linear() 
     .domain([0, categories.length - 1]) 
     .range(["red", "blue"]) 
     .interpolate(d3.interpolateLab))); 
+1

更新:D3のColorbrewerのlibが[d3-scale-chromatic](https://github.com/d3/d3-scale-chromatic)リポジトリに移動しました。 – danasilver

3

あなたは正しいアイデアを持っているので、各R/G/Bカラーチャンネルを処理するだけで済みます。たとえば、次の操作を行うことができますJavaScriptのバニラに:

# d3.rgb(color)

var a = [255, 0, 0], // First color 
    b = [0, 0, 255], // Other color 
    bands = 5,  // Bands is the length of your domain 
    i, 
    delta = [];  // Difference between color in each channel 

// Compute difference between each color 
for (i = 0; i < 4; i++){ 
    delta[i] = (a[i] - b[i])/(bands + 1); 
} 

// Use that difference to create your bands 
for (i = 0; i <= bands + 1; i++){ 
    var r = Math.round(a[0] - delta[0] * i); 
    var g = Math.round(a[1] - delta[1] * i); 
    var b = Math.round(a[2] - delta[2] * i); 
    console.log("<div style='background-color: #" + dec2hex(r) + dec2hex(g) + dec2hex(b) + "'>Band " + i + "</div>"); 
} 

// A helper function for formatting 
function dec2hex(i) { 
    return (i+0x100).toString(16).substr(-2).toUpperCase(); 
} 

d3 documentationによると、あなたは色のオブジェクトのrgb属性を使用して、各カラーチャンネルを抽出することができます

指定された色の文字列を解析して新しいRGB色を作成します。 colorが文字列でない場合は、文字列に変換されます。このコンストラクタを使用して、既存の色のコピーを作成したり、d3.hslの色をRGBに強制的に変換したりすることもできます。

...

得られた色は、[0,255]の範囲で、赤、緑及び青の整数チャンネル値として記憶されます。チャネルは、返されるオブジェクトのr、g、およびb属性として使用できます。

したがって、上記の例の上部に、あなたが言うことができる:

var myColor = d3.rgb("blue"), 
    a = [myColor.r, myColor.g, myColor.b], 
... 

はその助けをしていますか?

+0

はい、その確かに助けました!ありがとう、完璧に動作します。 – ekerner

0

いつも尺度と線形尺度を連鎖させることができます。

最初のスケールは離散値から定量化可能な値を作成し、2番目のスケールはこれらの値をカラースケールで補間します。このような

何か:

// Your categories 
 
var data = ["6TH", "7TH", "5TH", "4TH"], 
 

 
    // Define ordinal to linear scale... 
 
    ordinal = d3.scale.ordinal().domain(data).rangePoints([0, 1]), 
 

 
    // ...and linear to color scale 
 
    linear = d3.scale.linear().domain([0, 1]).range([d3.rgb("blue"), d3.rgb("red")]); 
 

 
// Now define your artificial 'compound' scale 
 
function scale(d) { 
 
    return linear(ordinal(d)); 
 
} 
 

 
// And then use it on your D3 code 
 
d3.selectAll('div') 
 
    .data(data) 
 
    .enter() 
 
    .append('div') 
 
    .style('background', scale) // <- et voilà ;) 
 
    .text(function(d) { 
 
    return d; 
 
    });
div { 
 
    color: white; 
 
    width: 3em; 
 
    padding: 1em; 
 
    margin: .2em 
 
    text-align: center; 
 
    font-family: Arial, Helvetica, sans-serif; 
 
    font-weight: bold 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

関連する問題