将滑块添加到条形图以过滤

时间:2017-12-27 16:44:12

标签: d3.js

page.html中

<!DOCTYPE html>
<!-- https://bl.ocks.org/mbostock/3886208 -->
<style>
    #tooltip {
        position: absolute;
        width: 200px;
        height: auto;
        padding: 10px;
        background-color: white;
        -webkit-border-radius: 10px;
        -moz-border-radius: 10px;
        border-radius: 10px;
        -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
        -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
        box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
        pointer-events: none;
    }

    .legend {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        font-size: 60%;
    }

    #tooltip.hidden {
        display: none;
    }

    #tooltip p {
        margin: 0;
        font-family: sans-serif;
        font-size: 16px;
        line-height: 20px;
    }
    g[class="col_1"] rect:hover {
        fill:#80061b;
    }
    g[class="col_2"] rect:hover {
        fill:#008394;
    }
</style>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"></script>
<body>

<div id="tooltip" class="hidden">
    <p><strong>Month: </strong><span id="month"></span><p>
    <p><strong>Value: </strong><span id="count"></span></p>
</div>

<script>
var margin = {top: 20, right: 20, bottom: 50, left: 80},
    width = 1300 - margin.left - margin.right,
    height = 700 - margin.top - margin.bottom;

var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

var g = svg.append("g")
           .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// parse the date / time
// look at the .csv in Notepad! DO NOT LOOK AT EXCEL!
var parseDate = d3.timeParse("%m/%d/%Y");


var x = d3.scaleTime()
          .range([0, width - margin.left - margin.right]);
var y = d3.scaleLinear().range([height, 0]);
var z = d3.scaleOrdinal()
          .range(["#CE1126", "#00B6D0"]); // red and blue 

var xMonthAxis = d3.axisBottom(x)
              .ticks(d3.timeMonth.every(1))
              .tickFormat(d3.timeFormat("%b")); // label every month

var xYearAxis = d3.axisBottom(x)
                  .ticks(d3.timeYear.every(1))
                  .tickFormat(d3.timeFormat("%Y")); // label every year

var yAxis = d3.axisLeft(y).tickFormat(d3.format('.2s'));

var formatNum = d3.format(",")

// load .csv file
d3.csv("test_data.csv", function(d, i, columns) {
  for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
  d.total = t;
  return d;
}, function(error, data){
    if (error) throw error;

    data.forEach(function(d) {
        d.date = parseDate(d.date);
    });

    var keys = data.columns.slice(1);
    var barWidth = (width - margin.right- margin.left)/(data.length+1);     

    data.sort(function(a, b) { return b.date - a.date; });


    x.domain(d3.extent( data, function(d){ return d.date }) );

    var max = x.domain()[1];
    var min = x.domain()[0];
    var datePlusOneMonth = d3.timeDay.offset(d3.timeMonth.offset(max, 1), -1); // last day of current month: move up one month, back one day 

    x.domain([min,datePlusOneMonth]);

    y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
    z.domain(keys);


    // the bars 
    g.append("g")
     .selectAll("g")
     .data(d3.stack().keys(keys)(data))
     .enter().append("g")
     .attr('class', function(d) { return d.key; })
     .attr("fill", function(d) { return z(d.key); })
     .selectAll("rect")
     .data(function(d) { return d; })
     .enter()
     .append("rect")
     .attr("x", function(d) { return x(d.data.date); })
     .attr("y", function(d) { return y(d[1]); })
     .attr("height", function(d) { return y(d[0]) - y(d[1]); })
     .attr("width", barWidth)
     .on("mousemove", function(d) {

        //Get this bar's x/y values, then augment for the tooltip
        var xPosition = parseFloat(d3.mouse(this)[0]) + 88;
        var yPosition = parseFloat(d3.mouse(this)[1]) - 29;
        var value = d.data[d3.select(this.parentNode).attr('class')]; // differentiating between col1 and col2 values

        //Update the tooltip position and value
        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#count")
          .text(formatNum(value)); // return the value 

        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#month")
          .text(d3.timeFormat("%B %Y")(d.data.date)); // return the value 

        //Show the tooltip
        d3.select("#tooltip").classed("hidden", false);

      })
     .on("mouseout", function() {
        //Hide the tooltip
        d3.select("#tooltip").classed("hidden", true);

     });


    // x-axis
    var monthAxis = g.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xMonthAxis);


    const firstDataYear = x.domain()[0];
    xYearAxis.tickValues([firstDataYear].concat(x.ticks()));

    var yearAxis = g.append("g")
                     .attr("class", "axis")
                     .attr("transform", "translate(0," + (height + 25) + ")")
                     .call(xYearAxis);

    var valueAxis = g.append("g")
                 .attr("class", "axis")
                 .call(yAxis);

    monthAxis.selectAll("g").select("text")
      .attr("transform","translate(" + barWidth/2 + ",0)");

    var options = d3.keys(data[0]).filter(function(key) { return key !== "date"; }).reverse();
    var legend = svg.selectAll(".legend")
                    .data(options.slice().filter(function(type){ return type != "total"}))
                    .enter().append("g")
                    .attr("class", "legend")
                    .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

    legend.append("rect")
          .attr("x", width - 18)
          .attr("width", 18)
          .attr("height", 18)
          .style("fill", z);

    function capitalizeFirstLetter(string) {
        return string.charAt(0).toUpperCase() + string.slice(1);
    }

    legend.append("text")
          .attr("x", width - 24)
          .attr("y", 9)
          .attr("dy", ".35em")
          .style("text-anchor", "end")
          .text(function(d) { return capitalizeFirstLetter(d); });

});
</script>

