D3转换不起作用

时间:2016-01-30 15:06:44

标签: d3.js

我遇到了让数据集之间的转换工作的问题。我希望单击按钮时数字,矩形和名称可以在彼此之间平滑过渡,但目前它们只会跳转。

我正在使用它们

players.select('.saves')
 .transition().duration(200)
 .attr('y', function(d, i) {
         return i * (h / data.length);
 })
 .attr('width', function(d) {
      return Scale(d['saves']) ;});

我的选择有问题吗?

https://jsfiddle.net/8voee4fm/1/

<button class="opts champ" value="championsleague">Champions League</button>
<button class="opts prem" value="premierleague">Premier League</button>

<div id="chart"></div>

var w = 300, h = 300;
var barHeight = 20;

var data = 

championsleague = [{
    "name": "Hart",
    "saves": "9",
    "total": "15",
  }, {
    "name": "Subasic",
    "saves": "6",
    "total": "10"
  }, {
    "name": "Neuer",
    "saves": "5",
    "total": "9"
  },{
    "name": "Olsen",
    "saves": "9",
    "total": "18"
  }, ];

premierleague = [{
  "name": "Hart",
  "saves": "12",
  "total": "27"
}, {
  "name": "Forster",
  "saves": "13",
  "total": "22"
}, {
  "name": "De Gea",
  "saves": "17",
  "total": "29"
}, {
  "name": "Green",
  "saves": "21",
  "total": "39"
},];

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

var canvas = d3.select('#chart')
.append('svg')
.attr('width', w)
.attr('height', h)
.append('g')
.attr("transform", "translate(10,30)");

var Scale = d3.scale.linear().domain([0, 39]).range([0, w]);

function updateLegend(data) {

var players = canvas
 .selectAll(".player")
  .data(data, function(d){
   // always create a unique key for your data-binding
     return d.name + d.saves + d.total;
  });

var playersEnter = players
 .enter()
 .append("g")
 .attr("class", "player");

playersEnter.append('rect')
  .attr('class','total')
  .style("fill", "#abcbc0")
  .attr('x', 0)
  .attr('height',  barHeight);
playersEnter.append('text')
  .attr('class','totaln')
  .style("fill", "black")
  .style("text-anchor", "right");
playersEnter.append('rect')
  .attr('class','saves')
  .style("fill", "#008c6c")
  .attr('x', 0)
  .attr('height',  barHeight);
playersEnter.append('text')
  .attr('class','savesn')
  .style("text-anchor", "right")
  .style("fill", "white");
playersEnter.append('text')
  .attr('class','name')
  .attr('x', 0);

players.select('.total').transition()
  .duration(200)
  .attr('y', function(d, i) {
    return i * (h / data.length)
  })
  .attr('width', function(d) {
        return Scale(d['total']) 
  })
  .attr('height',  barHeight);

players.select('.totaln').transition()
 .duration(200).text(function(d) {
      return d.total;
 })
 .attr('x', function(d) {
      return Scale(d['total']) -20})
 .attr('y', function(d,i) {
       return i * (h / data.length ) +15
 });

players.select('.saves')
 .transition().duration(200)
 .attr('y', function(d, i) {
         return i * (h / data.length);
 })
 .attr('width', function(d) {
      return Scale(d['saves']) ;});

players.select('.savesn')
 .transition()
 .duration(200).text(function(d) {
      return d.saves;
  })
 .attr('x', function(d) {
      return Scale(d['saves']) -18})
 .attr('y', function(d,i) {
        return i * (h / data.length ) +15
 });

  players.select('.name')
    .transition().duration(200)
    .text(function(d) {
      return d.name;
    })
    .attr('y', function(d, i) {
         return i * (h / data.length) -10
    });

 // remove old elements
 players.exit().remove();

};

    updateLegend(data);

    d3.selectAll('.opts')
    .on('click', function() {
    var data = eval(d3.select(this).property('value'));
    console.log(data)
    updateLegend(data);
  })

2 个答案:

答案 0 :(得分:1)

您只需纠正一行代码:

而不是

 var players = canvas
 .selectAll(".player")
  .data(data, function(d){
   // always create a unique key for your data-binding
     return d.name + d.saves + d.total;
  });
你写道:

 var players = canvas
 .selectAll(".player")
  .data(data);

现在它有效。 问题如下:您在输入选择中创建的DOM元素不是有效的SVG元素,因为至少缺少一个属性(例如,rect缺少宽度)。结果,转换创建了对象(来自未指定的SVG对象)。

因此,由于上述原因,您现在除了初始显示之外都有过渡。

这是工作的JSFiddle: https://jsfiddle.net/ee2todev/xjf0k2oy/

答案 1 :(得分:1)

如果您想避免使用 eval(),可以更改点击事件的句柄:

d3.selectAll('.opts')
  .on('click', function() {
    var data = eval(d3.select(this).property('value'));
    console.log(data)
    updateLegend(data);
  })

这样的事情:

d3.selectAll('.opts')
  .on('click', function() {
    var newdata = d3.select(this).property('value');
    newdata = window[newdata];
    console.log(newdata)
    updateLegend(newdata);
  })

(不是真的答案,但我没有足够的评论意见)