在交互式图表中动态缩放数据,其中数据会发生变化



我制作了一个交互式条形图,可以在其中上下拖动条形以调整数据。

当条形拖动到 y 轴域的当前最大值/最小值之外时,y 轴会相应地缩放。但是,我无法让其余的柱线相应地缩放(即:如果我将一根柱线的值增加到一个新的极端,其他柱线应该随着新比例而缩小)

我这里有一个 JS 小提琴,其中包含迄今为止所有有效的内容。

// canvas properties
var margin =
    {
        top: 40,
        bottom: 40,
        right: 30,
        left: 50
    }
var w = 960 - margin.left - margin.right,
    h = 500 - margin.top - margin.bottom;
// initiating axes
var x = d3.scale.ordinal()
        .rangeRoundBands([0, w], 0.1);
var y = d3.scale.linear()
        .range([h, 0]);
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickSize(0)
    .tickPadding(6);
var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");
var zeroline = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickSize(0)
    .tickFormat('')
var svg = d3.select("body").append("svg")
    .attr("width", w + margin.left + margin.right)
    .attr("height", h + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var newValue;    
var data = [
  {name: "A", value: -15},
  {name: "B", value: -20},
  {name: "C", value: -22},
  {name: "D", value: -18},
  {name: "E", value: 2},
  {name: "F", value: 6},
  {name: "G", value: 26},
  {name: "H", value: 18}
];
function type(d)
{
    d.value = +d.value;
    return d;
}
function generateChart(error, data)
{
    /* ========== Parse Data & Create Axes ========== */
     // create a new property called y (needed for d3.events)
    var data = data.map(function (d, i)
    {
        return {
            name: d.name,
            value: d.value,
            y: d.value
        }
    });
    var max = d3.max(data, function (d) { return d.y; });
    var min = -max;
    y.domain([min, max]).nice();
    x.domain(data.map(function (d) { return d.name; }));
    var zz = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (h / 2) + ")")
    .call(zeroline);
    var xx = svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + (h + 20) + ")")
        .call(xAxis);
    var yy = svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);
    /* ========== Drag Behaviour for Rectangles ========== */
    var drag = d3.behavior.drag()
        .on("drag", resize);
    /* ========== Create Rectangles ========== */
    var DataBar = svg.selectAll(".bar")
        .data(data)
        .enter().append("rect")
        .attr("class", function (d) { return "bar bar--" + (d.value < 0 ? "negative" : "positive"); })
        .attr("id", function (d) { return (d.value < 0 ? "negative" : "positive"); })
        .attr("x", function (d) { return x(d.name); })
        .attr("y", function (d) { return y(Math.max(0, d.value)); })
        .attr("width", x.rangeBand())
        .attr("height", function (d) { return Math.abs(y(d.value) - y(0)); })
        .attr("cursor", "ns-resize")
        .call(drag);
    /* ========== Drag Functions ========== */
    function resize(d)
    {
        if (d3.select(this)[0][0].id == 'positive')
        {
            d.y = d3.event.y;
            if (y.invert(d.y) >= 0) // positive -> postive
            {
                var barHeight = -(d.y - y(0));
                var bar = d3.select(this);
                bar.attr("y", function (d) { return d.y; })
                   .attr("height", barHeight)
                   .style("fill", "steelblue");
            }
            else if (y.invert(d.y) < 0) // positive -> negative
            {
                var barHeight = Math.abs((d.y) - y(0))
                var dragy = d3.event.y
                barHeight += dragy - (d.y);
                var bar = d3.select(this)
                bar.attr("height", barHeight)
                   .attr("y", y(0))
                   .style("fill", "darkorange");
            }
            newValue = y.invert(d.y);
        }
        else if (d3.select(this)[0][0].id == 'negative')
        {
            var barHeight = Math.abs(y(d.y) - y(0))
            var dragy = d3.event.y
            if (y.invert(dragy) < 0) // negative -> negative
            {
                barHeight += dragy - y(d.y);
                var bar = d3.select(this)
                bar.attr("height", barHeight)
                   .attr("y", y(0))
                   .style("fill", "darkorange");
            }
            else if (y.invert(dragy) >= 0) // negative -> positive
            {
                var barHeight = -(dragy - y(0));
                var bar = d3.select(this);
                bar.attr("y", function (d) { return dragy; })
                   .attr("height", barHeight)
                   .style("fill", "steelblue");
            }
            //newValue = y.invert(dragy);
        }
        var max = d3.max(data, function (d) { return d.value; });
        var min = -max;
        var update = [];
        if (newValue > max)// || newValue < min)
        {
            y.domain([-newValue, newValue]).nice();
            yy.call(yAxis)
        }
    }    
}
generateChart('error!', data)

(快速说明:y 轴重新缩放目前仅适用于初始蓝条。

if (newValue > max) { ... }块之后添加以下代码块:

var selectedObjectName = d3.select(this).data()[0].name;
svg.selectAll("rect.bar").filter(function (d){
   return (d.name != selectedObjectName);})
   .attr("height", function (d) { return Math.abs(y(d.value) - y(0));})
   .attr("y", function (d) { return y(Math.max(0, d.value)); });

这个想法是选择所有矩形,过滤掉当前选择的矩形,然后重新调整剩余矩形的高度和 y 坐标。小提琴

最新更新