</body>

test_data.csv

date,col_1,col_2
11/1/2012,1977652,1802851
12/1/2012,1128739,948687
1/1/2013,1201944,1514667
2/1/2013,1863148,1834006
3/1/2013,1314851,1906060
4/1/2013,1283943,1978702
5/1/2013,1127964,1195606
6/1/2013,1773254,977214
7/1/2013,1929574,1127450
8/1/2013,1980411,1808161
9/1/2013,1405691,1182788
10/1/2013,1336790,937890
11/1/2013,1851053,1358400
12/1/2013,1472623,1214610
1/1/2014,1155116,1757052
2/1/2014,1571611,1935038
3/1/2014,1898348,1320348
4/1/2014,1444838,1934789
5/1/2014,1235087,950194
6/1/2014,1272040,1580656
7/1/2014,980781,1680164
8/1/2014,1391291,1115999
9/1/2014,1211125,1542148
10/1/2014,1020824,1782795
11/1/2014,1685081,926612
12/1/2014,1469254,1767071
1/1/2015,1168523,935897
2/1/2015,1602610,1450541
3/1/2015,1830278,1354876
4/1/2015,1275158,1412555
5/1/2015,1560961,1839718
6/1/2015,949948,1587130
7/1/2015,1413765,1494446
8/1/2015,1166141,1305105
9/1/2015,958975,1202219
10/1/2015,902696,1023987
11/1/2015,961441,1865628
12/1/2015,1363145,1954046
1/1/2016,1862878,1470741
2/1/2016,1723891,1042760
3/1/2016,1906747,1169012
4/1/2016,1963364,1927063
5/1/2016,1899735,1936915
6/1/2016,1300369,1430697
7/1/2016,1777108,1401210
8/1/2016,1597045,1566763
9/1/2016,1558287,1140057
10/1/2016,1965665,1953595
11/1/2016,1800438,937551
12/1/2016,1689152,1221895
1/1/2017,1607824,1963282
2/1/2017,1878431,1415658
3/1/2017,1730296,1947106
4/1/2017,1956756,1696780
5/1/2017,1746673,1662892
6/1/2017,989702,1537646
7/1/2017,1098812,1592064
8/1/2017,1861973,1892987
9/1/2017,1129596,1406514
10/1/2017,1528632,1725020
11/1/2017,925850,1795575

输出

enter image description here

期望输出

我想在此图片上方插入一个滑块,勾勒出上图中显示的月数,如下所示:

enter image description here

用户需要能够使用滑块选择介于1和24之间的整数月份。应始终显示最近一个月(在本例中为Nov 2017)。滑块将仅显示最近一个月之前的月份数,由滑块中选择的值给出。 (例如,如果从滑块中选择1,图表将只包含Oct 2017Nov 2017。)

