Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/coord/axisCommonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ export interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon {
* Will be ignored if interval is set.
*/
alignTicks?: boolean

/**
* Configures the base of the interval to be used, e.g. use 2 for binary-based nice intervals (1, 2, 4, 8 × 2^n)
* or 10 for decimal-based intervals (1, 2, 5 × 10^n) (default).
*/
tickBase?: number;
}

export interface CategoryAxisBaseOption extends AxisBaseOptionCommon {
Expand Down
3 changes: 2 additions & 1 deletion src/coord/axisHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ export function niceScaleExtent(
fixMin: extentInfo.fixMin,
fixMax: extentInfo.fixMax,
minInterval: isIntervalOrTime ? model.get('minInterval') : null,
maxInterval: isIntervalOrTime ? model.get('maxInterval') : null
maxInterval: isIntervalOrTime ? model.get('maxInterval') : null,
tickBase: isIntervalOrTime ? model.get('tickBase') : undefined
});

// If some one specified the min, max. And the default calculated interval
Expand Down
7 changes: 4 additions & 3 deletions src/scale/Interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ class IntervalScale<SETTING extends ScaleSettingDefault = ScaleSettingDefault> e
*
* @param splitNumber By default `5`.
*/
calcNiceTicks(splitNumber?: number, minInterval?: number, maxInterval?: number): void {
calcNiceTicks(splitNumber?: number, minInterval?: number, maxInterval?: number, tickBase?: number): void {
splitNumber = splitNumber || 5;
let extent = this._extent.slice() as [number, number];
let span = this._getExtentSpanWithBreaks();
Expand All @@ -302,7 +302,7 @@ class IntervalScale<SETTING extends ScaleSettingDefault = ScaleSettingDefault> e
}

const result = helper.intervalScaleNiceTicks(
extent, span, splitNumber, minInterval, maxInterval
extent, span, splitNumber, minInterval, maxInterval, tickBase,
);

this._intervalPrecision = result.intervalPrecision;
Expand All @@ -316,6 +316,7 @@ class IntervalScale<SETTING extends ScaleSettingDefault = ScaleSettingDefault> e
fixMax?: boolean,
minInterval?: number,
maxInterval?: number
tickBase?: number,
}): void {
let extent = this._extent.slice() as [number, number];
// If extent start and end are same, expand them
Expand Down Expand Up @@ -350,7 +351,7 @@ class IntervalScale<SETTING extends ScaleSettingDefault = ScaleSettingDefault> e
this._innerSetExtent(extent[0], extent[1]);
extent = this._extent.slice() as [number, number];

this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval);
this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval, opt.tickBase);
const interval = this._interval;
const intervalPrecition = this._intervalPrecision;

Expand Down
3 changes: 2 additions & 1 deletion src/scale/Scale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ abstract class Scale<SETTING extends ScaleSettingDefault = ScaleSettingDefault>
fixMax?: boolean,
minInterval?: number,
maxInterval?: number
tickBase?: number,
}
): void;

Expand All @@ -270,4 +271,4 @@ abstract class Scale<SETTING extends ScaleSettingDefault = ScaleSettingDefault>
type ScaleConstructor = typeof Scale & clazzUtil.ClassManager;
clazzUtil.enableClassManagement(Scale as ScaleConstructor);

export default Scale;
export default Scale;
18 changes: 15 additions & 3 deletions src/scale/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import {getPrecision, round, nice, quantityExponent} from '../util/number';
import {getPrecision, round, nice, niceBinary, quantityExponent} from '../util/number';
import IntervalScale from './Interval';
import LogScale from './Log';
import type Scale from './Scale';
Expand Down Expand Up @@ -53,12 +53,13 @@ export function intervalScaleNiceTicks(
spanWithBreaks: number,
splitNumber: number,
minInterval?: number,
maxInterval?: number
maxInterval?: number,
tickBase?: number
): intervalScaleNiceTicksResult {

const result = {} as intervalScaleNiceTicksResult;

let interval = result.interval = nice(spanWithBreaks / splitNumber, true);
let interval = result.interval = getNiceInterval(spanWithBreaks / splitNumber, true, tickBase);
if (minInterval != null && interval < minInterval) {
interval = result.interval = minInterval;
}
Expand Down Expand Up @@ -173,3 +174,14 @@ export function logTransform(base: number, extent: number[], noClampNegative?: b
Math.log(noClampNegative ? extent[1] : Math.max(0, extent[1])) / loggedBase
];
}

function getNiceInterval(val: number, round?: boolean, base?: number): number {
if (base === 2) {
return niceBinary(val, round);
}
else if (base === 10) {
return nice(val, round);
}
// default to base 10
return nice(val, round);
}
46 changes: 46 additions & 0 deletions src/util/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,52 @@ export function nice(val: number, round?: boolean): number {
return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
}

/**
* Binary-based nice function for bytes, memory, etc.
* Produces intervals like 1, 2, 4, 8 × 2^n
*/
export function niceBinary(val: number, round?: boolean): number {
const exp2 = Math.pow(2, Math.floor(Math.log2(val)));
const f = val / exp2; // 1 <= f < 2

let nf: number;
if (round) {
if (f < 1.5) {
nf = 1;
}
else if (f < 2.5) {
nf = 2;
}
else if (f < 4) {
nf = 4;
}
else if (f < 7) {
nf = 8;
}
else {
nf = 16;
}
}
else {
if (f < 1) {
nf = 1;
}
else if (f < 2) {
nf = 2;
}
else if (f < 3) {
nf = 4;
}
else if (f < 5) {
nf = 8;
}
else {
nf = 16;
}
}
return nf * exp2;
}

/**
* This code was copied from "d3.js"
* <https://github.com/d3/d3/blob/9cc9a875e636a1dcf36cc1e07bdf77e1ad6e2c74/src/arrays/quantile.js>.
Expand Down