Обновление круговой диаграммы определенными цветами не работает должным образом - PullRequest
0 голосов
/ 16 октября 2018

Глядя на эту скрипку (http://jsfiddle.net/gs6rehnx/2106/),, есть четыре дуги с четырьмя разными цветами. Я ожидаю, что круговая диаграмма будет иметь три цвета после нажатия кнопки обновления. Однако, есть еще четыре дуги.отображение определенных цветов на 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>

1 Ответ

0 голосов
/ 16 октября 2018

Причина, по которой это не работает, заключается в том, что d3 состоит из трех основных частей:

  • введите
  • обновите
  • выйдите

В приведенном выше примере вы имеете дело с enter, update не совсем правильно, а exit полностью отсутствует.Это действительно хорошая статья автора, в которой обсуждается присоединение данных .

Enter

Ниже приводятся все элементы данных 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>
...