Javascript d3.js时间序列无限滚动

Javascript d3.js时间序列无限滚动,javascript,d3.js,Javascript,D3.js,我正在制作一个时间序列折线图,让用户可以从现在开始向后滚动。我可以找到关于实时d3.js图表的教程,可以找到关于缩放和平移的教程,还可以找到关于使用外部数据源的教程。我很难把这些知识整合起来 以下是我正在寻找的行为: 图表可以在时间上向后平移(意味着线、数据点和轴随着鼠标或手指的拖动而移动) 平移应仅影响x轴,不应进行缩放 当用户平移图表时,会加载更多的数据,从而提供无限滚动的体验 我计划缓冲至少一个额外的“页面”数据,让用户滚动到其中(这部分已经解决了) 我认为我不需要转换,因为图表的平移已

我正在制作一个时间序列折线图,让用户可以从现在开始向后滚动。我可以找到关于实时d3.js图表的教程,可以找到关于缩放和平移的教程,还可以找到关于使用外部数据源的教程。我很难把这些知识整合起来

以下是我正在寻找的行为:

  • 图表可以在时间上向后平移(意味着线、数据点和轴随着鼠标或手指的拖动而移动)
  • 平移应仅影响x轴,不应进行缩放
  • 当用户平移图表时,会加载更多的数据,从而提供无限滚动的体验
  • 我计划缓冲至少一个额外的“页面”数据,让用户滚动到其中(这部分已经解决了)
  • 我认为我不需要转换,因为图表的平移已经可以顺利地转换它了
这就是我迄今为止所做的工作:

  // set up a zoom handler only for panning
  // by limiting the scaleExtent    
  var zoom = d3.behavior.zoom()
  .x(x)
  .y(y)
  .scaleExtent([1, 1])
  .on("zoom", pan);

  var loadedPage = 1; // begin with one page of data loaded
  var nextPage = 2; // next page will be page 2
  var panX = 0;

  function pan() 
  {
     if (d3.event) 
     {
        panX = d3.event ? d3.event.translate[0] : 0;

        // is there a better way to determine when
        // to load the next page?
        nextPage = panX / (width + margin.left + margin.right) + 2;
        nextPage = Math.floor(nextPage);

        // if we haven't loaded in the next page's data
        // load it in so that the user can scroll into it
        if (nextPage > loadedPage) {

          console.log("Load a new page");
          loadedPage += 1;

          // load more data
          Chart.query( /*params will be here*/ ).then(
            function(response) {

              // append the new data onto the front of the array
              data = data.concat(response);
              console.log(data.length);

              // I need to add the new data into the line chart
              // but how do I make that work with the pan
              // logic from zoom?

         }
       );
     }
        // is this where I update the axes and scroll the chart?
        // What's the best way to do that?

      }
    }
在这段代码中,我可以知道何时从服务器提取更多数据,但我不确定如何将数据插入到图表中,以使用平移偏移量。我是使用transform translate,还是可以更新直线路径的d值


欢迎提出任何建议。。。此外,如果有人知道任何演示已经通过时间序列数据显示了无限平移,那将非常感谢。

这太晚了,但回答只是为了万一有人需要再次。我已经为我的散点图准备好了大部分代码,所以上传了。希望对你有帮助。这段代码是在我学习这个特性时创建的。所以使用前请检查

注: 使用缩放行为实现D3js平移, 使用scaleExtent禁用缩放, Y平移限制。 达到x极限时加载的数据。 请检查一下电话号码

