DmitryBaranovskiy / g.raphael

Charts for Raphaël
http://g.raphaeljs.com/
1.52k stars 435 forks source link

Unexpected axis scale when using the dotcharts. #195

Open jeppo74 opened 10 years ago

jeppo74 commented 10 years ago

Most of the time the axis of the dotchart is limited by the most extreme datapoints in your chart. However I provide two examples where the scale on the axis is not as expected. One example shows that the axis sometimes have a larger span than the most extreme datapoints. In the other example the chart is misleading because datapoints are not correctly aligned to the axis. This example should be easy to paste into a new webpage.

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<meta charset="utf-8" />
<title>Bug in dotchart?</title>
<script src="./dotchart_example_files/raphael.js"></script>
<script src="./dotchart_example_files/g.raphael.js"></script>
<script src="./dotchart_example_files/g.dot.js"></script>
<script>

function DrawAll() {

//First parameters are the same for all charts
var offsetX = 10;
var offsetY = 10;
var width = 300;
var height = 300;
var values = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var axisx = ["", "", "", "", "", "", "", "", "", "", ""];
var axisy = ["", "", "", "", "", "", "", "", "", "", ""];

//These are specific for the first chart.
var okX = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var okY = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var tenSteps = 10;

var okCanvas = Raphael("paper", width, height);
var okChart = okCanvas.dotchart(offsetX, offsetY, width, height, okX, okY, values, { symbol: "o", max: 3, heat: true, axis: "0 0 1 1", axisxstep: tenSteps, axisystep: tenSteps, axisxlabels: axisx, axisxtype: "+", axisytype: "+", axisylabels: axisy, opacity: 0.8 })

//These are used in both problem charts.
var weirdX = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var weirdY = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var weirdCanvas1 = Raphael("paper1", width, height);
var weirdChart1 = weirdCanvas1.dotchart(offsetX, offsetY, width, height, weirdX, weirdY, values, { symbol: "o", max: 3, heat: true, axis: "0 0 1 1", axisxstep: tenSteps, axisystep: tenSteps, axisxlabels: axisx, axisxtype: "+", axisytype: "+", axisylabels: axisy, opacity: 0.8 })


//This is the only parameter change.
var nineSteps = 9;

var weirdCanvas2 = Raphael("paper2", width, height);
var weirdChart2 = weirdCanvas2.dotchart(offsetX, offsetY, width, height, weirdX, weirdY, values, { symbol: "o", max: 3, heat: true, axis: "0 0 1 1", axisxstep: nineSteps, axisystep: nineSteps, axisxlabels: axisx, axisxtype: "+", axisytype: "+", axisylabels: axisy, opacity: 0.8 })

}

</script>
</head>

<body onload="DrawAll()">
<h1>OK scale</h1>
<h2>Axis ends where the most extreme datapoints are.</h2>
<br />
<div id="paper"></div>
<br />
<br />
<h1>Weird scale1</h1>
<h2>Axis do not start at (1,1) as expected.</h2>
<div id="paper1"></div>
<br />
<br />
<h1>Weird scale2</h1>
<h2>Count the marked numbers along the axis. Number 5 is missing.</h2>
<h2>Also the points seems misaligned to the axis. Check point (1,1) against mark on the axis.</h2>
<div id="paper2"></div>
</body>
</html>

jeppo74 commented 10 years ago

To make this bugreport more easy to understand I am adding screenshots. Problem is described in each picture. weird scale 1 weird scale 2

jeppo74 commented 10 years ago

These problem was first produced with g.raphael 0.5 and could be reproduced with version 0.51. It seems related to #192 .

jeppo74 commented 10 years ago

I made a hack to function snapEnds that seems to solve my problems. The two problems shown in the screenshots are solved by my hack. I also tested about 40 charts of random data. This version is more predictable without the +-0.5 magic.

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

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

    function round(a) {       //Jego modified this 2014-01-20. This +-0.5 magic causes us trouble. Our customer reports it as a bug.
        return Math.round(a); //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 + 0.0) * Math.pow(10, i)) / Math.pow(10, i); //2014-01-21 jego changed 0.5 to 0.0 for more predictable behaviour
    }

    f = round((from - (i > 0 ? 0 : 0.0)) * Math.pow(10, i)) / Math.pow(10, i); //2014-01-21 jego changed 0.5 to 0.0 for more predictable behaviour
    return { from: f, to: t, power: i };
},
naoisegolden commented 9 years ago

Same here. Didn't try the hack yet.