Javascript 响应D3平滑滑块-在调整窗口大小时更改滑块宽度

Javascript 响应D3平滑滑块-在调整窗口大小时更改滑块宽度,javascript,d3.js,Javascript,D3.js,我正在开发一个响应D3滑块,它只允许定义日期值-如果我不改变窗口大小,滑块就会工作。问题是:如果窗口大小更改,我的函数resize_slider()不会调整滑块大小。有什么想法吗?改变滑块宽度的最佳方法是什么 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script type="text/javascript" src=

我正在开发一个响应D3滑块,它只允许定义日期值-如果我不改变窗口大小,滑块就会工作。问题是:如果窗口大小更改,我的函数resize_slider()不会调整滑块大小。有什么想法吗?改变滑块宽度的最佳方法是什么

<!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>

.axis\u滑块.domain{
填充:无;
行程:#000;
笔划不透明度:.3;
笔划宽度:10px;
笔划线头:圆形;
}
.axis_滑块.halo{
填充:无;
行程:#ddd;
笔划宽度:8px;
笔划线头:圆形;
}
.处理{
填充:#fff;
行程:#000;
笔画不透明度:.5;
笔划宽度:1.25px;
指针事件:无;
}
var日期_值=[];
日期_值[0]=新日期(2016,9,31);
日期_值[1]=新日期(2016,10,30);
日期_值[2]=新日期(2016,11,30);
日期_值[3]=新日期(2017,0,31);
var当前值=日期值。长度-1;
var play_width=50;
var=50;
var w=window.innerWidth-填充;
var margin={top:0,right:padding*2,bottom:300,left:padding*2},
高度_滑块=100;
var slider_plays=false;
var slider\u play\u newstart=false;
var slider_x=d3.time.scale()
.domain([date\u values[0],date\u values[date\u values.length-1])
.范围([0,w-4*填充])
.夹具(正确);
var brush=d3.svg.brush()
.x(滑块x)
.on(“刷子”,刷子)
.on(“刷端”,刷端);
var svg_slider=d3。选择(“散点图_slider”)。追加(“svg”)
.attr(“宽度”,w-play\u宽度)
.attr(“高度”,高度\滑块)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
svg_slider.append(“g”)
.attr(“类”、“x轴\ U滑块”)
.attr(“变换”、“平移(0“+高度\滑块/2+”))
.call(d3.svg.axis()
.刻度(滑块x)
.tick值(日期值)
.orient(“底部”)
.tickFormat(d3.time.format(“%b%Y”))
.1(12))
.select(“.domain”)
.select(函数(){返回this.parentNode.appendChild(this.cloneNode(true));})
.attr(“类别”、“光环”);
var slider=svg_slider.append(“g”)
.attr(“类”、“滑块”)
.打电话(刷子);
滑块。选择全部(“.extent,.resize”)
.remove();
滑块。选择(“.background”)
.attr(“高度”,高度/滑块);
变量句柄=slider.append(“圆”)
.attr(“类”、“句柄”)
.attr(“变换”、“平移(0“+高度\滑块/2+”))
.attr(“r”,9);
滑块
.call(画笔.extent([date_值[当前日期值],日期值[当前日期值]))
.呼叫(刷子、事件);
函数brushed(){
var值=brush.extent()[0];
if(d3.event.sourceEvent){
值=滑块x.反转(d3.鼠标(此)[0]);
范围([值,值]);
}
handle.attr(“cx”,slider_x(value));
}
函数brushend(){
如果(!d3.event.sourceEvent){
return;//仅在输入后转换
}
var值=brush.extent()[0];
范围([值,值]);
d3.选择(本)
.transition()
.呼叫(刷子、事件);
函数getRoundedDate_ID(d){
最近的\u日期\u编号=0

对于(var i=1;i来说,主要的问题是,在调整大小时,将width属性指定给g元素,而不是整个svg。 您可以通过拆分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);
}
但是设置svg的宽度并不能使可视化响应,因为您必须基于当前宽度构建新的比例并更新图形


按照您的方法,您需要进行一些重构,如中所示,以便在调整大小时重新绘制滑块。您还可以检查一些其他选项,以使SVG以纯CSS方式响应,如图所示。

亲爱的Deniela,感谢您的回答。SVG更新和范围可以使用:slider_x.range([0,w-2*填充])和brush.extent([日期值[当前日期值],日期值[当前日期值]);问题:有什么想法可以更新刻度线和标签吗?编辑了我的答案。为了使标签便于移动,您还可以考虑在宽度较小时旋转标签。还有一个问题:更新的小提琴会将滑块重置为第一个值。我想在删除HTML(d3.select)后会调用brushed函数(“#scatterchart_slider”).html(“”),因此控制台中出现以下错误:错误:属性cx:预期长度,“NaN”。