//代码在这里
window.chartBuilder={};
(功能(ns){
函数getMargin(){
var保证金={
前20名,
右:15,
底数:60,
左:60
};
变量宽度=960-margin.left-margin.right;
变量高度=500-margin.top-margin.bottom;
返回{
保证金:保证金,
宽度:宽度,
高度:高度
};
}
函数getData(){
风险值数据=[
[5, 3],
[10, 17],
[15, 4],
[2, 8]
];
返回数据;
}
//功能定义范围(数据、宽度、高度){
//var x=d3.scale.linear()
//.domain([0,d3.max(数据,函数(d)){
//返回d[0];
//        })])
//.范围([0,宽度]);
//
//变量y=d3.scale.linear()
//.domain([0,d3.max(数据,函数(d)){
//返回d[1];
//        })])
//.范围([高度,0]);
//返回{x:x,y:y};
//}
函数定义范围(数据、域、范围){
var domainArr=域;
如果(!domain | | domain.length==0){
domainArr=[0,d3.max(数据,函数(d)){
返回d[1];
})];
}
变量y=d3.scale.linear()
.domain(domainArr)
.射程(射程);
返回y;
}
函数定义比例(数据、域、范围){
var domainArr=域;
如果(!domain | | domain.length==0){
domainArr=[d3.min(数据,函数(d)){
返回d[0];
}),d3.max(数据,函数(d){
返回d[0];
})];
}
var x=d3.scale.linear()
.domain(domainArr)
.射程(射程);
返回x;
}
函数getSvg(宽度、边距、高度){
变量图表=d3。选择('主体')
.append('svg:svg')
.attr('width',width+margin.right+margin.left)
.attr('height',height+margin.top+margin.bottom)
.attr(“类别”、“图表”);
收益表;
}
函数getContainerGroup(图表、边距、宽度、高度){
var main=chart.append('g')
.attr('transform','translate('+margin.left+','+margin.top+'))
.attr('width',width)
.attr('height',height)
.attr('class','main');
回水总管;
}
功能渲染x轴(x、主视图、高度){
var xAxis=d3.svg.axis()
.比例(x)
.orient(“底部”);
var xAxisElement=main.select('.x.axis');
if(xAxisElement.empty()){
xAxisElement=main.append('g')
.attr('transform','translate(0',+height+'))
.attr('class','x轴')
}
调用(xAxis);
返回xAxis;
}
功能渲染轴(y,主){
var yAxis=d3.svg.axis()
.比例(y)
.东方(左);
var yAxisElement=main.select('.y.axis');
if(yAxisElement.empty()){
yAxisElement=main.append('g')
.attr('transform','translate(0,0'))
.attr('class','y轴');
}
yAxis元素调用(yAxis);
返回yAxis;
}
功能渲染器散射图(主、数据、比例){
var g=main.append(“svg:g”);
var divTooltip=d3.select('.tooltip1');
if(divTooltip.empty()){
divTooltip=d3。选择('body')。追加('div'))
.attr('class','tooltip1')
.style('opacity',0);
}
g、 选择全部(“散点”)
.数据(数据、功能(d、i){
返回i;
})
.enter().append(“svg:circle”)
.attr(“cx”,函数(d,i){
回归标度.x(d[0]);
})
.attr(“cy”,函数(d){
回归尺度y(d[1]);
})
.on('点击')功能(d){
//log(d.toString());
})
.attr(“r”,8);
}
函数addZoomRect(主、缩放、缩放){
var zoomRect=main.append('rect')
.attr('width',function(){
返回scales.x(d3.max(scales.x.domain());
})
.attr('height',function(){
返回scales.y(d3.min(scales.y.domain());
})
.attr('x',0)
.attr('y',0)
.attr('填充','透明')
.attr('stroke','red');
如果(缩放){
zoomRect.call(缩放);
}
返回zoomRect;
}
功能限制规划(缩放){
var zoomTranslate=this.translate();
this.translate([zoomTranslate[0],0]);
}
功能addXScrollEndEvent(比例,
var pan = d3.behavior.zoom()
    .x(x_scale)
    .scale(scale)
    .size([width, height])
    .scaleExtent([scale, scale])
    .on('zoom', function(e) { ... });
// Apply the behavior
viz.call(pan);

// Now that we've scaled in, find the farthest point that
// we'll allow users to pan forward in time (to the right)
max_translate_x = width - x_scale(new Date(now));
viz.call(pan.translate([max_translate_x, 0]).event);
...
.scaleExtent([scale, scale])
.on('zoom', function(e) {
     var current_domain = x_scale.domain(),
         current_max = current_domain[1].getTime();

     // If we go past the max (i.e. now), reset translate to the max
     if (current_max > now)
        pan.translate([max_translate_x, 0]); 

    // Update the data & points once user hits the point where current data ends
     if (pan.translate()[0] > min_translate_x) {
        updateData();
        addNewPoints();
     }

     // Redraw any components defined by the x axis
     x_axis.call(x_axis_generator);
     circles.attr('cx', function(d) { 
        return x_scale(new Date(d.registered));
     });
});