1

我是 D3 的新手,实际上我正在尝试条形图的水平平移选项。我尝试了以下示例,其中水平平移可以完美运行,但我可以看到某些问题。因为我想限制图表中特定范围内存在的数据的平移(不想水平平移到无穷大),请帮助我完成此操作。是否有在线可用的工作示例。谢谢你。

JS代码:

    var data = [
      {"date":"2011-12-31","num":5},
      {"date":"2012-01-05","num":10},
      {"date":"2012-01-10","num":22},
      {"date":"2012-01-15","num":72},
      {"date":"2012-01-20","num":87},
      {"date":"2012-01-25","num":90}
];


function draw(){

    var location = "#post"
    var month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    var graph_width = 500;
    var graph_height = 200;

    var values = _.pluck(data, 'num');
    var max_val = d3.max(values);
    var v_scale = graph_height / max_val;
    var data_counts = data.length;
    var bar_width = graph_width / data_counts;
    var minDate = new Date(data[0]["date"]);
    var maxDate = new Date(data[data.length - 1]["date"]);

    var y = d3.scale.linear()
        .domain([0, max_val])
        .range([graph_height, 0]);

    console.log(minDate);
    var x = d3.time.scale().domain([minDate, maxDate]).range([0, graph_width]);


    var chart = d3.select(location).append("svg")
        .attr("class", "chart")
        .attr("width", graph_width + 20)
        .attr("height", graph_height + 20).
        call(d3.behavior.zoom().x(x).scaleExtent([1, 8]).on("zoom", zoom));

    var lines = chart.selectAll("line");

    var lines_y = lines
        .data(x.ticks(5))
        .enter().append("line")
        .attr("x1", x)
        .attr("x2", x)
        .attr("y1", function(d) {
        return graph_height - 20 - d;})
        .attr("y2", graph_height)
        .style("stroke", "#ccc");

    var lines_x = lines
        .data(y.ticks(10))
        .enter().append("line")
        .attr("x1", 0)
        .attr("x2", graph_width)
        .attr("y1", y)
        .attr("y2", y)
        .style("stroke", "#ccc");

    xAxis = d3.svg.axis().scale(x);
    yAxis = d3.svg.axis().scale(y).orient("left");

    chart.append("svg:g")
        .attr("class", "xaxis")
        .attr("transform", "translate(0,200)")
        .call(xAxis);

    chart.append("svg:g")
        .attr("class", "yaxis")
        .attr("transform", "translate(25,0)")
        .call(yAxis);

    var rect = chart.selectAll("rect")
        .data(data).enter()
        .append("rect")
        .attr("x", function(d, i) {return x(new Date(d["date"])) + 20;})
        .attr("y", function(d, i) {return graph_height - (d["num"] * v_scale);})
        .attr("width", x(new Date(data[1]["date"])))
        .attr("height", function(d, i) {return d["num"] * v_scale;});

    function zoom() {
        chart.select(".xaxis").call(xAxis);
        chart.select(".yaxis").call(yAxis);
        chart.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
    }

    }
draw();
4

2 回答 2

1

Here's a general purpose solution for anyone who needs it. By looking at the range rather than the domain of the X scale, this works with date/time axes too.

var zoom = d3.behavior.zoom()
    .scaleExtent([1,Infinity])
    .on("zoom", function () {
        var t = zoom.translate(),
            max = d3.max(x.range()),
            tx = Math.max( Math.min(0, t[0]), width - max * zoom.scale() );

        zoom.translate([ tx, t[1] ]);

        draw();
    });
于 2014-09-17T09:42:11.053 回答
0

To restrict the panning, simply check the value of the translation before applying it. Note that the translation value will be the inverse of the direction that you're panning in. That is, if you pan in the positive x direction, the translation value for x will be negative.

The code will look something like this.

function zoom() {
    if(d3.event.translate[0] > -100) {
        // translate
    }
}

The actual value (-100 above) will depend on what you actually want. You might want to pass a value in your input domain to restrict the panning to e.g. the edge of the graph.

于 2013-04-08T16:17:17.507 回答