2015-11-24 40 views
2

我试图使用this方法来获取最接近的y值,对于当前鼠标位置处的x值。D3 scale.invert()不是x的返回日期

我的数据集是这样的:

linedata = [{amount:100,date:'2015-11-2'}, 
      {amount:-1000,date:'2015-11-3'}, 
      {amount:5000,date:'2015-11-4'} 
      ... 
      ] 

我有绘制精细的线图,而我只是如何scale.invert()和工作平分玩。 创建平分功能:

var bisectDate = d3.bisector(function(d) { return d.date; }).left; 

然后,再往下,绘制图形之后,还有我把在那里的图形绘制

graph.append("rect") 
     .attr("class", "overlay") 
     .attr("width", w) 
     .attr("height", h) 
     .on("mouseover", function() { focus.style("display", null); }) 
     .on("mouseout", function() { focus.style("display", "none"); }) 
     .on("mousemove", mousemove); 

然后mousemove()功能区域的矩形定义像这样:

function mousemove() { 
    var xPosition = xScale.invert(d3.mouse(this)[0]), //<-- give me the date at the x mouse position 
     closestElement = bisectDate(linedata, xPosition, 1), //<-- use the bisector to search the array for the closest point to the left and find that point given our mouse position 
     d0 = linedata[closestElement - 1] 
     d1 = linedata[closestElement], 
     d = xPosition - d0.date > d1.date - xPosition ? d1 : d0; 
    focus.attr("transform", "translate(" + xScale(+line_dateFormat.parse(d.date)) + "," + yScale(d.amount) + ")"); 
    focus.select("text").text(d.amount); 
}; 

我遇到的问题是,这条线在mouseover()功能:

var xPosition = xScale.invert(d3.mouse(this)[0]) 

不返回日期,它返回一个数字,如矩形的像素宽度。下一行,平分线,不能这个数字比较的日期,所以最终总是为1。

我期待xPosition是要么日期是这样的:

Sat Jul 19 2014 09:32:43 GMT+1000 (AEST) 
Sat Jul 19 2014 07:28:21 GMT+1000 (AEST) 
Sat Jul 19 2014 05:24:00 GMT+1000 (AEST) 
Sat Jul 19 2014 03:50:43 GMT+1000 (AEST) 
Fri Jul 18 2014 22:39:49 GMT+1000 (AEST) 
Fri Jul 18 2014 14:53:27 GMT+1000 (AEST) 

或像这样:

1446382800000 
1446382800000 
1446382800000 
1446382800000 

,但我发现这样的东西:

531.190359375 
472.78146093749996 
408.8622890625 
358.1677734375 
333.92257031249994 

Obviou狡猾,我做错了,但我不明白为什么的基本原理。任何人都可以向我解释为什么即时获取数字而不是日期?

+1

您从示例中更改了哪些内容?它在那里工作,所以它一定是你改变了的东西。 –

+0

我的数据结构与示例不同。在这个例子中它是一个tsv文件。我以上面提到的形式将变量传递给模板。同样在此示例中,此处声明比例: var x = d3.time.scale() .range([0,width]); var y = d3.scale.linear() .range([height,0]); 以及后来添加的域: x.domain(...); y.domain(...); 而在我的我这一切在一个 变种xScale等= d3.time.scale() \t \t。域(...) \t \t .range([0,W]); VAR yScale = d3.scale.linear() \t \t。域([amount_min,amount_max]) \t \t .range([H,0]) \t \t .nice(); – Sebastian

+0

您能否提供一个完整的示例,以便重现此问题? –

回答

1

使用方法Nithin CV Poyyil建议确定执行器的输出为了解决这个问题,我必须做2件事。

1 - 在我的后端应用程序中,将日期从字符串'2015-11-02'转换为纪元时间(以毫秒为单位),然后将其发送到d3.js使用的视图。这使得它更容易处理,可能应该从现在开始一直这样做直到永远。

2 - 即时通讯不好在JavaScript和不理解范围。所以我只是集中(和复制)所需的所有功能集成到鼠标悬停功能是这样的:

