2012-04-02 7 views
2

2行の間に陰影を付けるJavaScriptチャートライブラリを探しています。 ChartDirectorはこれを非常にうまく処理します(http://www.advsofteng.com/gallery_line2.html - ライン間の色付けを参照)が、よりインタラクティブなチャートライブラリが必要です。2行の間の陰影領域を処理するためのJavaScriptグラフ作成ライブラリ

さまざまなJavaScriptライブラリを調べました。 FLOTとHighchartsは近づくが、それでも彼らの制限があります。

  • FLOTはfillBetweenプラグインを使用して、2つのライン間のシェーディングをサポートしていますが、一番上にある行に応じて、複数の色で濃淡をサポートしていません。
  • 積み重ねられたエリアチャートを使用してハイチャートで2つのライン間のシェーディングを達成できますが、2つのラインが交差する場合は処理しません。

+0

FusionCharts XT - http://fusioncharts.com/をご覧ください。 2行の間に陰影は表示されませんが、インタラクティブなJavaScriptグラフ作成ライブラリの要件を満たしています。 –

答えて

1

ハイチャートを使用してしまいました。私はこの例をElementStacksとし、交点を扱うように修正しました。 Negative Areaを参照してください。

$(function() { 
var Intersection = function (d1, d2) { 
    var self = this; 

    this.init = function() { 
    this.d1 = this.sortLine(d1); 
    this.d2 = this.sortLine(d2); 

    if (this.d1.length != this.d2.length) { 
     throw 'd1 and d2 expected to be same size'; 
    } 

    this.dps = _.zip(d1, d2); 

    hasUnmatchedIndex = _.any(this.dps, function(dp_pair) { 
     return dp_pair[0][0] != dp_pair[1][0]; 
    }); 

    if (hasUnmatchedIndex) 
     throw 'd1 and d2 do not have same indices'; 
    }; 

    this.sortLine = function(line) { 
    return _.sortBy(line, function(dp) { return dp[0]; }); 
    }; 

    this.transitions = function() { 
    return _.map(this.dps, function(dp_pair) { 
     a = dp_pair[0]; 
     b = dp_pair[1]; 
     result = null; 
     if (a[1] < b[1]) 
     result = -1; 
     else if (a[1] > b[1]) 
     result = 1; 
     else 
     result = 0; 

     return [a[0], result]; 
    }); 
    }; 

    this.dropTransitions = function() { 
    prev = null; 
    drops = []; 

    _.each(this.transitions(), function(curr) { 
     if (prev && prev[1] != curr[1] && prev[1] != 0 && curr[1] != 0) 
     drops.push([prev, curr]) 
     prev = curr; 
    }); 

    return drops; 
    }; 

    this.data = function() { 
    //self = this; 
    _d1 = this.sortLine(this.d1.concat(this.intersections())); 
    _d2 = this.sortLine(this.d2.concat(this.intersections())); 
    d1_g = []; 
    d2_g = []; 
    d_min = []; 
    dps = _.zip(_d1, _d2); 
    _.each(dps, function(dp_pair,i) { 
     index = dp_pair[0][0]; 
     dpv1 = dp_pair[0][1]; 
     dpv2 = dp_pair[1][1]; 

     if (dpv1 == null || dpv2 == null) { 
     d1_g.push([index, null]); 
     d2_g.push([index, null]); 
     } else { 
     diff = Math.abs(dpv1 - dpv2); 
     if (dpv1 > dpv2) { 
      d1_g.push([index, diff]); 
      d2_g.push([index, 0]); 
     } else if (dpv2 > dpv1) { 
      d1_g.push([index, 0]); 
      d2_g.push([index, diff]); 
     } else { 
      d1_g.push([index, diff]); 
      d2_g.push([index, diff]); 
     } 
     } 
     d_min.push([index, Math.min(dpv1, dpv2)]); 
    }); 

    return [d1_g, d2_g, d_min]; 
    }; 

    this.intersections = function() { 
    //self = this; 

    return _.map(this.dropTransitions(), function(dt) { 
     line1 = _.filter(self.d1, function(dp) { 
     return dp[0] == dt[0][0] || dp[0] == dt[1][0]; 
     }); 

     line2 = _.filter(self.d2, function(dp) { 
     return dp[0] == dt[0][0] || dp[0] == dt[1][0]; 
     }); 

     return self.findIntersection(line1, line2); 
    }); 
    }; 

    this.findIntersection = function(line1, line2) { 
    eq1 = this.lineEquation(line1); 
    eq2 = this.lineEquation(line2); 

    m1 = eq1.m; 
    b1 = eq1.b; 

    m2 = eq2.m; 
    b2 = eq2.b; 

    x = (b2 - b1)/(m1 - m2) 
    y = (m1 * x) + b1 
    return [x,y]; 
    }; 

    this.lineEquation = function(line) { 
    p1 = _.map(line[0], function(n) { return parseFloat(n); }); 
    p2 = _.map(line[1], function(n) { return parseFloat(n); }); 

    x1 = p1[0]; 
    y1 = p1[1]; 

    x2 = p2[0]; 
    y2 = p2[1]; 

    m = (y1 - y2)/(x1 - x2); 
    b = y1 - (m*x1); 
    eq = {'m': m, 'b': b}; 
    return eq; 
    }; 

    this.print = function (obj) { alert(JSON.stringify(obj)); }; 
    this.init(d1, d2); 
}; 

var d1r = [10, 8, 7, 6, 5, 4, 3, 5, 3, 9, 10, 11, 2]; 
var d2r = [ 5, 6, 7, 8, 9, 10, 9, 8, 12, 3, 2, 1, 20]; 

var d1 = _.map(d1r, function(e,i) { return [i, e-10]; }); 
var d2 = _.map(d2r, function(e,i) { return [i, e-10]; }); 

var t = new Intersection(d1, d2); 
var data = t.data(); 
var values = _.map(data, function(dps) { 
    return _.map(dps, function(dp) { 
     return dp[1]; 
    });   
}); 
var minValue = _.min(_.flatten(values)); 
// Need to find threshold to handle negative stacking values 
var threshold = minValue < 0 ? minValue : 0; 


var dp1 = t.d1; 

var dp2 = t.d2; 

var dp1_g = data[0]; 

var dp2_g = data[1]; 

var dp_min = data[2]; 

var chart = new Highcharts.Chart({ 
    chart: { 
     renderTo: 'container', 
     type: 'area', 
     animation: false 
    }, 
    plotOptions: { 
     area: { 
      stacking: true, 
      lineWidth: 0, 
      shadow: false, 
      marker: { 
       enabled: false 
      }, 
      enableMouseTracking: false, 
      showInLegend: false   
     }, 
     line: { 
      zIndex: 5 
     }, 
     series: { 
      threshold: threshold 
     } 
    }, 
    series: [{ 
     type: 'line', 
     color: 'red', 
     data: dp1 

    },{ 
     type: 'line', 
     color: 'black', 
     data: dp2 

    },{ 
     color: 'orange', 
     data: dp1_g 

    },{ 
     color: 'grey', 
     data: dp2_g 

    },{ 
     id: 'transparent', 
     color: 'rgba(255,255,255,0.0)', 
     data: dp_min 

    }] 
}, function(chart){ 
    chart.get('transparent').area.hide(); 
}); 
}); 
関連する問題