我已经尝试过使用https://bl.ocks.org/officeofjane/9b9e606e9876e34385cc4aeab188ed73的代码,但由于以下原因,这并不能满足我的需求:滑块值和数据中的值不一定对应于过滤(即,月数与要过滤的日期之比)。我确实理解了使用滑块使条形图工作所需的基本思路 - 必须使用exitenter选项。

我不需要一个完整的解决方案,但任何有关如何开始这方面的指导都将受到赞赏。

1 个答案:

答案 0 :(得分:2)

好。这是一个带有简单的 jQuery滑块的代码片段(正如我在评论中所建议的那样),过滤掉过去24个月的数据。要显示初始数据,即原始数据,必须将滑块设置为0(无法找到任何其他方法)。您可以使用滑块代码。

&#13;
&#13;
var dataAsCsv = `date,col_1,col_2
11/1/2012,1977652,1802851
12/1/2012,1128739,948687
1/1/2013,1201944,1514667
2/1/2013,1863148,1834006
3/1/2013,1314851,1906060
4/1/2013,1283943,1978702
5/1/2013,1127964,1195606
6/1/2013,1773254,977214
7/1/2013,1929574,1127450
8/1/2013,1980411,1808161
9/1/2013,1405691,1182788
10/1/2013,1336790,937890
11/1/2013,1851053,1358400
12/1/2013,1472623,1214610
1/1/2014,1155116,1757052
2/1/2014,1571611,1935038
3/1/2014,1898348,1320348
4/1/2014,1444838,1934789
5/1/2014,1235087,950194
6/1/2014,1272040,1580656
7/1/2014,980781,1680164
8/1/2014,1391291,1115999
9/1/2014,1211125,1542148
10/1/2014,1020824,1782795
11/1/2014,1685081,926612
12/1/2014,1469254,1767071
1/1/2015,1168523,935897
2/1/2015,1602610,1450541
3/1/2015,1830278,1354876
4/1/2015,1275158,1412555
5/1/2015,1560961,1839718
6/1/2015,949948,1587130
7/1/2015,1413765,1494446
8/1/2015,1166141,1305105
9/1/2015,958975,1202219
10/1/2015,902696,1023987
11/1/2015,961441,1865628
12/1/2015,1363145,1954046
1/1/2016,1862878,1470741
2/1/2016,1723891,1042760
3/1/2016,1906747,1169012
4/1/2016,1963364,1927063
5/1/2016,1899735,1936915
6/1/2016,1300369,1430697
7/1/2016,1777108,1401210
8/1/2016,1597045,1566763
9/1/2016,1558287,1140057
10/1/2016,1965665,1953595
11/1/2016,1800438,937551
12/1/2016,1689152,1221895
1/1/2017,1607824,1963282
2/1/2017,1878431,1415658
3/1/2017,1730296,1947106
4/1/2017,1956756,1696780
5/1/2017,1746673,1662892
6/1/2017,989702,1537646
7/1/2017,1098812,1592064
8/1/2017,1861973,1892987
9/1/2017,1129596,1406514
10/1/2017,1528632,1725020
11/1/2017,925850,1795575`;