function mousemove() { 
    var xScale = d3.time.scale() 
    .domain([d3.min(linedata, function(d) { return d.date; }), d3.max(linedata, function(d) { return d.date; })]) 
    .range([0, w + 170]); 

    var yScale = d3.scale.linear() 
    .domain([amount_min, amount_max]) 
    .range([h, 0]) 
    .nice(); 

    var bisectDate = d3.bisector(function(d) { return d.date; }).left; 
    var dateFormat = d3.time.format('%d. %b') 

    var xPosition = xScale.invert(d3.mouse(this)[0]),//xScale.invert(d3.mouse(this)[0]), //<-- give me the date at the x mouse position 
     closestElement = bisectDate(linedata, xPosition, 1), //<-- use the bisector to search the array for the closest point to the left and find that point given our mouse position 
     d0 = linedata[closestElement - 1], 
     d1 = linedata[closestElement], 
     d = xPosition - d0.date > d1.date - xPosition ? d1 : d0; 

    focus.attr("transform", "translate(" + xScale(d.date) + "," + yScale(d.amount) + ")"); 
    focus.select("text").text("Amount: " + d.amount + " Date: " + d.date); 
}; 

不是“正确”的方式做到这一点,但我得到我想要的结果和多数民众对我来说更重要。谢谢您的帮助!

1

希望这可以帮助你,

检查使用 d3.time规模的xScale等功能是否正确写入。

测试xScale等功能通过在给定的该范围内传递任何日期值。 eg : xScale(new Date("01-01-1998")),结果必须在您给出的 范围内。

测试返回值xScale.invert(0 or 1)结果必须是日期 在您给定的域中的值。

基于博斯托克的链接会为您提供,下面给出代码工作为我好,

var width=500; 
var xAxisScale = d3.time.scale().range([0, width]); 
xAxisScale.domain([new Date("01-01-2014"),new Date("01-01-2015")]); 
var rangeValue=xAxisScale(new Date("01-05-2014")) 
var dateDomainValue=xAxisScale.invert(15); 
console.log(rangeValue,dateDomainValue); 

var mousemove=function(d){ 
var xPosition = xAxisScale.invert(d3.mouse(this)[0]) 
console.log("mousemove:",xPosition) 
}; 

d3.selectAll("svg").append("rect") 
     .attr("class", "overlay") 
     .attr("width", 200) 
     .attr("height", 300) 
     .style("fill","gray") 
     .on("mouseover", function() { console.log("mouseover") }) 
     .on("mouseout", function() { console.log("mouseout"); }) 
     .on("mousemove", mousemove); 

HTML:

<svg width="500" height="500"></svg> 

输出:

mouseover 
mousemove: Sun Jan 05 2014 09:07:12 GMT+0530 (India Standard Time) 
mousemove: Sun May 25 2014 12:57:36 GMT+0530 (India Standard Time) 
mousemove: Wed May 21 2014 03:50:24 GMT+0530 (India Standard Time) 
mouseout 
+0

如果将域与缩放声明放在一起,它是否有所作为? – Sebastian

+0

当我做到这一点: '函数鼠标移动(){ \t变种rangeValue = 91.611450389948 \t变种dateDomainValue = xScale.invert(rangeValue); \t var aaandAgain = xScale(dateDomainValue); \t console.log(rangeValue,dateDomainValue,aaandAgain); }' 我得到这个: '91.611450389948 89.5664668873093 91.611450389948' 为什么'xScale.invert()时,我用它在函数内部'行不通? – Sebastian

+0

它可以工作,否则,如果不在函数中: 'var rangeValue = 91.611450389948 var dateDomainValue = xScale.invert(rangeValue); var aaandAgain = xScale(dateDomainValue); 的console.log(rangeValue,dateDomainValue,aaandAgain);' 给出正确的: '91.611450389948太阳2015年12月13日18点50分32秒GMT + 1100(AEDT)91.61145037294973' – Sebastian