D3 Y轴缩放和路径转换

时间:2016-10-06 23:32:42

标签: d3.js

我一直非常密切关注this post有关D3线转换的信息,实现类似于this的内容,除了按时间轴转换。

最终目标是显示实时数据点。

我已定义了轴,如下所示:

var x = d3.time.scale()
    .domain([now - (n - 2) * duration, now - duration])
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0])
    .domain([0, 100])

var axisx = svg.append('g')
    .attr('class', 'x axis')
    .attr('transform', `translate(0, ${height})`)
    .call(x.axis = d3.svg.axis().scale(x).orient('bottom').tickPadding(10));

var axisy = svg.append('g')
    .attr('class', 'y axis')
    .attr('transform', `translate(${width}, 0)`)
    .call(y.axis = d3.svg.axis().scale(y).orient('right').tickPadding(10));

这样的界线如下:

var line = d3.svg.line()
    .interpolate('basis')
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); })
    .y(function(d, i) { return y(d); });

我添加了一个转换函数,就像链接的帖子谈到要在一段时间内水平转换点一样:

(function tick() {

    transition = transition.each(function() {

        // Update the domain of the x-axis
        now = new Date();
        x.domain([now - (n - 2) * duration, now - duration]);

        // Push the new data point
        data.push(temperature);

        // Redraw the line
        svg.select('.line')
            .attr('d', line)
            .attr('transform', null);

        // Slide the x-axis left
        axisx.call(x.axis);

        // Slide the line left
        path.transition()
            .attr('transform', `translate(${x(now - (n - 1) * duration)})`);

        // Pop the old data point off the front
        data.shift();

    }).transition().each('start', tick);
})();

到目前为止,当Y轴域固定时,事情很有效。我想动态调整域的大小和Y轴的标签,所以我在转换函数中添加了以下内容:

y.domain([
    Math.min.apply(Math, data) - 10,
    Math.max.apply(Math, data) + 10
])
axisy.call(y.axis);

并且,虽然y轴刻度似乎正确调整,但每次调用过渡函数时重新绘制线条时会出现这种明显的毛刺效应(不是在每个过渡函数刻度之间):

Chart Redraw Glitch

显然,问题在于我没有动画相位之间线的垂直运动。所以,第一个问题是:D3中有一种简单的方法可以做到这一点吗?

我意识到根据数据的最大值和最小值设置域是一个挑战,因为数据不再一致地转换,它也在缩放。

所以我认为我可能最终不得不接受这样设置域名:

y.domain([temperature - 10, temperature + 10]);

窗户固定的地方。然后我想我将不得不改变转换,以便它具有属性:

.attr('transform', `translate(${x(now - (n - 1) * duration)}, ${y(data[1] - data[0]}))`);

我可以看到此transform会在y上调用关联的line函数,但我不确定如何重新定义它。我试过了:

.y(function(d, i) { return y(d / i); });

但这似乎不起作用。

如何让这些线路转换工作?非常感谢你的帮助,我为这样一个深入而冗长的问题道歉。

Link to full gist of code.

1 个答案:

答案 0 :(得分:0)

编辑:我意识到我的旧方法在许多情况下是不正确的,并删除了示例代码/计算。当我能够弄清楚出了什么问题时,我会更新......

这是一个很酷的问题。链接到(Mike Bostock)的示例只是在X方向上插入平移,以便在更新时平滑地将曲线向左移动。但是,在您的示例中,您想要实时更改Y轴刻度 -

如果我们考虑这一点,就意味着除了将曲线向左移动(通过X方向的平移变换),我们需要将其压缩一点(通过Y方向的尺度变换)。除了在Y方向上缩放之外,还需要将其平移一点以弥补y轴的新位置。

您可以使用[SVG矩阵转换] [1]完成所有这些操作。你只需要弄清楚你的常数是什么(a,b,c,d,e,f)。这些可以使用旧的和新的比例来计算。