1

我想修改这个 jquery 饼图,以便在修改任何一个标签时,更改只发生在下一个标签中。如果下一个标签为 0,则更改应该发生在前一个标签中。如果这也是 0,那么不应该发生任何变化。

现在发生的事情是,如果您对任何标签进行更改;补偿性变化发生在所有标签中。但这没有帮助。因为用户可能想要修复一个标签然后调整其他标签。

请帮忙。

    var nb_sliders = null; // nb of range sliders
var moving_id = null; // id of the moved slider
var oldValue = []; // previous values of the sliders

var radius = 150; // pie chart radius
var color = d3.scale.category20(); // color scheme (10, 20, 20b, 20c ...)
var pi = Math.PI; // 3.14

// pie chart config
var pie = d3.layout.pie()
    .value(function (d) {
    return d.value;
})
//.startAngle(-90 * (pi/180))
//.endAngle(90 * (pi/180))
.sort(null);

// arc object
var arc = d3.svg.arc()
    .outerRadius(radius)
    .innerRadius(radius / 2);

// nb sliders event
d3.select('#nbFormSubmit').on('click', function () {
    d3.event.preventDefault();
    nb_sliders = d3.select('#nbSliders')[0][0].value;
    init();
});

// initialize the sliders, events and pie chart
function init() {
    oldValue = [];
    moving_id = null;

    d3.select('#rangebox tbody').html('');

    // append sliders to table
    for (i = 0; i < nb_sliders; i++) {
        var tr = d3.select('#rangebox tbody').append('tr');
        tr.append('td')
            .attr('class', 'edit')
            .attr('contenteditable', true)
            .text('Label ' + (i + 1));
        tr.append('td')
            .append('input')
            .attr('type', 'range')
            .attr('data-id', i)
            .attr('class', 'range')
            .attr('step', 1)
            .attr('min', 0)
            .attr('max', 100);
        tr.append('td')
            .attr('class', 'range_value');
    }

    d3.selectAll('#rangebox .range').each(function () {
        var def = parseInt(100 / nb_sliders);
        this.value = def;
        oldValue[d3.select(this).attr('data-id')] = this.value;
    });

    equalize();
    showValues();
    pieChart();

    // content edit event
    d3.selectAll('.edit').on('input', function () {
        updateLabels();
    });

    // slider event
    d3.selectAll('.range').on('change', function () {
        this.value = parseInt(this.value);
        if (this.value < 0) this.value = 0;
        else if (this.value > 100) this.value = 100;

        var id = d3.select(this).attr('data-id');
        moving_id = id;

        var old_value = oldValue[moving_id];
        var new_value = this.value;
        var delta = (new_value - old_value) / (nb_sliders - 1);

        d3.selectAll('#rangebox .range').each(function () {
            var r_id = d3.select(this).attr('data-id');
            var r_val = this.value;
            if (r_id != moving_id && r_val > delta) {
                var equalized = parseInt(r_val - delta);
                this.value = equalized;
                oldValue[r_id] = this.value;
            }
        });

        oldValue[moving_id] = new_value;

        equalize();
        showValues();
        updatePieChart();
    });
}

// get JSON data from sliders
function getData() {
    var json = [];
    d3.selectAll('#rangebox .range').each(function () {

        json.push({
            label: d3.select(this.parentNode.parentNode)
                .select('td:first-child')
                .text(),
            value: this.value
        });
    });
    return json;
}

// compute total percentage from sliders
function getTotal() {
    var total = 0;
    d3.selectAll('#rangebox .range').each(function () {
        total = total + parseInt(this.value);
    });
    return total;
}

// equalize the sliders (decimal delta)
function equalize() {
    var remaining = 100 - getTotal();

    if (remaining != 0) {
        var to_eq = null;
        var min = null;
        var max = null;
        var min_value = 9999;
        var max_value = 0;

        console.log(remaining);

        d3.selectAll('#rangebox .range').each(function () {
            var id = d3.select(this).attr('data-id');

            if (id != moving_id) {
                if (parseInt(this.value) > parseInt(max_value)) {
                    max_value = this.value;
                    max = this;
                }
                if (parseInt(this.value) < parseInt(min_value)) {
                    min_value = this.value;
                    min = this;
                }
            }
        });

        if (remaining > 0) to_eq = min;
        else to_eq = max;

        if (to_eq) {
            if (remaining > 0) {
                to_eq.value = parseInt(to_eq.value) + 1;
                remaining = remaining - 1;
            } else {
                to_eq.value = parseInt(to_eq.value) - 1;
                remaining = remaining + 1;
            }
            oldValue[d3.select(to_eq).attr('data-id')] = to_eq.value;

            if (remaining != 0) equalize();
        }
    }
}

// show slider value
function showValues() {
    d3.selectAll('#rangebox .range').each(function () {
        var perct = this.value + '%';
        d3.select(this.parentNode.nextSibling).html(perct);
    });
}

// draw pie chart
function pieChart() {
    var json = getData();

    d3.select("#pie svg").remove();

    // svg canvas
    var svg = d3.select("#pie")
        .append("svg:svg")
        .attr("width", radius * 2)
        .attr("height", radius * 2)
        .append("svg:g")
        .attr("transform", "translate(" + radius + "," + radius + ")");

    // slices
    var arcs = svg.selectAll("path").data(pie(getData()))

    // render the slices
    arcs.enter()
        .append('svg:path')
        .attr("fill", function (d, i) {
        return color(i);
    })
        .attr("d", arc)
        .each(function (d) {
        this._current = d;
    })
        .append('title')
        .text(function (d, i) {
        return json[i].value + '%';
    });

    // render the labels
    arcs.enter()
        .append("svg:text")
        .attr("transform", function (d) {
        return "translate(" + arc.centroid(d) + ")";
    })
        .attr("text-anchor", "middle")
        .text(function (d, i) {
        if (json[i].value > 1) return json[i].label;
        else return null;
    });
}

// update pie chart
function updatePieChart() {
    updateArcs();
    updateLabels();
}

// update the slices of the pie chart
function updateArcs() {
    var json = getData();

    d3.selectAll("#pie path title")
        .text(function (d, i) {
        return json[i].value + '%';
    });

    d3.selectAll("#pie path")
        .data(pie(json))
        .transition()
        .duration(700)
        .attrTween('d', arcTween);
}

// update the labels of the pie chart
function updateLabels() {
    d3.selectAll("#pie text")
        .data(pie(getData()))
        .transition()
        .duration(700)
        .attr("transform", function (d) {
        return "translate(" + arc.centroid(d) + ")";
    })
        .text(function (d, i) {
        if (getData()[i].value > 0) return getData()[i].label;
        else return null;
    });
}

// transition for the arcs
function arcTween(a) {
    var i = d3.interpolate(this._current, a);
    this._current = i(0);
    return function (t) {
        return arc(i(t));
    };
}
4

0 回答 0