2013-02-04 36 views
3

使用沿着x軸的毫秒繪製線條圖時,我通常會發現數據點位置不一致。最常見的是,初始數據點位於y軸的左側(如下圖所示),有時最後的數據點將超出視圖框的右側/超過x軸的終點。gRaphael線形圖繪製超出軸的值

有誰知道: 1)爲什麼發生這種情況, 2)如何防止它,& /或 3)如何檢查它(我可以用變換來移動線/分,如果我知道它的時候發生了多少)。

我的代碼:

var r = Raphael("holder"), 
txtattr = { font: "12px sans-serif" }; 
var r2 = Raphael("holder2"), 
txtattr2 = { font: "12px sans-serif" }; 

var x = [], y = [], y2 = [], y3 = []; 

for (var i = 0; i < 1e6; i++) { 
    x[i] = i * 10; 
    y[i] = (y[i - 1] || 0) + (Math.random() * 7) - 3; 
} 
var demoX = [[1, 2, 3, 4, 5, 6, 7],[3.5, 4.5, 5.5, 6.5, 7, 8]]; 
var demoY = [[12, 32, 23, 15, 17, 27, 22], [10, 20, 30, 25, 15, 28]]; 

var xVals = [1288885800000, 1289929440000, 1290094500000, 1290439560000, 1300721700000, 1359499228000, 1359499308000, 1359499372000]; 
var yVals = [80, 76, 70, 74, 74, 78, 77, 72]; 
var xVals2 = [1288885800000, 1289929440000]; 
var yVals2 = [80, 76]; 

var lines = r.linechart(10, 10, 300, 220, xVals, yVals, { nostroke: false, axis: "0 0 1 1", symbol: "circle", smooth: true }) 
.hoverColumn(function() { 
    this.tags = r.set(); 

    for (var i = 0, ii = this.y.length; i < ii; i++) { 
     this.tags.push(r.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{ fill: "#fff" }, { fill: this.symbols[i].attr("fill") }])); 
     } 
    }, function() { 
     this.tags && this.tags.remove(); 
     }); 

lines.symbols.attr({ r: 3 }); 


var lines2 = r2.linechart(10, 10, 300, 220, xVals2, yVals2, { nostroke: false, axis: "0 0 1 1", symbol: "circle", smooth: true }) 
.hoverColumn(function() { 
    this.tags = r2.set(); 

    for (var i = 0, ii = this.y.length; i < ii; i++) { 
     this.tags.push(r.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{ fill: "#fff" }, { fill: this.symbols[i].attr("fill") }])); 
     } 
    }, function() { 
     this.tags && this.tags.remove(); 
     }); 

lines2.symbols.attr({ r: 3 }); 

我必須使用gRaphael與x軸必須是在毫秒(這是後來用W /定製日期字符串)

主要的例子小提琴:http://jsfiddle.net/kcar/aNJxf/

二次例如小提琴(頁面上第四示例頻繁顯示兩個軸錯誤): http://jsfiddle.net/kcar/saBnT/

根本原因是snapEnds函數(第718行g.raphael.js),它在四捨五入的情況下(儘管在某些情況下罰款)會在其他情況下對日期加上或減去年份。

在這一點之後,還沒有一路走過,但是由於數據點在每次四捨五入變得瘋狂時都放錯了位置,而不是在沒有時,我會繼續前進並假設這導致了問題計算圖表列,在發送到snapEnds之前,這些值僅用於確認其不僅僅是接收錯誤計算的數據。從g.raphael.js

snapEnds: function(from, to, steps) { 
    var f = from, 
     t = to; 

    if (f == t) { 
     return {from: f, to: t, power: 0}; 
    } 

    function round(a) { 
     return Math.abs(a - .5) < .25 ? ~~(a) + .5 : Math.round(a); 
    } 

    var d = (t - f)/steps, 
     r = ~~(d), 
     R = r, 
     i = 0; 

    if (r) { 
     while (R) { 
      i--; 
      R = ~~(d * Math.pow(10, i))/Math.pow(10, i); 
     } 

     i ++; 
    } else { 
     if(d == 0 || !isFinite(d)) { 
      i = 1; 
     } else { 
      while (!r) { 
       i = i || 1; 
       r = ~~(d * Math.pow(10, i))/Math.pow(10, i); 
       i++; 
      } 
     } 

     i && i--; 
    } 

    t = round(to * Math.pow(10, i))/Math.pow(10, i); 

    if (t < to) { 
     t = round((to + .5) * Math.pow(10, i))/Math.pow(10, i); 
    } 

    f = round((from - (i > 0 ? 0 : .5)) * Math.pow(10, i))/Math.pow(10, i); 
    return { from: f, to: t, power: i }; 
}, 
+0

