Skip to main content
Module

x/billboardjs/ChartInternal/Axis/AxisRendererHelper.ts

πŸ“Š Re-usable, easy interface JavaScript chart library based on D3.js
Go to Latest
File
/** * Copyright (c) 2017 ~ present NAVER Corp. * billboard.js project is licensed under the MIT license * @ignore */import {getScale} from "../internals/scale";import {isDefined, isNumber, isString} from "../../module/util";import type {d3Selection} from "../../../types/types";
export default class AxisRendererHelper { private owner; private config; private scale;
constructor(owner) { const scale = getScale(); const {config, params} = owner;
this.owner = owner; this.config = config; this.scale = scale;
if (config.noTransition || !params.config.transition_duration) { config.withoutTransition = true; }
// set range config.range = this.scaleExtent((params.orgXScale || scale).range()); }
/** * Compute a character dimension * @param {d3.selection} node <g class=tick> node * @returns {{w: number, h: number}} * @private */ static getSizeFor1Char(node?) { // default size for one character const size = { w: 5.5, h: 11.5 };
!node.empty() && node.select("text") .text("0") .call(el => { try { const {width, height} = el.node().getBBox();
if (width && height) { size.w = width; size.h = height; } } catch (e) { } finally { el.text(""); } });
this.getSizeFor1Char = () => size;
return size; }
/** * Get tick transform setter function * @param {string} id Axis id * @returns {Function} transfrom setter function * @private */ getTickTransformSetter(id: string): (selection: d3Selection, scale) => void { const {config} = this; const fn = id === "x" ? value => `translate(${value + config.tickOffset},0)` : value => `translate(0,${value})`;
return (selection, scale) => { selection.attr("transform", d => fn(Math.ceil(scale(d)))); }; }
scaleExtent(domain: [number, number]): [number, number] { const start = domain[0]; const stop = domain[domain.length - 1];
return start < stop ? [start, stop] : [stop, start]; }
generateTicks(scale, isYAxes: boolean): number[] { const {tickStepSize} = this.owner.params; const [start, end] = scale.domain(); let ticks: number[] = [];
// When 'axis[y|y2].tick.stepSize' option is set if (isYAxes && tickStepSize) { let interval = Math.round(start);
while (interval <= end) { ticks.push(interval); interval += tickStepSize; } } else if (scale.ticks) { const {tickArguments} = this.config;
// adjust excessive tick count show if (scale.type === "log" && !tickArguments) { // nicer symlog ticks didn't implemented yet: https://github.com/d3/d3-scale/issues/162 // get ticks values from logScale const s = getScale("_log") .domain([start > 0 ? start : 1, end]) .range(scale.range());
ticks = s.ticks();
for (let cnt = end.toFixed().length; ticks.length > 15; cnt--) { ticks = s.ticks(cnt); }
ticks.splice(0, 1, start); ticks.splice(ticks.length - 1, 1, end); } else { ticks = scale .ticks(...(this.config.tickArguments || [])); }
ticks = ticks .map(v => { // round the tick value if is number const r = (isString(v) && isNumber(v) && !isNaN(v) && Math.round(v * 10) / 10) || v;
return r; }); } else { for (let i = Math.ceil(start); i < end; i++) { ticks.push(i); }
if (ticks.length > 0 && ticks[0] > 0) { ticks.unshift(ticks[0] - (ticks[1] - ticks[0])); } }
return ticks; }
copyScale() { const newScale = this.scale.copy();
if (!newScale.domain().length) { newScale.domain(this.scale.domain()); }
newScale.type = this.scale.type;
return newScale; }
textFormatted(v: string | number | any): string { const tickFormat = this.config.tickFormat;
// to round float numbers from 'binary floating point' // https://en.wikipedia.org/wiki/Double-precision_floating-point_format // https://stackoverflow.com/questions/17849101/laymans-explanation-for-why-javascript-has-weird-floating-math-ieee-754-stand const value = /\d+\.\d+0{5,}\d$/.test(v) ? +String(v).replace(/0+\d$/, "") : v; const formatted = tickFormat ? tickFormat(value) : value;
return isDefined(formatted) ? formatted : ""; }
transitionise(selection): d3Selection { const {config} = this; let transitionSelection = selection;
if (config.withoutTransition) { transitionSelection = selection.interrupt(); } else if (config.transition || !this.owner.params.noTransition) { // prevent for 'transition not found' case // https://github.com/naver/billboard.js/issues/2140 try { transitionSelection = selection.transition(config.transition); } catch (e) {} }
return transitionSelection; }}