Javascript D3悬停图-数千个x条目-鼠标灵敏度
我使用D3创建了以下图表: 资料来源: 这是为了可视化3个变量在上升顺序中的分布,并确定小于或大于1的值 当鼠标悬停时,垂直条会同步3个图表并相应移动。下面代码中的mousemove函数获取特定鼠标坐标对应的x值,然后通过查找可以获取标识符,该标识符允许我将条形图的移动与所有3个图表同步Javascript D3悬停图-数千个x条目-鼠标灵敏度,javascript,d3.js,charts,Javascript,D3.js,Charts,我使用D3创建了以下图表: 资料来源: 这是为了可视化3个变量在上升顺序中的分布,并确定小于或大于1的值 当鼠标悬停时,垂直条会同步3个图表并相应移动。下面代码中的mousemove函数获取特定鼠标坐标对应的x值,然后通过查找可以获取标识符,该标识符允许我将条形图的移动与所有3个图表同步 var xS = d3.scale.linear() .range( [ 0, this.width ] )//width 400 .domain( [1, options.data.length]
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");
};
感谢您的帮助,
谢谢 对,这主要是鼠标分辨率的问题。但是,即使有一个无限敏感的鼠标,你也不会期望人类用户能够如此精确地控制鼠标。用我的鼠标,在屏幕上移动400像素大约等于鼠标垫上的7厘米=70毫米。8800个点,即每毫米125个数据点。太多因此,你必须想出一种与图表交互的替代方法,这将涉及更多的工作 我能想到的最简单的选择是监听文档上的mousemove事件,而不是rect:
d3.select(document) // Maybe "body" is better than document
...
.on("mousemove", mousemove)
然后,您将在整个窗口中获得鼠标值。然后需要将xS的范围定义为
这样,根据浏览器窗口的大小,您可以获得高达4倍的分辨率。显然,鼠标位置与图表上突出显示的位置不对应,但这不一定是问题。问题是,对于8800条记录,鼠标分辨率仍然不足以满足您所要求的精度。注意:我刚刚意识到,在这个方案中,您还需要考虑鼠标的y位置,确定哪个图表与它垂直对齐
另一种方法是使用箭头键或鼠标滚轮从一条记录移动到紧接它之后或之前的一条记录。在这个场景中,您首先读取鼠标位置,就像您当前所做的一样,以查找它产生的任何记录。但是,只要鼠标保持静止,用户就可以使用滚轮或按键调整位置。您的gid查找将如下所示:
gid = dataSets[localName][xValue + refinement]
细化将被初始化为0,但每次按下“向上”或“向下”按钮时,您都会将其递增/递减1。根据建议,我已经实现了键盘方法,允许在X轴上遍历每个条目,代码可在此处找到: 它工作得很好 集成在以下疾病地图平台中:
来源:听起来,0和400点非常接近边缘,基本上不在用于捕获mousemove事件的rect范围内,和/或完全不在SVG范围内。如果是这样,您需要将rect稍微加宽一点,以便它可以捕获x个小于0或>400的坐标,然后使用Math.min/Math.max值将其保持在0到400之间。而且,由于SVG边界会剪裁矩形,因此还需要增加SVG的宽度,以便在其周围引入一些填充。最大的问题是可用的宽度有限。如果我的X宽为400px,但我有8800个条目,并且执行鼠标悬停效果的线条当时只能移动1px,那么如果xS.invertmouseX只能有400个唯一的mouseX坐标值,它怎么能在整个数据集上移动呢?创建建议和注释!非常感谢。我将尝试箭头键方法!再次感谢meetamit提出的尖锐建议,见下文!
xS.range([0, window.innerWidth])
gid = dataSets[localName][xValue + refinement]