2015-11-14 3 views
2

для тех, кто работает с D3 ... У меня многострочный график и удалось заполнить область между двумя сериями. Вторая часть, которую я пытаюсь выяснить, заключается в том, что можно передавать условные операторы, чтобы заполненная область меняла цвет, когда значение точки данных одного набора больше, чем значение другой.условно заполнить область между двумя строками в d3

var w = 200, 
 
    h = 200, 
 
    p = 50; 
 

 
var ddd = [[1,.22,.12],[2,.45,.09],[3,.54,.14],[4,.32,.18],[5,.89,.19],[6,.76,.22],[7,.72,.29],[8,.68,.34],[9,.73,.22],[10,.88,.37],[11,.92,.44],[12,.95,.89],[13,.97,.97],[14,.99,1.21],[15,1.11,1.99],[16,1.01,2.38],[17,1.13,2.11],[18,1.18,2.11],[19,1.22,2.18], \t \t \t [20,1.29,2.03]], 
 
    
 
    xmin = d3.min(ddd,function(d){return d[0];}), 
 
    xmax = d3.max(ddd,function(d){return d[0];}), 
 
    ymin = 0, 
 
    ymax = 2.25; 
 

 
var xscale = d3.scale.linear() 
 
\t .domain([xmin,xmax]) 
 
\t .range([p,w-p]); 
 
var yscale = d3.scale.linear() 
 
\t .domain([ymin,ymax]) 
 
\t .range([h-p,p]); 
 
var xaxis = d3.svg.axis() 
 
\t .scale(xscale) 
 
\t .orient("bottom"); 
 
var yaxis = d3.svg.axis() 
 
\t .scale(yscale) 
 
\t .orient("left"); 
 

 
var central = d3.select("div#z") 
 
\t .append("svg") 
 
\t .attr("width",w) 
 
\t .attr("height",h); 
 

 
var line1 = d3.svg.line() 
 
\t .x(function(d) {return xscale(d[0])}) 
 
\t .y(function(d) {return yscale(d[1])}); 
 
var line2 = d3.svg.line() 
 
\t .x(function(d) {return xscale(d[0])}) 
 
\t .y(function(d) {return yscale(d[2])}); 
 

 
var x = d3.scale.linear().range([p,w-p]), 
 
\t y = d3.scale.linear().range([h-p,p]); 
 

 
var area = d3.svg.area() 
 
\t .x(function(d){return xscale(d[0])}) 
 
\t //.y0(h-p) 
 
\t .y0(function(d){return yscale(d[2])}) 
 
\t .y1(function(d){return yscale(d[1])}); 
 

 
central.append("g") 
 
\t .attr("class","axis") 
 
\t .attr("transform","translate(0," + (h-p) + ")") 
 
\t .call(xaxis); 
 
central.append("g") 
 
\t .attr("class","axis") 
 
\t .attr("transform","translate(" + (p) + ",0)") 
 
\t .call(yaxis); 
 

 
central.append("svg:path") 
 
\t .attr("d",line1(ddd)) \t 
 
    .attr("stroke","red") 
 
\t .attr("stroke-width",2) 
 
\t .attr('fill','none'); 
 
central.append("svg:path") 
 
\t .attr("d",line2(ddd)) 
 
\t .attr("stroke","blue") 
 
\t .attr("stroke-width",2) 
 
\t .attr("fill","none"); 
 

 
central.append("path") 
 
\t .datum(ddd) 
 
\t .attr("class", "area") 
 
//function(d){if (d[1] > d[2]) {return area} else {return area51};}) 
 
\t .attr("d",area);
.axis path, 
 
.axis line { 
 
    fill: none; 
 
    stroke: black; 
 
    shape-rendering: crispEdges; 
 
} 
 
.axis text { 
 
    font-family: sans-serif; 
 
    font-size: 9px; 
 
} 
 
.area { 
 
    fill: lightsteelblue; 
 
    stroke-width: 0; 
 
} 
 
.area51 { 
 
    fill: lightsteelblue; 
 
    stroke-width: 0; 
 
} 
 
.area:hover { 
 
    fill: grey; 
 
    stroke-width: 0; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="z"></div>

Так на основе диаграммы, как я могу получить правую сторону диаграммы заполненной с другим цветом?

ответ

1

Я использую library .... огромную библиотеку для обнаружения пути пересечения (любезность: @thelonious)

//the red line path 
    var rl = central.append("svg:path") 
    .attr("d",line1(ddd)) 
    .attr("id", "linered") 
    .attr("stroke","red") 
    .attr("stroke-width",2) 
    .attr('fill','none'); 

//the blue line path  
    var bl = central.append("svg:path") 
    .attr("d",line2(ddd)) 
    .attr("id", "lineblue") 
    .attr("stroke","blue") 
    .attr("stroke-width",2) 
    .attr("fill","none"); 

Чтобы получить точку пересечения этого

var shape1 = new Path(rl.node()); 
var shape2 = new Path(bl.node()); 

var overlays = Intersection.intersectShapes(shape1, shape2); 

сделать левую и правая область диаграмму отдельно, как показано ниже, и добавить разные классы

if (overlays.points.length > 0){ 
    var d = overlays.points[0] 
    var midx = xscale.invert(d.x); 
    var midy = yscale.invert(d.y); 

    //assuming that the curve will have single y values for an x 
    var left = ddd.filter(function(k){ return (k[0] <= midx);}); 
    var right = ddd.filter(function(k){ return (k[0] > midx);}); 
    //inserting the new middle point 
    right.unshift([midx,midy,midy]); 
    //left area 
    central.append("path") 
    .datum(left) 
    .attr("class", "area") 
    .attr("d",area); 
    //right area 
    central.append("path") 
    .datum(right) 
    .attr("class", "area51") 
    .attr("d",area); 
} 

W код орков here

Надеюсь, это поможет!

Смежные вопросы