D3悬停图表 - 数千个x条目 - 鼠标灵敏度

时间:2014-09-16 15:27:46

标签: javascript d3.js charts

我使用D3创建了以下图表: chart http://envhealthatlas.co.uk/bow_tie_like_chart.png

这是以上升顺序显示3个变量的分布,并识别低于和大于1的值。

垂直条同步3个图表并在鼠标悬停时相应移动。下面代码中的mousemove函数获取对应于特定鼠标坐标的x值,然后从查找中我可以获得标识符,这允许我将条形移动与所有3个图表同步。

 var xS = d3.scale.linear()
  .range( [ 0, this.width ] )//width 400
  .domain( [1,  options.data.length]); 

var yS = d3.scale.linear()
  .range( [ this.height, 0 ] )
  .domain( [ 0, this.maxDataPoint ] );


var linename =  this.name + "_line";


this.area = d3.svg.area()
  //.interpolate( "monotone" )
  .x( function( d ) {
    return xS( +d[xOrder] );
  } )
  .y0( function( d ) {
    if ( d[ localName ] < 1 ) {
      return yS( d[ localName ] );
    } else {
      return yS( 1 )
    }

  } )
  .y1( function( d ) {
    if ( d[ localName ] < 1 ) {
      return yS( 1 );
    } else {
      return yS( d[ localName ] )
    }
  } );


this.chartContainer = svg.append( "g" )
  .attr( 'class', this.name.toLowerCase() )
  .attr( "transform", "translate(" + this.margin.left + "," + ( this.margin.top + ( this.height * this.id ) + ( 10 * this.id ) ) + ")" );

/* We've created everything, let's actually add it to the page */
this.chartContainer.append( "path" )
  .data( [ options.data ] )
  .attr( "class", "chart unadj " + this.name.toLowerCase() )
  .attr( "clip-path", "url(#clip-" + this.id + ")" )
  .attr( "d", this.area );


var mousemove = function( d ) {

    var xValue = Math.round(xS.invert(d3.mouse(this)[0])) ,
        gid = null;

    var update = function( xVal , txt, set ){
        lines[set]
          .attr("transform","translate(" + xS(xVal) + "," + 0 + ")");
        texts[set]
          .text( txt );
    };

    if( typeof dataSets[localName][xValue] !== 'undefined'){
        gid =  dataSets[localName][xValue]["gid"];// Sync with other area charts
    };      

    for (var set in dataSets){ 
        var dataLength = dataSets[set].length ;
        while(dataLength--){
            if(dataSets[set][dataLength]["gid"] === gid){
                var xVal =  +dataSets[set][dataLength][xOrder],// xOrder is an auto increment field used for sync purpose and for the xs linear scale
                    yVal = dataSets[set][dataLength][set];
                update(xVal, yVal, set);  
            };      
        };
    };  
};

this.chartContainer.append( "rect" )
    .attr( "class", "overlayHover" )
    .attr( "width", width)
    .attr( "height", chartHeight )
    .on( "mousemove", mousemove );

/* Highlighter */
lines[localName] = this.chartContainer.append("line")
    .attr("class", "lineHover")
    .attr("x1", 0)
    .attr("y1", 0)
    .attr("x2", 0)
    .attr("y2", chartHeight)
    .attr("height", 2 )
    .attr("height", chartHeight )
    .attr("id", linename );


this.yAxis = d3.svg.axis().scale( yS ).orient( "left" ).tickValues( [ 0, 1, this.maxDataPoint ]);

this.chartContainer.append( "g" )
  .attr( "class", "y axis" )
  .attr( "transform", "translate(0,0)" )
  .call( this.yAxis );

this.chartContainer.append( "text" )
  .attr( "class", "country-title" )
  .attr( "transform", "translate(10,20)" )
  .text( this.name  );

texts[localName] = this.chartContainer.append( "text" )
  .attr( "class","areaValue")
  .attr ( "id", localName + "_text"  )
  .attr( "transform", "translate(10,32)" )
  .text("0.00");    

};

问题: 图表看起来表现不错,但是通过使用我的当前数据集和几千条记录,我意识到某些值永远不会显示。例如,如果我将鼠标悬停在图表的最左侧或最右侧(最低或最高),我无法将鼠标坐标设置为0.00和400(图表宽度),因此无法获得数据集的极值。

可用宽度和x条目数量是否存在问题?

数据如下所示我有大约9000条记录:

gid,rr_unadj,x_order
948,0.751,1
947,0.751,2
6728,0.762,3
950,0.768,4

任何帮助表示赞赏, 谢谢!

2 个答案:

答案 0 :(得分:0)

对,这主要是鼠标分辨率的问题。但即使使用无限敏感的鼠标,您也不会期望人类用户能够如此精确地控制鼠标。使用我的鼠标,在屏幕上移动400像素等于鼠标垫上约7厘米(= 70毫米)。有8800点,即每毫米约125个数据点。太多了。所以你必须想出一种与图表互动的替代方式,它将涉及更多的工作。

我能想到的最简单的选择是在文档而不是rect上监听mousemove事件:

d3.select(document) // Maybe "body" is better than document
  ...
  .on("mousemove", mousemove)

然后,您将在整个窗口中获取鼠标值。然后,您需要将xS的范围定义为

xS.range([0, window.innerWidth])

这样,根据浏览器窗口大小,您可以获得高达4倍的分辨率。显然,鼠标位置不会与图表上突出显示的位置相对应,但这不一定是个问题。 的问题在于,对于8800条记录,它仍然不足以满足您要求的精度。 (注意:我刚刚意识到,使用此方案,您还需要考虑鼠标y位置,确定哪个图表垂直对齐。)

另一种方法是使用箭头键或鼠标滚轮从一个记录移动到紧跟在其之后或之前的记录。在这种情况下,您首先要像现在一样读取鼠标位置,以查找它产生的任何记录。但是,只要鼠标保持静止,用户就可以使用滚轮或键来改善该位置。您的gid查找将如下所示:

gid =  dataSets[localName][xValue + refinement]

refinement将初始化为0,但每次按下向上或向下,您都会将其递增/递减1.

答案 1 :(得分:0)

根据建议,我已经实现了键盘方法,它允许遍历X轴中的每个条目,代码可以在这里找到: https://github.com/smallAreaHealthStatisticsUnit/rapidInquiryFacility/blob/master/rifWebPlatform/web/js/v2/components/chart/units/d3renderers/multipleAreaCharts.d3renderer.js

效果很好。

集成在下面的疾病制图平台中: disease mapping http://www.envhealthatlas.co.uk/disease_mapping.png