d3缩放/平移行为以毫秒为间隔变化

时间:2014-02-26 19:43:58

标签: javascript d3.js

我正在一个问题域工作,我需要以毫秒的时间间隔显示数据。我发现当你在图表上放大得足够远时,缩放/平移功能的行为会突然改变!如果您使用的是时间刻度,则会在轴开始显示毫秒时发生这种情况。

具体来说,行为改变是d3如何缩放鼠标光标。对于以秒或更高为单位测量的间隔,网格线相对于光标位置进行缩放。鼠标停留在下午6点,滚动将导致下午6点占用更多空间。但是一旦达到毫秒,无论光标位置如何,网格似乎都会从最左边缩放。平移也会停止轴的移动。

我在d3中不是很有经验,但对我来说,这看起来像个bug。我在缩放文档中没有看到任何关于此的内容。是否有这样的原因,如果是这样的话,它可以以某种方式被覆盖吗?

在下面的链接中,只要缩放得足够远以使x轴标签从:YY变为.YYY(即:50到.653),您应该会看到问题。

这显示了“损坏”的行为:http://jsfiddle.net/JonathanPullano/LuYDY/3/

这显示了“正确”行为:http://jsfiddle.net/JonathanPullano/LuYDY/2/

编辑:我发现问题不在于缩放行为,而在于time.scale()本身。我做了另一个小提琴,使用setTimeout自动重新缩放轴而不使用缩放。问题仍然存在。试试吧。

http://jsfiddle.net/JonathanPullano/LuYDY/4/

var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 600 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

var x = d3.time.scale()
    .domain([-5000, 5000])
    .range([0, width]);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("rect")
    .attr("width", width)
    .attr("height", height);

var gXAxis = svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")

function chart(selection) {
    selection.each(function(data) {

        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom")
            .ticks(5)
            .tickSize(-height);

        gXAxis.call(xAxis);
    });
}

update();
function update() {
  var start = new Date(x.domain()[0].getTime() + 10);
  var end = new Date(x.domain()[1].getTime() - 10);
  if(start.getTime() < end.getTime()) {
    x.domain([start,end]);
    setTimeout(update,10);
  }
  svg.call(chart);
}

1 个答案:

答案 0 :(得分:1)

缩放和平移的行为符合预期,但每次都会以不同的值绘制刻度线/网格线,这使得它在开始时看起来不稳定,并且在极端缩放时使其看起来像网格不移动。

我修改了你的小提琴以使用更完整的刻度格式功能,并且每次在同一点(刻度上)绘制一个圆圈:

http://jsfiddle.net/LuYDY/5/

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .ticks(5)
    .tickSize(-height)
    .tickFormat(d3.time.format("%H:%M.%L") );

正如您所看到的,值按预期变焦和平移,但是刻度值总是在窗口上的相同点处间隔,而不是在圆形的毫秒数处。

该错误只是时间尺度的“漂亮”圆形日期时间值的定义在此范围内分崩离析。明确地将比例称为.nice()也不起作用。

时间刻度方法试图找到一个合适的时间单位来选择刻度,当整个域小于1秒时,这种方法不起作用。如果它切换到“好”的线性标度定义(即,舍入到10的倍数),那将是理想的。

即。如果你这样做:

x = d3.time.scale()
    .domain([10, 477])
    .nice();

然后查询x域并将值转换回整数,你仍然得到[10,477]。如果您使用线性刻度执行此操作,则域将舍入为[0,500]。同样,该时间刻度的刻度值放在域的精确分数处,但是放在线性刻度的圆数处。

你可以在github上发出这个问题请求。与此同时,如果您的数据域在毫秒范围内,可能只需使用线性刻度。