Linear string gRaphael outputs values ​​per axis

When drawing a line chart with gRaphael using milliseconds along the x-axis, I usually get inconsistencies when placing data points. Most often, the original data points are to the left of the y-axis (as seen in the scripts below), sometimes the last data point will be behind the right side of the viewport / after the end of the x-axis.

Does anyone know: 1) Why is this happening, 2) How to prevent it, and / or 3) How to check it (I can use transform to move lines / dots if I know when / by how much).

my code:

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 });

      

I need to use gRaphael and the x-axis should be in milliseconds (it is tagged later with date strings with settings)

Basic example fiddle: http://jsfiddle.net/kcar/aNJxf/

Secondary example script (4th example on page often shows both axis errors): http://jsfiddle.net/kcar/saBnT/

The main reason is the snapEnds function (line 718 of g.raphael.js) which rounding occurs, while the penalty in some cases is adding or subtracting years from / to the date in other cases.

Didn't make my way all this way after this point, but since data points are lost every time rounding goes crazy and not when not, I'm going to go ahead and assume that this causes problems with calculating the chart columns as well as before submitting to SnapEnds values ​​are just points to confirm that it is not just getting rendered data.

code for this function from 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 };
},

      

+3


source to share


4 answers


removed the rounded nonsense from snapEnds and didn't get any more problems, didn't notice any flaws with any of the axes or any other area of ​​the chart. If you see him, I would love to hear him.

the code for this function from g.raphael.js:



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

      

+2


source


Hi if you comment on this:

        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);
        }

      



in g.line.js. It seems to solve the problem, and it also solves a similar problem with y-axis values.

+1


source


Upgrading from v0.50 to v0.51 fixed the problem for me.

+1


source


Not sure why this is happening, adding a transparent set was not a desirable option. The simplest way to check if the data that was plotted outside of the graph seems to be getting a bounding box for a set of axes and a bounding box for the data, and checks for the difference between the x and x2 values.

If anyone can help me with scaling the dataset, or figure out how to do it at all, I would still happily appreciate / answer the vote

//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


source







All Articles