简体   繁体   中英

jQuery slider not working on d3 multiples, but not returning error either

I'm trying to add a jQuery range slider to the main chart on a page that contains small multiples of area charts, but the slider does not slide, and the charts do not transition. I'm using the code from this block as a guide for how to implement such a slider.

Here's a link to my (semi-working) Plunker: https://plnkr.co/edit/zwCBQ1wR3iBlGYCMYqFe?p=preview

I thought this should be simple, since I've already set up the means for dynamically configuring the x-axis, depending on the data, with the following code:

var startDate = d3.time.month.offset(new Date(), -108); 
var endDate = new Date ();                              
var dates = createDatesArr(startDate, endDate);
...
var area = d3.svg.area()
.x(function(d) {
return xScale(d.x);
...
xScale.domain([
    d3.min(dates, function(d) {
        return d;
    }),
    d3.max(dates, function(d) {
            return d;
        })
    ]);

    var totals = [];

    for (i = 0; i < dates.length; i++) {
        totals[i] = 0;
        for (j = 0; j < dataset.length; j++) {
            totals[i] += dataset[j].values[i].y;
        }
    }

The code that seems to be problematic with the jQuery slider I've added is this:

  function zoom(begin, end) {
    xScale.domain([begin, end - 1]);
    yScale.domain([begin, end - 1]);

    var t = state.transition().duration(0);         

    var size = end - begin;
    var step = size / 10;

    t.select('.path').attr("d", function(d) {
                return area(d.values);
            });
  }
...
  $(function() {
        $( "#slider-range" ).slider({
            range: true,
            min: 0,
            max: dataset.length-1,
            values: [ 0, dataset.length-1 ],
            slide: function( event, ui ) {
              var begin = d3.min([ui.values[0], dataset.length]);
              var end = d3.max([ui.values[1], 0]);
              console.log("begin:", begin, "end:", end);

              zoom(begin, end);
            }
        });
    }); 

Here, again, is a link to a (semi-working) Plunker: https://plnkr.co/edit/zwCBQ1wR3iBlGYCMYqFe?p=preview

From reading similar questions about sliders, it seems the general recommendation is to use brush/zoom to implement focus + context, as in this block , but doing so is beyond my abilities at this point. (Though I'd love to see it demonstrated.)

What I'm trying to do is implement some means of graphically (eg by means of a slider or brush) adjusting the x-axis/date range of the main chart, and its small multiples, such that they are zoomed or redrawn when the slider is moved. As it stands, the slider doesn't slide, the charts do not zoom or redraw, and the browser returns no error messages. Can you demonstrate a solution?

Here you go buddy! Plunker

Made a lot of changes to the code. Here is a diff-check of our codes:

Code Difference

Relevant changes:

function rerenderAreaChart(selectedState, dataset, svgHook, size, begin, end) {
  var totalTicksX = Math.round(size.w / 60),
    totalTicksY = Math.round(size.h / 40);

  xAxis.ticks(totalTicksX);
  yAxis.ticks(totalTicksY);

  yScale.range([padding.top, size.h - padding.bottom]);

  xScale.domain([begin, end]);

  var filtered_indices = [];
  dataset[0].values.forEach(function(k, i) {
    if (k.x >= begin && k.x <= end) {
      filtered_indices.push(i);
    }
  });
  var max = d3.max(filtered_indices, function(idx) {
    return d3.sum(dataset, function(d) {
      return d.values[idx].y;
    })
  });
  yScale.domain([max, 0]);

  d3.select(svgHook).select('svg.state.' + selectedState).select('.x.axis')
    .transition().duration(50).call(xAxis).selectAll(".tick text")
    .call(wrap, 0);

  d3.select(svgHook).select('svg.state.' + selectedState).select('.y.axis')
    .transition().duration(50).call(yAxis);

  dataset.forEach(function(d) {
    d.values.forEach(function(v, idx) {
      v.hidden = filtered_indices.indexOf(idx) === -1;
    })
  });
  stack(dataset);

  d3.select(svgHook).select('svg.state.' + selectedState).select('g.paths').selectAll("path")
    .attr("clip-path", "url(#clip)")
    .attr('d', function(d) {
      return area(d.values.filter(function(k) {
        return k.x >= begin && k.x <= end;
      }));
    });
}

Take a look at the jQuery slider too. I've missed commenting the code which I'll do soon and update the link. Please go through the code and let me know if find any bugs or anything that isn't understandable.

And I'm sorry for the delay as I lost all the code once (didn't save it), had to rewrite it today.

One thing I would like you to make note of is it's better to use "style" instead of "attr" (attribute) for stylings such as "fill", "stroke" etc. I've changed those too.

Hope this helps. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM