2017-06-27 3 views
0

私は、定義された日付の値のみを許可するレスポンシブなD3スライダで作業しています。問題は:私の関数resize_slider()は、ウィンドウのサイズが変わった場合にスライダのサイズを変更しません。任意のアイデアとスライダー幅を変更する最善の方法は何ですか?レスポンシブD3スムーズスライダ - ウィンドウのスライダの幅を変更する

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <meta charset="utf-8"> 
     <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> 

     <style type="text/css"> 
      .axis_slider .domain { 
       fill: none; 
       stroke: #000; 
       stroke-opacity: .3; 
       stroke-width: 10px; 
       stroke-linecap: round; 
      } 

      .axis_slider .halo { 
       fill: none; 
       stroke: #ddd; 
       stroke-width: 8px; 
       stroke-linecap: round; 
      } 

      .handle { 
       fill: #fff; 
       stroke: #000; 
       stroke-opacity: .5; 
       stroke-width: 1.25px; 
       pointer-events: none; 
      } 

     </style> 

    </head> 


    <body> 


     <div class="matrixchart"> 
      <div id="scatterchart_slider"><div id="playbutton" style="position: absolute; left: 20px; top:30px;"><img src="images/play.gif" width="50px" height=50px; onmouseover="this.src='images/play2.gif';" onmouseout="this.src='images/play.gif';"></div></div> 
     </div> 



     <script type="text/javascript"> 

      var date_values=[]; 
      date_values[0] = new Date(2016,9,31); 
      date_values[1] = new Date(2016,10,30); 
      date_values[2] = new Date(2016,11,30); 
      date_values[3] = new Date(2017,0,31); 
      var current_nr_date_values = date_values.length-1; 

      var play_width = 50; 
      var padding = 50; 
      var w = window.innerWidth - padding; 


      var margin = {top: 0, right: padding*2, bottom: 300, left: padding*2}, 
       height_slider = 100; 

      var slider_plays = false; 
      var slider_play_newstart = false; 

      var slider_x = d3.time.scale() 
       .domain([date_values[0], date_values[date_values.length-1]]) 
       .range([0, w - 4*padding]) 
       .clamp(true); 

      var brush = d3.svg.brush() 
       .x(slider_x) 
       .on("brush", brushed) 
       .on("brushend", brushend); 

      var svg_slider = d3.select("#scatterchart_slider").append("svg") 
       .attr("width", w-play_width) 
       .attr("height", height_slider) 
       .append("g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

      svg_slider.append("g") 
       .attr("class", "x axis_slider") 
       .attr("transform", "translate(0," + height_slider/2 + ")") 
       .call(d3.svg.axis() 
        .scale(slider_x) 
        .tickValues(date_values) 
        .orient("bottom") 
        .tickFormat(d3.time.format("%b %Y")) 
        .tickPadding(12)) 
        .select(".domain") 
        .select(function() { return this.parentNode.appendChild(this.cloneNode(true)); }) 
        .attr("class", "halo"); 

      var slider = svg_slider.append("g") 
       .attr("class", "slider") 
       .call(brush); 

      slider.selectAll(".extent,.resize") 
       .remove(); 

      slider.select(".background") 
       .attr("height", height_slider); 

      var handle = slider.append("circle") 
       .attr("class", "handle") 
       .attr("transform", "translate(0," + height_slider/2 + ")") 
       .attr("r", 9); 

      slider 
       .call(brush.extent([date_values[current_nr_date_values], date_values[current_nr_date_values]])) 
       .call(brush.event); 


      function brushed() { 
       var value = brush.extent()[0]; 

       if (d3.event.sourceEvent) { 
       value = slider_x.invert(d3.mouse(this)[0]); 
       brush.extent([value, value]); 
       } 

       handle.attr("cx", slider_x(value)); 
      } 

      function brushend() { 
       if (!d3.event.sourceEvent) { 
       return; // only transition after input 
       } 

       var value = brush.extent()[0];      
       brush.extent([value, value]); 

       d3.select(this) 
       .transition() 
       .call(brush.event);       

       function getRoundedDate_ID(d) { 
        nearest_date_nr = 0 
        for (var i = 1; i<=date_values.length-1; i++) { 
         if ((Math.abs(d.getTime() - new Date(date_values[i]).getTime())) < (d.getTime() - new Date(date_values[nearest_date_nr]).getTime())) {nearest_date_nr = i;} 
        }  
        return nearest_date_nr; 
       } 

       d3.select(this) 
       .transition() 
       .duration(1000) 
       .call(brush.extent(brush.extent().map(function(d) { 
        var roundedDate= new Date(d); 
        current_nr_date_values = getRoundedDate_ID(d); 
        return date_values[current_nr_date_values] 
        }))) 

       .call(brush.event); 
      }  


      function resize_slider(){ 
       w = window.innerWidth - padding; 
       svg_slider.attr("width", w-play_width); 
      }    

      d3.select(window).on('resize', resize_slider); 

     </script> 
</body> 
</html> 

答えて

0

主な問題は、サイズ変更時にsvg全体ではなくg要素にwidth属性を割り当てることです。 これは、svgとg要素の定義を分割することで解決できます。

var svg = d3.select("#scatterchart_slider").append("svg") 
    .attr("width", w - play_width) 
    .attr("height", height_slider) 
var svg_slider = svg.append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

そして、リサイズ上:

function resize_slider() { 
    w = window.innerWidth - padding; 
    svg.attr("width", w - play_width); 
} 

しかし、あなたは現在の幅に基づいて新しいスケールを構築し、グラフを更新する必要があるため、それは可視化が応答するためにenaughないのSVGの幅を設定します。

あなたのアプローチに従えば、updated fiddleに示されているようにリファクタリングを少しして、サイズ変更時にスライダを再描画する必要があります。 hereのように、純粋なCSSの方法でSVGを反応させるためのいくつかのオプションをチェックすることもできます。

+0

親愛なるデニエラ、あなたの答えに感謝します。 SVG-Updateが動作し、範囲も以下の範囲で動作します。 slider_x.range([0、w-2 *パディング])AND brush.extent([日付値] [現在の日付値]、日付値[現在の日付値]]); 問題:どのように私はスケールラインとラベルを更新できますか? –

+0

私の答えを編集しました。モバイルフレンドリーなラベルを作成するには、幅が小さいときにラベルを回転させることも考えられます。 –

+0

ありがとうございます - それは完璧に動作しています! –

関連する問題