// Initialize jQuery slider
$('div#month-slider').slider({
	min: 0,
  max: 24,
  create: function() {
  	// add value to the handle on slider creation
  	$(this).find('.ui-slider-handle').html($( this ).slider( "value" ));
  },
  slide: function(e, ui) {
  	// change values on slider handle and label based on slider value
  	$('div.slider-container span.value').html(ui.value);
		$(e.target).find('.ui-slider-handle').html(ui.value);
    
    // calculate offset date based on slider value
  	var offsetDate = ui.value ? d3.timeMonth.offset(datePlusOneMonth, -ui.value) : min;
    // set x domain and re-render xAxis
		x.domain([offsetDate, datePlusOneMonth]);
    g.select('.x.axis').call(xMonthAxis);
    g.select('.yearaxis.axis').call(xYearAxis);


		// calcuate filtered data based on new offset date, set y axis domain and re-render y axis
    var filteredData = data.filter(function(d) { return d.date >= offsetDate; });
    y.domain([0, d3.max(filteredData, function(d) { return d.total; })]).nice();    
    g.select('.y.axis').transition().duration(200).call(yAxis);
    
    
    // re-render the bars based on new filtered data
    // the bars 
    var bars = g.select("g.bars")
     .selectAll("g")
     .data(d3.stack().keys(keys)(filteredData));

     var barRects = bars.enter().append("g").merge(bars)
     .attr('class', function(d) { return d.key; })
     .attr("fill", function(d) { return z(d.key); })
     .selectAll("rect")
     .data(function(d) { return d; });
     
     barRects.exit().remove();
     
     barRects.enter()
     .append("rect");
     
   barWidth = (width - margin.right- margin.left)/(filteredData.length+1);     

     g.select("g.bars").selectAll('g rect')
     .attr("x", function(d) { return x(d.data.date); })
     .attr("y", function(d) { return y(d[1]); })
     .attr("height", function(d) { return y(d[0]) - y(d[1]); })
     .attr("width", barWidth)
     .on("mousemove", function(d) {

        //Get this bar's x/y values, then augment for the tooltip
        var xPosition = parseFloat(d3.mouse(this)[0]) + 88;
        var yPosition = parseFloat(d3.mouse(this)[1]) - 29;
        var value = d.data[d3.select(this.parentNode).attr('class')]; // differentiating between col1 and col2 values

        //Update the tooltip position and value
        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#count")
          .text(formatNum(value)); // return the value 

        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#month")
          .text(d3.timeFormat("%B %Y")(d.data.date)); // return the value 

        //Show the tooltip
        d3.select("#tooltip").classed("hidden", false);

      })
     .on("mouseout", function() {
        //Hide the tooltip
        d3.select("#tooltip").classed("hidden", true);

     });
  }
})

var margin = {top: 20, right: 20, bottom: 50, left: 80},
    width = 1300 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

var g = svg.append("g")
           .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// parse the date / time
// look at the .csv in Notepad! DO NOT LOOK AT EXCEL!
var parseDate = d3.timeParse("%m/%d/%Y");


var x = d3.scaleTime()
          .range([0, width - margin.left - margin.right]);
var y = d3.scaleLinear().range([height, 0]);
var z = d3.scaleOrdinal()
          .range(["#CE1126", "#00B6D0"]); // red and blue 

var xMonthAxis = d3.axisBottom(x)
              .ticks(d3.timeMonth.every(1))
              .tickFormat(d3.timeFormat("%b")); // label every month

var xYearAxis = d3.axisBottom(x)
                  .ticks(d3.timeMonth.every(6))
                  .tickFormat(d3.timeFormat("%Y")); // label every year

var yAxis = d3.axisLeft(y).tickFormat(d3.format('.2s'));

var formatNum = d3.format(",")

var data = d3.csvParse(dataAsCsv, function(d, i, columns) {
	  for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
  d.total = t;
  return d;
});