如果我將毫秒數轉換爲小時數,但這些錯誤大部分都會被消除(它們仍然會出現的差不多),但在我的情況下,這仍然不是很理想,但可以作爲快速解決其他人遇到同樣問題的方法。 – kcar

+0

只需要指出來自Epoch的毫秒數/小時 – kcar

+0

在調查這一點時,似乎有些時候它的線路比例關閉了(有時線路太長,所以第一個和最後一個點超出了它們應該在的位置,有時線太短),有時候只是定位。對於我的生活,我不知道爲什麼相同的數據/代碼會導致完全不同的錯誤。 – kcar

回答

2

刪除舍入謬論snapEnds和沒有更多的問題,沒有發現任何軸或圖表的任何其他領域的任何缺點。如果你看到一個,我很樂意聽到它。現在

代碼g.raphael.js該功能:

snapEnds: function(from, to, steps) { 
    return {from: from, to: to, power: 0};  
}, 
0

仍然不知道爲什麼它發生時,在透明的集合添加該功能的

碼並不是一個理想的選擇。 檢查數據點是否在圖的外部呈現的最簡單方法似乎是獲取軸集的邊界框和數據點的邊界框,並檢查x和x2值之間的差異。

如果有人能幫助我與縮放數據點集,或找出如何使這根本不會發生,我仍然會高興地欣賞/向上投票結果

//assuming datapoints is the Raphael Set for the datapoints, axes is the 
//Raphael Set for the axis, and datalines is the Raphael Set for the 
//datapoint lines 
var pointsBBox = datapoints.getBBox(); 
var axesBBox = axes.getBBox(); 
var xGapLeft = Math.ceil(axesBBox.x - pointsBBox.x); 
//rounding up to integer to simplify, and the extra boost from y-axis doesn't 
//hurt, <1 is a negligible distance in transform 
var xGapRight = Math.ceil(axesBBox.x2 - pointsBBox.x2); 
var xGap = 0; 
if(xGapLeft > 0){ 
    datapoints.transform('t' +xGapLeft +',0'); 
    datalines.transform('t' +xGapLeft +',0'); 
    xGap = xGapLeft; 
}else if (xGapRight < 0) { //using else if because if it is a scale issue it will 
//be too far right & too far left, meaning both are true and using transform will 
//just shift it right then left and you are worse off than before, using 
//set.transform(scale) works great on dataline but when using on datapoints scales 
// symbol radius not placement 
    if (xGapLeft < 0 && xGapRight < xGapLeft) { xGapRight = xGapLeft; } 
//in this case the initial point is right of y-axis, the end point is right of 
//x-axis termination, and the difference between last point/axis is greater than 
//difference between first point/axis 

    datapoints.transform('t' +xGapRight +',0'); 
    datalines.transform('t' +xGapRight +',0'); 
    xGap = xGapRight; 
} 
rehookHoverOverEvent(xGap); //there are so many ways to do this just leaving it 
//here as a call to do so, if you don't the hover tags will be over the original 
//datapoints instead of the new location, at least they were in my case. 
+0

我會誠實地說,我並不真正關心這個修復,因爲它沒有解決根本問題,並且如果行太長或太短(縮放問題)不起作用,但它是一個爲我工作的樂隊援助,並可能爲別人工作,但這就是爲什麼我沒有選擇它作爲「接受的答案」。 – kcar

1

你好,如果你對此有何評論此:

 if (valuesy[i].length > width - 2 * gutter) { 
      valuesy[i] = shrink(valuesy[i], width - 2 * gutter); 
      len = width - 2 * gutter; 
     } 

     if (valuesx[i] && valuesx[i].length > width - 2 * gutter) { 
      valuesx[i] = shrink(valuesx[i], width - 2 * gutter); 
     } 
在g.line.js

,這似乎解決問題,並且它還解決了與y軸上的值類似的問題。

+0

感謝您的建議,從g.raphael.js註釋掉snapEnds函數的主體似乎已經做到了,3個月後我沒有注意到這樣做的任何負面影響 – kcar

1

從v0.50升級到v0.51解決了我的問題。

+0

很遺憾,我已經在0.51上了,但是我知道這個問題的幾個不同的修復建議在g.raphael git上,所以我猜這個修復程序正在自己工作。 – kcar