Переключатель d3 v4 с сортируемой гистограммой

Попытка передать значение переключателя функции change(), которая сортирует гистограмму.

jsfiddle находится здесь

Сначала у меня есть группа переключателей,

  <form id="form">
    <input type="radio" name="stack" value="val1">val1<br>
    <input type="radio" name="stack" value="val2">val2<br>
    <input type="radio" name="stack" value="val3">val3<br>
  </form>

Я передаю значение из проверенного переключателя в функцию, называемую change(),

  d3.selectAll("input[name='stack']").on("change", change);

Эта функция изменения предназначена для сортировки xAxis,

function change() {
  console.log(this.value); // outputs correctly

  var x0 = x.domain(data.sort(this.value = "val1" ?
        function(a, b) {
          return b.val1 - a.val1;
        } :
        function(a, b) {
          return d3.ascending(a.name, b.name);
        })
      .map(function(d) {
        return d.name;
      }))
    .copy();

  svg.selectAll(".bar")
    .sort(function(a, b) {
      return x0(a.name) - x0(b.name);
    });

  var transition = svg.transition().duration(750),
    delay = function(d, i) {
      return i * 50;
    };

  transition.selectAll(".bar")
    .delay(delay)
    .attr("x", function(d) {
      return x0(d.name);
    });

  transition.select(".x.axis")
    .call(xAxis)
    .selectAll("g")
    .delay(delay);
}

Я получаю сообщение об ошибке

Uncaught TypeError: t.apply is not a function

и ссылаясь на строку

  .call(xAxis)

xAxis создается ранее в коде с помощью

var xAxis = svg.append("g")
  .attr("class", "axis")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x));

Возможно, я неправильно использую тернарный оператор в sort().

Спасибо


person Shane G    schedule 04.08.2017    source источник
comment
Вы можете создать скрипку, в которой будет представлена ​​​​эта проблема?   -  person bumbeishvili    schedule 05.08.2017
comment
jsfiddle jsfiddle.net/ofey/ydg8qs4t/4 спасибо   -  person Shane G    schedule 05.08.2017
comment
Теперь я вижу, что я должен был добавить класс к столбцам .attr('class', 'bar'); а также сортировка по val1 и имени на самом деле не приводит к изменению, поскольку они находятся в том же порядке.   -  person Shane G    schedule 06.08.2017


Ответы (1)


Я понял, как отсортировать эту гистограмму с помощью трех переключателей. Я использую тернарный оператор с форматом if else else.

Также здесь он находится на jsfiddle и Github и gh-pages

<!DOCTYPE html>

<body>
  <div>
    <form id="form">
      <input type="radio" name="stack" value="val1">blue (val1)
      <br>
      <input type="radio" name="stack" value="val2">white (val2)
      <br>
      <input type="radio" name="stack" value="val3">green (val3)
      <br>
    </form>
  </div>
  <div id="bar_chart">
  </div>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script>
    var data = [{
      "name": "A",
      "val1": 10,
      "val2": 6,
      "val3": 1

    }, {
      "name": "B",
      "val1": 8,
      "val2": 7,
      "val3": 3
    }, {
      "name": "C",
      "val1": 9,
      "val2": 5,
      "val3": 4
    }]

    data.forEach(function(d) {
      d.value = +d.value;
    });

    var margin = {
        top: 50,
        right: 50,
        bottom: 100,
        left: 80
      },
      width = 1500 - margin.left - margin.right,
      height = 600 - margin.top - margin.bottom;

    var x = d3.scaleBand()
      .domain(data.map(function(d) {
        return d.name
      }))
      .range([0, width / 4]);

    var y1 = d3.scaleLinear()
      .domain([0, d3.max(data, function(d) {
        return d.val1
      })])
      .range([height, 0]);

    var y2 = d3.scaleLinear()
      .domain([0, d3.max(data, function(d) {
        return d.val2
      })])
      .range([height, 0]);

    var y3 = d3.scaleLinear()
      .domain([0, d3.max(data, function(d) {
        return d.val3
      })])
      .range([height, 0]);

    var svg = d3.select("#bar_chart")
      .data(data)
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var xAxis = d3.axisBottom(x)
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

    // Add the Y Axis
    svg.append("g")
      .attr("class", "axis")
      .call(d3.axisLeft(y1)
        .ticks(7));

    var tooltip = d3.select("#info")
      .append("div")
      .style("position", "absolute")
      .style("z-index", "10")
      .style("visibility", "hidden");

    var rects = svg.selectAll('rect')
      .data(data);

    //********* Bar Chart 1 ****************
    var newRects1 = rects.enter();

    newRects1.append('rect')
      .attr('x', function(d, i) {
        return x(d.name);
      })
      .attr('y', function(d, i) {
        return y1(d.val1);
      })
      .attr('height', function(d, i) {
        return height - y1(d.val1)
      })
      .attr('opacity', 0.85)
      .attr("class", "bar")
      .attr('width', 40)
      .attr("transform", "translate(" + 27 + ",0)")
      .style('fill', 'blue')
      .style('stroke', 'gray')
      .attr('class', 'bar');

    //********* Bar Chart 2 ****************
    var newRects2 = rects.enter();

    newRects2.append('rect')
      .attr('x', function(d, i) {
        return x(d.name);
      })
      .attr('y', function(d, i) {
        return y1(d.val2);
      })
      .attr('height', function(d, i) {
        return height - y1(d.val2)
      })
      .attr('opacity', 0.85)
      .attr('width', 40)
      .attr("transform", "translate(" + 37 + ",0)")
      .style('fill', 'white')
      .style('stroke', 'gray')
      .attr('class', 'bar');

    //********* Bar Chart 3 ****************
    var newRects3 = rects.enter();

    newRects3.append('rect')
      .attr('x', function(d, i) {
        return x(d.name);
      })
      .attr('y', function(d, i) {
        return y1(d.val3);
      })
      .attr('height', function(d, i) {
        return height - y1(d.val3)
      })
      .attr('width', 40)
      .attr('opacity', 0.95)
      .attr("transform", "translate(" + 47 + ",0)")
      .style('fill', 'green')
      .style('stroke', 'gray')
      .attr('class', 'bar');

    d3.selectAll("input[name='stack']").on("change", change);

    function change() {

      var x0 = x.domain(data.sort(this.value == "val1" ?
          (function(a, b) {
            return b.val1 - a.val1;
          }) : ((this.value == "val2") ?
            (function(a, b) {
              return b.val2 - a.val2;
            }) : (function(a, b) {
              return b.val3 - a.val3;
            }))).map(function(d) {
          return d.name;
        }))
        .copy();

      svg.selectAll(".bar")
        .sort(function(a, b) {
          return x0(a.name) - x0(b.name);
        });

      var transition = svg.transition().duration(750),
        delay = function(d, i) {
          return i * 50;
        };

      transition.selectAll(".bar")
        .delay(delay)
        .attr("x", function(d) {
          return x0(d.name);
        });

      transition.select(".x.axis")
        .call(xAxis)
        .selectAll("g")
        .delay(delay);
    }
  </script>
person Shane G    schedule 06.08.2017