diff --git a/src/utils/scales-utils.js b/src/utils/scales-utils.js index f4b5bef9a..5ca122e11 100644 --- a/src/utils/scales-utils.js +++ b/src/utils/scales-utils.js @@ -150,6 +150,37 @@ export function _getSmallestDistanceIndex(values, scaleObject) { return result; } +/** + * This is a workaround for issue that ordinal scale + * does not have invert method implemented in d3-scale. + * @param {Object} Ordinal d3-scale object. + * @returns {void} + * @private + */ + +function addInvertFunctionToOrdinalScaleObject(scale) { + if (scale.invert) { + return; + } + + scale.invert = function invert(value) { + const [lower, upper] = scale.range(); + const start = Math.min(lower, upper); + const stop = Math.max(lower, upper); + + if (value < start + scale.padding() * scale.step()) { + return scale.domain()[0]; + } + + if (value > stop - scale.padding() * scale.step()) { + return scale.domain()[scale.domain().length - 1]; + } + + const index = Math.floor((value - start - scale.padding() * scale.step()) / scale.step()); + return scale.domain()[index]; + } +} + /** * Crate a scale function from the scale object. * @param {Object} scaleObject Scale object. @@ -179,6 +210,7 @@ export function getScaleFnFromScaleObject(scaleObject) { .range(range); if (type === ORDINAL_SCALE_TYPE) { scale.padding(0.5); + addInvertFunctionToOrdinalScaleObject(scale); } return scale; } diff --git a/tests/utils/scales-utils-tests.js b/tests/utils/scales-utils-tests.js index 7c5f559d5..842ba4fde 100644 --- a/tests/utils/scales-utils-tests.js +++ b/tests/utils/scales-utils-tests.js @@ -505,6 +505,22 @@ test('scales-utils #getScaleFnFromScaleObject', t => { [-1, 1], 'should build a generic domain that reflects about zero' ); + + const ordinalScale = getScaleFnFromScaleObject({ + type: 'ordinal', + domain: ["a", "b", "c", "d", "e"], + range: [20, 120] + }); + + t.equal(ordinalScale.invert(-10), "a"); + t.equal(ordinalScale.invert(25), "a"); + t.equal(ordinalScale.invert(40), "a"); + t.equal(ordinalScale.invert(60), "b"); + t.equal(ordinalScale.invert(80), "c"); + t.equal(ordinalScale.invert(100), "d"); + t.equal(ordinalScale.invert(115), "e"); + t.equal(ordinalScale.invert(130), "e"); + t.end(); });