D3甜甜圈图,负(逆时针)和正(顺时针)(角度是动态的)

时间:2018-10-30 11:51:03

标签: javascript d3.js

我得到一个JSON查询,我想在同一张图中呈现一个正(红色)和负(黑色)段。正数是JSON中的第一个数字,负数是第二个数字。

var dataset = {
    numbers: [3200, 5400, 8600]
};

var width = 960,
  height = 500,
  radius = Math.min(width, height) / 2;

var enterClockwise = {
    startAngle: 0,
    endAngle: 0
};

var enterAntiClockwise = {
    startAngle: Math.PI * 2,
    endAngle: Math.PI * 2
};

//var color = d3.scale.category20();
var color = d3.scale.ordinal().range([d3.rgb("#c7003b"), d3.rgb('#000'), d3.rgb('#ccc'),d3.rgb('transparent')])

var pie = d3.layout.pie()
  .sort(null);

var arc = d3.svg.arc()
  .innerRadius(radius - 80)
  .outerRadius(radius - 40);
  
var arcThin = d3.svg.arc()
  .innerRadius(radius - 65)
  .outerRadius(radius - 55);

var svg = d3.select('#Donut-chart').append('svg')
     .attr('id', 'Donut-chart-render')
     .attr("width", '100%')
     .attr("height", '100%')
     .attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
     .attr('preserveAspectRatio', 'xMinYMin')

  
var path = svg.selectAll("path")
  .data(pie(dataset.numbers))
  .enter().append("path")
    .attr("fill", function (d, i) { return color(i); })
    .attr("d", function(d){
      	return arc(enterClockwise);
    })
    .each(function (d) {
        this._current = {
            data: d.data,
            value: d.value,
            startAngle: enterClockwise.startAngle,
            endAngle: enterClockwise.endAngle
        } 
    });

path.transition()
    .duration(750)
    .attrTween("d", arcTween);

function createChart() {
    path = path.data(pie(dataset[this.value]));
    path.enter().append("path")
        .attr("fill", function (d, i) {
            return color(i);
        })
        .attr("d", arc(enterAntiClockwise))
        .each(function (d) {
            this._current = {
                data: d.data,
                value: d.value,
                startAngle: enterAntiClockwise.startAngle,
                endAngle: enterAntiClockwise.endAngle
            };
        });

}

function arcTween(a, j) {
    var i = d3.interpolate(this._current, a);
    this._current = i(0);
    return function (t) {
        return (j === (dataset.numbers.length - 1)) ? arcThin(i(t)) : arc(i(t));
    };
}

/*
function arcTweenOut(a, j) {
    var i = d3.interpolate(this._current, { startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0 });
    this._current = i(0);
    return function (t) {
        console.log(j === dataset.length - 1)
        return arc(i(t));
    };
}
*/

function type(d) {
    d.value = +d.value;
    return d;
}

createChart(dataset);
@import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla,sans-serif;margin:auto;position:relative}.text{text-anchor:middle;color:#000;font-size:1.7em;font-weight:700;text-transform:uppercase}#legend{align-items:center;border-radius:5px;display:flex;height:0%;justify-content:space-around;width:95%;font-size:25px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>

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

因此,基本上我希望它看起来像这样: enter image description here

正数将从顺时针的点0开始,负数将从相同的点但逆时针开始。

我有一个使用以下方法的想法:

.each(function (d, i=0) {
    console.log(i);
    i++;
    if(i == 1){
      this._current = {
          data: d.data,
          value: d.value,
          startAngle: enterAntiClockwise.startAngle,
          endAngle: enterAntiClockwise.endAngle
      } 
    }
    else{
      this._current = {
          data: d.data,
          value: d.value,
          startAngle: enterClockwise.startAngle,
          endAngle: enterClockwise.endAngle
      } 
    }

});

那没有用。

1 个答案:

答案 0 :(得分:0)

最简单的解决方案是在添加路径之前对数据进行操作。

var angleData = pie(dataset.numbers);
angleData[1].startAngle = 0;
angleData[1].endAngle = -angleData[1].endAngle + angleData[0].endAngle; // finding the clockwise angle
angleData[2].startAngle = angleData[0].endAngle; // shifting position of third arc
angleData[2].endAngle = (2*Math.PI) + angleData[1].endAngle;

var dataset = {
    numbers: [3200, 5400, 8600]
};

var width = 960,
  height = 500,
  radius = Math.min(width, height) / 2;

var enterClockwise = {
    startAngle: 0,
    endAngle: 0
};

var enterAntiClockwise = {
    startAngle: Math.PI * 2,
    endAngle: Math.PI * 2
};

//var color = d3.scale.category20();
var color = d3.scale.ordinal().range([d3.rgb("#c7003b"), d3.rgb('#000'), d3.rgb('#ccc'),d3.rgb('transparent')])

var pie = d3.layout.pie()
  .sort(null);

var arc = d3.svg.arc()
  .innerRadius(radius - 80)
  .outerRadius(radius - 40);
  
var arcThin = d3.svg.arc()
  .innerRadius(radius - 65)
  .outerRadius(radius - 55);

var svg = d3.select('#Donut-chart').append('svg')
     .attr('id', 'Donut-chart-render')
     .attr("width", '100%')
     .attr("height", '100%')
     .attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
     .attr('preserveAspectRatio', 'xMinYMin').append("g").attr("class", "parent");

var angleData = pie(dataset.numbers);
angleData[1].startAngle = 0;
angleData[1].endAngle = -angleData[1].endAngle + angleData[0].endAngle;
angleData[2].startAngle = angleData[0].endAngle;
angleData[2].endAngle = (2*Math.PI) + angleData[1].endAngle;
	 
var path = svg.selectAll("path")
  .data(angleData)
  .enter().append("path")
    .attr("fill", function (d, i) { return color(i); })
    .attr("d", function(d){
      	return arc(enterClockwise);
    })
    .each(function (d) {
        this._current = {
            data: d.data,
            value: d.value,
            startAngle: enterClockwise.startAngle,
            endAngle: enterClockwise.endAngle
        } 
    });

path.transition()
    .duration(750)
    .attrTween("d", arcTween);


	
function createChart() {
    path = path.data(pie(dataset[this.value]));
    path.enter().append("path")
        .attr("fill", function (d, i) {
            return color(i);
        })
        .attr("d", arc(enterAntiClockwise))
        .each(function (d) {
            this._current = {
                data: d.data,
                value: d.value,
                startAngle: enterAntiClockwise.startAngle,
                endAngle: enterAntiClockwise.endAngle
            };
        });

}

function arcTween(a, j) {
    var i = d3.interpolate(this._current, a);
    this._current = i(0);
    return function (t) {
        return (j === (dataset.numbers.length - 1)) ? arcThin(i(t)) : arc(i(t));
    };
}

/*
function arcTweenOut(a, j) {
    var i = d3.interpolate(this._current, { startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0 });
    this._current = i(0);
    return function (t) {
        console.log(j === dataset.length - 1)
        return arc(i(t));
    };
}
*/

function type(d) {
    d.value = +d.value;
    return d;
}
@import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla,sans-serif;margin:auto;position:relative}.text{text-anchor:middle;color:#000;font-size:1.7em;font-weight:700;text-transform:uppercase}#legend{align-items:center;border-radius:5px;display:flex;height:0%;justify-content:space-around;width:95%;font-size:25px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>

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