data.forEach(function(d) {
  d.date = parseDate(d.date);
});

    var keys = data.columns.slice(1);
    var barWidth = (width - margin.right- margin.left)/(data.length+1);     

    data.sort(function(a, b) { return b.date - a.date; });


    x.domain(d3.extent( data, function(d){ return d.date }) );

    var max = x.domain()[1];
    var min = x.domain()[0];
    var datePlusOneMonth = d3.timeDay.offset(d3.timeMonth.offset(max, 1), -1); // last day of current month: move up one month, back one day 

    x.domain([min,datePlusOneMonth]);

    y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
    z.domain(keys);


    // the bars 
    g.append("g").classed('bars', true)
     .selectAll("g")
     .data(d3.stack().keys(keys)(data))
     .enter().append("g")
     .attr('class', function(d) { return d.key; })
     .attr("fill", function(d) { return z(d.key); })
     .selectAll("rect")
     .data(function(d) { return d; })
     .enter()
     .append("rect")
     .attr("x", function(d) { return x(d.data.date); })
     .attr("y", function(d) { return y(d[1]); })
     .attr("height", function(d) { return y(d[0]) - y(d[1]); })
     .attr("width", barWidth)
     .on("mousemove", function(d) {

        //Get this bar's x/y values, then augment for the tooltip
        var xPosition = parseFloat(d3.mouse(this)[0]) + 88;
        var yPosition = parseFloat(d3.mouse(this)[1]) - 29;
        var value = d.data[d3.select(this.parentNode).attr('class')]; // differentiating between col1 and col2 values

        //Update the tooltip position and value
        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#count")
          .text(formatNum(value)); // return the value 

        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#month")
          .text(d3.timeFormat("%B %Y")(d.data.date)); // return the value 

        //Show the tooltip
        d3.select("#tooltip").classed("hidden", false);

      })
     .on("mouseout", function() {
        //Hide the tooltip
        d3.select("#tooltip").classed("hidden", true);

     });


    // x-axis
    var monthAxis = g.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xMonthAxis);


    const firstDataYear = x.domain()[0];
  //  xYearAxis.tickValues([firstDataYear].concat(x.ticks()));

    var yearAxis = g.append("g")
                     .attr("class", "yearaxis axis")
                     .attr("transform", "translate(0," + (height + 25) + ")")
                     .call(xYearAxis);

    var valueAxis = g.append("g")
                 .attr("class", "y axis")
                 .call(yAxis);

    monthAxis.selectAll("g").select("text")
      .attr("transform","translate(" + barWidth/2 + ",0)");

    var options = d3.keys(data[0]).filter(function(key) { return key !== "date"; }).reverse();
    var legend = svg.selectAll(".legend")
                    .data(options.slice().filter(function(type){ return type != "total"}))
                    .enter().append("g")
                    .attr("class", "legend")
                    .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

    legend.append("rect")
          .attr("x", width - 18)
          .attr("width", 18)
          .attr("height", 18)
          .style("fill", z);

    function capitalizeFirstLetter(string) {
        return string.charAt(0).toUpperCase() + string.slice(1);
    }

    legend.append("text")
          .attr("x", width - 24)
          .attr("y", 9)
          .attr("dy", ".35em")
          .style("text-anchor", "end")
          .text(function(d) { return capitalizeFirstLetter(d); });
&#13;
    #tooltip {
        position: absolute;
        width: 200px;
        z-index: 2;
        height: auto;
        padding: 10px;
        background-color: white;
        -webkit-border-radius: 10px;
        -moz-border-radius: 10px;
        border-radius: 10px;
        -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
        -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
        box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
        pointer-events: none;
    }

    .legend {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        font-size: 60%;
    }

    #tooltip.hidden {
        display: none;
    }

    #tooltip p {
        margin: 0;
        font-family: sans-serif;
        font-size: 16px;
        line-height: 20px;
    }
    g[class="col_1"] rect:hover {
        fill:#80061b;
    }
    g[class="col_2"] rect:hover {
        fill:#008394;
    }
    div.slider-container {
      margin: 20px auto;
    }
    div#month-slider {
      width: 50%;
      margin: 0 auto;
    }
    div#month-slider .ui-slider-handle {
      text-align: center;
    }
&#13;
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">


<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script
  src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
  integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E="
  crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"></script>

<div id="tooltip" class="hidden">
    <p><strong>Month: </strong><span id="month"></span><p>
    <p><strong>Value: </strong><span id="count"></span></p>
</div>

<div class="slider-container">
  <span>Number of months: <span class="value"></span></span>
  <div id="month-slider">

  </div>
</div>
&#13;
&#13;
&#13;

重要的代码更改:

