使用特定颜色更新饼图未按预期工作

Updating Pie Chart with Specific colors not working as expected

看这个fiddle(http://jsfiddle.net/gs6rehnx/2106/),有四种不同颜色的四个圆弧。我希望饼图在单击更新按钮后具有三种颜色。但是,仍然有四个弧。我想,specific 颜色到 values 的映射不能正常工作?还是其他东西不起作用?

const chart = {};
const duration = 750;
const width = 160;
const height = 160;

const min = Math.min(width, height);
const oRadius = min / 2 * 0.9;
const iRadius = min / 2.5 * 0.85;

const pie = d3
  .pie()
  .value(function(d) {
    return d.value;
  })
  .sort(null);

const arc = d3
  .arc()
  .outerRadius(oRadius)
  .innerRadius(iRadius);

function arcTween(a) {
  const i = d3.interpolate(this._current, a);
  this._current = i(0);
  return function(t) {
    return arc(i(t));
  };
};

const labels = ['1', '2', '3', '4'];
const color = ["rgba(126,211,33,1)", "rgba(39,173,232,1)", "rgba(229,5,1,1)", "rgba(245,166,35,1)"];

const scale = d3.scaleOrdinal()
  .domain(labels)
  .range(color);

const create = function(data) {
  const svg = d3
    .select('.foo')
    .append('svg')
    .attr('class', 'pie')
    .attr('width', width)
    .attr('height', height)
    .attr('id', 'svgClass');

  svg
    .append('g')
    .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
    .attr('id', 'bar');

  draw(data);
}

const draw = function(data) {
  const path = d3.select('#bar')
    .selectAll('path')
    .data(pie(data))

  path
    .enter()
    .append('g')
    .append('path')
    .attr('d', arc)
    .attr('fill', (d, i) => {
      return scale(d.data.name)
    });

  path
    .transition()
    .duration(duration)
    .attrTween('d', function(d) {
      const interpolate = d3.interpolate({
        startAngle: 0,
        endAngle: 0
      }, d);
      return function(t) {
        return arc(interpolate(t));
      };
    });
};

const data = [{
  "name": "1",
  "value": 2
}, {
  "name": "2",
  "value": 1
}, {
  "name": "3",
  "value": 2
}, {
  "name": "4",
  "value": 1
}];

const newData = [{
  "name": "1",
  "value": 2
}, {
  "name": "2",
  "value": 1
}, {
  "name": "3",
  "value": 2
}];

function createPie() {
  create(data)
}

function updatePie() {
  draw(newData)
}
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
    
<button type="button" onclick="createPie()">Click Me First!</button>
<button type="button" onclick="updatePie()">Update Diagram!</button>
<div class='foo'></div>

这不起作用的原因是因为 d3 有三个主要部分可供选择:

  • 输入
  • 更新
  • 退出

在上面的示例中,您处理的是 enterupdate 不太正确,exit 完全缺失。这是作者讨论 data joins.

的一篇非常好的文章

输入

以下获取所有 new 数据元素,并为每个元素添加一个新的 g 元素。

path.enter().append('g')

退出

您遗漏的以下内容将获取 DOM 中不再出现在数据中的所有项目,并将其删除。

path.exit().remove();

const chart = {};
const duration = 750;
const width = 160;
const height = 160;

const min = Math.min(width, height);
const oRadius = min / 2 * 0.9;
const iRadius = min / 2.5 * 0.85;

const pie = d3
  .pie()
  .value(function(d) {
    return d.value;
  })
  .sort(null);

const arc = d3
  .arc()
  .outerRadius(oRadius)
  .innerRadius(iRadius);

function arcTween(a) {
  const i = d3.interpolate(this._current, a);
  this._current = i(0);
  return function(t) {
    return arc(i(t));
  };
};

const labels = ['1', '2', '3', '4'];
const color = ["rgba(126,211,33,1)", "rgba(39,173,232,1)", "rgba(229,5,1,1)", "rgba(245,166,35,1)"];

const scale = d3.scaleOrdinal()
  .domain(labels)
  .range(color);

const create = function(data) {
  const svg = d3
    .select('.foo')
    .append('svg')
    .attr('class', 'pie')
    .attr('width', width)
    .attr('height', height)
    .attr('id', 'svgClass');

  svg
    .append('g')
    .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
    .attr('id', 'bar');

  draw(data);
}

const draw = function(data) {
  const path = d3.select('#bar')
    .selectAll('path')
    .data(pie(data))

  path
    .enter()
    .append('g')
    .append('path')
    .attr('d', arc)
    .attr('fill', (d, i) => {
      return scale(d.data.name)
    });
    
  path.exit().remove();

  path
    .transition()
    .duration(duration)
    .attrTween('d', function(d) {
      const interpolate = d3.interpolate({
        startAngle: 0,
        endAngle: 0
      }, d);
      return function(t) {
        return arc(interpolate(t));
      };
    });
};

const data = [{
  "name": "1",
  "value": 2
}, {
  "name": "2",
  "value": 1
}, {
  "name": "3",
  "value": 2
}, {
  "name": "4",
  "value": 1
}];

const newData = [{
  "name": "1",
  "value": 2
}, {
  "name": "2",
  "value": 1
}, {
  "name": "3",
  "value": 2
}];

function createPie() {
  create(data)
}

function updatePie() {
  draw(newData)
}
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
    
<button type="button" onclick="createPie()">Click Me First!</button>
<button type="button" onclick="updatePie()">Update Diagram!</button>
<div class='foo'></div>