2017-11-19 22 views
2

私はちょうどlynda.comのコースを取ってjavascriptd3.jsを学び始めました。私の目標は、数字の配列やカットオフを取り、このようなプロットを生成する関数を作成することです:2または3色の領域のプロット密度関数?

density

私はこれを生成するJavaScriptコードを書くことができました:

enter image description here

ああ、-opts.thresholdの左の領域は、-opts.thresholdopts.thresholdの間の領域を読み取る必要があり、残りは緑色であることを伝える方法を見つけ出すのに苦労しています。

これは私のjavascriptコードです:これは便利である場合には

HTMLWidgets.widget({ 

    name: 'IMposterior', 

    type: 'output', 

    factory: function(el, width, height) { 

    // TODO: define shared variables for this instance 

    return { 

     renderValue: function(opts) { 

     console.log("MME: ", opts.MME); 
     console.log("threshold: ", opts.threshold); 
     console.log("prob: ", opts.prob); 
     console.log("colors: ", opts.colors); 


     var margin = {left:50,right:50,top:40,bottom:0}; 

     var xMax = opts.x.reduce(function(a, b) { 
      return Math.max(a, b); 

     }); 
     var yMax = opts.y.reduce(function(a, b) { 
      return Math.max(a, b); 

     }); 
     var xMin = opts.x.reduce(function(a, b) { 
      return Math.min(a, b); 

     }); 
     var yMin = opts.y.reduce(function(a, b) { 
      return Math.min(a, b); 

     }); 


     var y = d3.scaleLinear() 
        .domain([0,yMax]) 
        .range([height,0]); 

     var x = d3.scaleLinear() 
        .domain([xMin,xMax]) 
        .range([0,width]); 


     var yAxis = d3.axisLeft(y); 
     var xAxis = d3.axisBottom(x); 


     var area = d3.area() 
         .x(function(d,i){ return x(opts.x[i]) ;}) 
         .y0(height) 
         .y1(function(d){ return y(d); }); 

     var svg = d3.select(el).append('svg').attr("height","100%").attr("width","100%"); 
     var chartGroup = svg.append("g").attr("transform","translate("+margin.left+","+margin.top+")"); 


     chartGroup.append("path") 
      .attr("d", area(opts.y)); 


     chartGroup.append("g") 
      .attr("class","axis x") 
      .attr("transform","translate(0,"+height+")") 
      .call(xAxis); 


     }, 

     resize: function(width, height) { 

     // TODO: code to re-render the widget with a new size 

     } 

    }; 
    } 
}); 

、私はpublic github repo上のすべての私のコードを保存しました。

答えて

1

このanswerでは、グラディエントを使用するか、複数の領域を使用するという2つの提案されたソリューションがあります。別の解決策を提案します:この領域を、3つの矩形のクリップパスとして使用し、一緒にプロット領域全体をカバーします。

各矩形の左端と右端を保持するデータ配列を作成して矩形を作成します。 Rectangleのheight属性とy属性は、長方形を追加するときにそれぞれsvgの高さとゼロに設定することができるため、配列に含める必要はありません。

最初の矩形の左端の長さはxScale.range()[0]で、最後の矩形の右端の長さはxScale.range()[1]です。中間座標xScale(1)に配置することができ、xScale(-1)など

このような配列は、(あなたの提案の設定とXスケール名を使用して)次のようになります。

var rects = [ 
       [x.range()[0],x(-1)], 
       [x(-1),x(1)], 
       [x(1),x.range()[1]] 
      ] 

そして、それらを配置します。

.enter() 
    .append("rect") 
    .attr("x", function(d) { return d[0]; }) 
    .attr("width", function(d) { return d[1] - d[0]; }) 
    .attr("y", 0) 
    .attr("height",height) 

長方形にclip-path属性を設定することを忘れないでください: .attr("clip-path","url(#areaID)")、および塗りつぶしを3つの異なる色に設定してください。

svg.append("clipPath) 
.attr("id","area") 
.append("path") 
.attr(// area attributes 
... 

Hereのアクションで概念(使用いえ:今あなたがしなければならないすべてはnoneにお住まいの地域の塗りと線を設定し、指定されたIDを持つクリップパスにお住まいの地域を追加している

長方形またはテキストパスに影響を与えてはならないV3、。@アンドリュー・レイド提案へ

0

おかげで、私は複数の領域を使用するソリューションを実装することができました。

enter image description here

HTMLWidgets.widget({ 

    name: 'IMposterior', 

    type: 'output', 

    factory: function(el, width, height) { 

    // TODO: define shared variables for this instance 

    return { 

     renderValue: function(opts) { 

     console.log("MME: ", opts.MME); 
     console.log("threshold: ", opts.threshold); 
     console.log("prob: ", opts.prob); 
     console.log("colors: ", opts.colors); 
     console.log("data: ", opts.data); 


     var margin = {left:50,right:50,top:40,bottom:0}; 

     xMax = d3.max(opts.data, function(d) { return d.x ; }); 
     yMax = d3.max(opts.data, function(d) { return d.y ; }); 
     xMin = d3.min(opts.data, function(d) { return d.x ; }); 
     yMin = d3.min(opts.data, function(d) { return d.y ; }); 

     var y = d3.scaleLinear() 
        .domain([0,yMax]) 
        .range([height,0]); 

     var x = d3.scaleLinear() 
        .domain([xMin,xMax]) 
        .range([0,width]); 


     var yAxis = d3.axisLeft(y); 
     var xAxis = d3.axisBottom(x); 


     var area = d3.area() 
         .x(function(d){ return x(d.x) ;}) 
         .y0(height) 
         .y1(function(d){ return y(d.y); }); 

     var svg = d3.select(el).append('svg').attr("height","100%").attr("width","100%"); 
     var chartGroup = svg.append("g").attr("transform","translate("+margin.left+","+margin.top+")"); 


     chartGroup.append("path") 
      .attr("d", area(opts.data.filter(function(d){ return d.x< -opts.MME ;}))) 
      .style("fill", opts.colors[0]); 

     chartGroup.append("path") 
      .attr("d", area(opts.data.filter(function(d){ return d.x > opts.MME ;}))) 
      .style("fill", opts.colors[2]); 

     if(opts.MME !==0){ 
      chartGroup.append("path") 
      .attr("d", area(opts.data.filter(function(d){ return (d.x < opts.MME & d.x > -opts.MME) ;}))) 
      .style("fill", opts.colors[1]); 
     } 


     chartGroup.append("g") 
      .attr("class","axis x") 
      .attr("transform","translate(0,"+height+")") 
      .call(xAxis); 


     }, 

     resize: function(width, height) { 

     // TODO: code to re-render the widget with a new size 

     } 

    }; 
    } 
}); 
関連する問題