forio / contour

Apache License 2.0
120 stars 21 forks source link

Dynamically generated left padding for axis ticks are not always accurate #297

Open lukwallace opened 5 years ago

lukwallace commented 5 years ago

Reference in code, using Y-Axis as example:

The spacing calculated for the left padding:

_getAdjustedLeftPadding: function(options) {
    var yDomainScaled = this._getYScaledDomain(this.yDomain, this.options);
    var tmpScale = d3.scale.linear().domain(yDomainScaled);
    var yLabels = tmpScale.ticks(options.ticks);
    var format = options.labels.formatter || d3.format(options.labels.format || ",.0f");
    var yAxisText = _.map(yLabels, format).join("<br>");
    var yLabelBounds = _.nw.textBounds(yAxisText, ".y.axis");
    return maxTickSize(this.options.yAxis) + (this.options.yAxis.tickPadding || 0) + yLabelBounds.width;
},

^ Uses tmpScale.ticks(options.ticks) to generate approximated tick values for spacing calculation

The actual tick value calculation for the y-axis:

axis: function() {
    /*jshint eqnull:true */
    var options = this.options.yAxis;
    var domain = this.domain;
    var dMin = options.min != null ? options.min : options.zeroAnchor ? Math.min(0, domain[0]) : domain[0];
    var dMax = options.max != null ? options.max : domain[1];
    var tickValues = options.tickValues || _.nw.niceTicks(dMin, dMax, options.ticks);
    var numTicks = this.numTicks(domain, options.min, options.max);
    var format = options.labels.formatter || d3.format(options.labels.format);
    return d3.svg.axis().scale(this._scale).tickFormat(format).tickSize(options.innerTickSize, options.outerTickSize).tickPadding(options.tickPadding).ticks(numTicks).tickValues(tickValues);
},

^ Uses options.tickValues || _.nw.niceTicks(dMin, dMax, options.ticks); to generate the actual tick values to be rendered.

This will occasionally cause the the ticks labels to be rendered with an inaccurate amount of space for them. We managed to produce this issue with a standard column chart using the data: [{"x":"AGM","y":12.125990845966125},{"x":"Supercapacitor","y":-12.39133198369404}]

hkumar1993 commented 5 years ago

I took a look at the data and noticed the extremely large number of decimal places being used. Seems that when I fix the y value to a single decimal point using parseFloat((value).toFixed(1), then the chart padding fixes itself. Its possible that there is some floating point issue happening in the niceMinMax function that is causing Contour to just give up and not calculate the correct padding for the chart.