2015-11-24 61 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