代码之家  ›  专栏  ›  技术社区  ›  Datacrawler

在D3甜甜圈图表中添加更细的弧线

  •  1
  • Datacrawler  · 技术社区  · 6 年前

    var dataset = [
        {positive: 20, negative: 40 ,total: 100}
      ];
    

    我想用一个类似于这样的油炸圈饼图来表示数据:

    enter image description here

    积极的 20/100 , 40/100 剩下的都是 total-negative-positive 哪个是 100-40-20 = 60 在这种情况下。

    这是非常有效的,但我希望它在一个D3图表:

    Chart.types.Doughnut.extend({
        name: "DoughnutAlt",
        initialize: function (data) {
            Chart.types.Doughnut.prototype.initialize.apply(this, arguments);
    
            // save the actual clear method
            var originalClear = this.clear;
            // override the clear method to draw the background after each clear
            this.clear = function () {
                originalClear.apply(this, arguments)
    
                var ctx = this.chart.ctx;
                // use any one of the segments to get the inner and outer radius and center x and y
                var firstSegment = this.segments[0];
                // adjust 0.3 to increaase / decrease the width of the background
                var gap = (firstSegment.outerRadius - firstSegment.innerRadius) * (1 - 0.3) / 2;
    
                ctx.save();
                ctx.fillStyle = "#EEE";
                ctx.beginPath();
                ctx.arc(firstSegment.x, firstSegment.y, firstSegment.outerRadius - gap, 0, 2 * Math.PI);
                ctx.arc(firstSegment.x, firstSegment.y, firstSegment.innerRadius + gap, 0, 2 * Math.PI, true);
                ctx.closePath();
                ctx.fill();
                ctx.restore();
            }
        }
    });
    
    
    var pointsUsed = [
        {
            value: 20,
            color: "#c7003b",
        },
        {
            value: 40,
            color: "#000",
        },    
        {
            value: 60,
            color: "transparent",
        },
    ];
    
    var pointsUsed_ctx = document.getElementById("pointsUsed").getContext("2d");
    
    var pointsUsed = new Chart(pointsUsed_ctx).DoughnutAlt(pointsUsed, {
        segmentShowStroke: false,
        segmentStrokeWidth: 0,
        percentageInnerCutout: 87,
        showTooltips: false,
        animationEasing: 'easeInOutCubic',
        responsive: true
    });
    <script src="https://rawgit.com/nnnick/Chart.js/v1.0.2/Chart.min.js"></script>
    <canvas id="pointsUsed" height="200" width="200"></canvas>

    所以,我使用了一个响应的d3图表来呈现这个,我调整了数据集,以便包含总数。我想做的是使未使用部分的弧(总-正-负)有一个更薄的弧。

    var dataset = {
        numbers: [20, 40, 40]
    };
    
    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 - 100)
      .outerRadius(radius - 20);
    
    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", 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);
    
    
    
    var timeout = setTimeout(function () {
        d3.select("input[value=\"oranges\"]").property("checked", true).each(change);
    }, 2000);
    
    function createChart() {
        clearTimeout(timeout);
        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
                };
            }); // store the initial values
    
        path.exit()
            .transition()
            .duration(750)
            .attrTween('d', arcTweenOut)
            .remove() // now remove the exiting arcs
    
        path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
    }
    
    function arcTween(a) {
        var i = d3.interpolate(this._current, a);
        this._current = i(0);
        return function (t) {
            return arc(i(t));
        };
    }
    function arcTweenOut(a) {
        var i = d3.interpolate(this._current, { startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0 });
        this._current = i(0);
        return function (t) {
            return arc(i(t));
        };
    }
    
    
    function type(d) {
        d.value = +d.value;
        return d;
    }
    
    createChart(dataset);
    body {
            margin: auto;
            position: relative;
        }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
    <div id="Donut-chart"></div>
    1 回复  |  直到 6 年前
        1
  •  0
  •   Mark    6 年前

    var dataset = {
        numbers: [20, 40, 40]
    };
    
    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 - 100)
      .outerRadius(radius - 20);
      
    var arcThin = d3.svg.arc()
      .innerRadius(radius - 80)
      .outerRadius(radius - 40);
    
    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,i){
          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);
    
    
    
    var timeout = setTimeout(function () {
        d3.select("input[value=\"oranges\"]").property("checked", true).each(change);
    }, 2000);
    
    function createChart() {
        clearTimeout(timeout);
        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
                };
            }); // store the initial values
    
        path.exit()
            .transition()
            .duration(750)
            .attrTween('d', arcTweenOut)
            .remove() // now remove the exiting arcs
    
        path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
    }
    
    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);
    body {
            margin: auto;
            position: relative;
        }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
    <div id="Donut-chart"></div>