jQuery滑块,min0max24(其中0将显示原始数据,1-24将是最近一次日期(11月17日)的最后一个月的数据

    // Initialize jQuery slider
    $('div#month-slider').slider({
        min: 0,
      max: 24,
      create: function() {
        // add value to the handle on slider creation
        $(this).find('.ui-slider-handle').html($( this ).slider( "value" ));
      },
      slide: function(e, ui) {
        // change values on slider handle and label based on slider value
        $('div.slider-container span.value').html(ui.value);
            $(e.target).find('.ui-slider-handle').html(ui.value);

    // calculate offset date based on slider value
    var offsetDate = ui.value ? d3.timeMonth.offset(datePlusOneMonth, -ui.value) : min;
    // set x domain and re-render xAxis
        x.domain([offsetDate, datePlusOneMonth]);
    g.select('.x.axis').call(xMonthAxis);
    g.select('.yearaxis.axis').call(xYearAxis);


        // calcuate filtered data based on new offset date, set y axis domain and re-render y axis
    var filteredData = data.filter(function(d) { return d.date >= offsetDate; });
    y.domain([0, d3.max(filteredData, function(d) { return d.total; })]).nice();    
    g.select('.y.axis').transition().duration(200).call(yAxis);


    // re-render the bars based on new filtered data
    // the bars 
    var bars = g.select("g.bars")
     .selectAll("g")
     .data(d3.stack().keys(keys)(filteredData));

     var barRects = bars.enter().append("g").merge(bars)
     .attr('class', function(d) { return d.key; })
     .attr("fill", function(d) { return z(d.key); })
     .selectAll("rect")
     .data(function(d) { return d; });

     barRects.exit().remove();

     barRects.enter()
     .append("rect");

     barWidth = (width - margin.right- margin.left)/(filteredData.length+1);     

     g.select("g.bars").selectAll('g rect')
     .attr("x", function(d) { return x(d.data.date); })
     .attr("y", function(d) { return y(d[1]); })
     .attr("height", function(d) { return y(d[0]) - y(d[1]); })
     .attr("width", barWidth)
     .on("mousemove", function(d) {

        //Get this bar's x/y values, then augment for the tooltip
        var xPosition = parseFloat(d3.mouse(this)[0]) + 88;
        var yPosition = parseFloat(d3.mouse(this)[1]) - 29;
        var value = d.data[d3.select(this.parentNode).attr('class')]; // differentiating between col1 and col2 values

        //Update the tooltip position and value
        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#count")
          .text(formatNum(value)); // return the value 

        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")                       
          .select("#month")
          .text(d3.timeFormat("%B %Y")(d.data.date)); // return the value 

        //Show the tooltip
        d3.select("#tooltip").classed("hidden", false);

      })
     .on("mouseout", function() {
        //Hide the tooltip
        d3.select("#tooltip").classed("hidden", true);

     });
     }
    })

<强>详细信息:

  • 根据滑块值使用d3.timeMonth.offset计算偏移日期。
  • 根据此偏移日期过滤掉数据。
  • 使用输入/更新/退出模式重新渲染X轴,Y轴和条形图。 我也添加了评论。

其他变化:

  1. 为轴添加了其他类以区分它们。 X轴:

    .attr("class", "x axis")
    

    X年轴:

    .attr("class", "yearaxis axis")
    

    Y轴:

    .attr("class", "y axis")
    

    在jQuery滑块上添加了一些CSS:

    div.slider-container {
      margin: 20px auto;
    }
    div#month-slider {
      width: 50%;
      margin: 0 auto;
    }
    div#month-slider .ui-slider-handle {
      text-align: center;
    }
    

    z-indexdiv#tooltip。尝试删除它,你就会知道原因。

  2. 如果您有任何疑问,请与我们联系。希望这可以帮助。 :)

      

    修改

    1. 保持所需的刻度线位置:
    2. 计算barWidth后,在滑块中添加以下代码

          monthAxis.selectAll("g").select("text")
            .attr("transform","translate(" + barWidth/2 + ",0)");
      
      1. 保持幻灯片上的年轴标记:
      2. 我花了一段时间才弄明白,但我提出了一种不同于回答here的方法。通过这种方法,尝试从数据中取出几行,您将观察到乱七八糟的碎片。

        因此,在新方法中,tickValues的{​​{1}}计算如下:

        xYearAxis

        即。从 const firstDataYear = x.domain()[0]; var tickValues = x.ticks().filter(function(d) { return !d.getMonth()}); if(firstDataYear.getFullYear() !== tickValues[0].getFullYear()) { tickValues = [firstDataYear].concat(tickValues); } xYearAxis.tickValues(tickValues); 获取所有年份,如果没有,则前置x domain。我发现这是一种更好的方法。

        这是一个演示链接:

        JS FIDDLE DEMO

        如果这解决了问题,请告诉我。