@toast-ui/chart
Version:
TOAST UI Application: Chart
176 lines (175 loc) • 9.62 kB
JavaScript
import { getInitAxisIntervalData, getMaxLabelSize, isLabelAxisOnYAxis, makeTitleOption, getDefaultRadialAxisData, } from "../helpers/axes";
import { makeLabelsFromLimit, getFontHeight } from "../helpers/calculator";
import { getTitleFontString } from "../helpers/style";
import { DEGREE_360, DEGREE_0 } from "../helpers/sector";
import { isObject, calculateSizeWithPercentString } from "../helpers/utils";
import { RadialAxisType } from "./radialAxes";
import { isExistPlotId } from "../helpers/plot";
const DEFAULT_LABEL_PADDING = 15;
const RANGE_BAR_MARGIN = 10;
const CLOCK_HAND_MARGIN = 10;
export const DATA_LABEL_MARGIN = 30;
function makeSolidData(outerRadius, barWidth, solidOptions) {
const initialSolidOptions = (solidOptions !== null && solidOptions !== void 0 ? solidOptions : false);
const solidBarWidth = calculateSizeWithPercentString(outerRadius, barWidth);
const defaultSolidOptions = {
visible: true,
radiusRange: {
inner: outerRadius - solidBarWidth,
outer: outerRadius,
},
barWidth: solidBarWidth,
clockHand: false,
};
if (!initialSolidOptions) {
return Object.assign(Object.assign({}, defaultSolidOptions), { visible: false });
}
return isObject(initialSolidOptions)
? Object.assign(Object.assign({}, defaultSolidOptions), initialSolidOptions) : defaultSolidOptions;
}
function getCircularAxisData({ labels, intervalData, circularAxisLabelMargin, circularAxisLabelFont, defaultAxisData, bandWidth, options, solidBarWidth, }) {
var _a, _b, _c, _d;
const { maxLabelWidth, maxLabelHeight } = getMaxLabelSize(labels, circularAxisLabelMargin, circularAxisLabelFont);
const { totalAngle, axisSize, centerX, centerY, startAngle, endAngle, drawingStartAngle, clockwise, } = defaultAxisData;
const { tickInterval, labelInterval } = intervalData;
const outerRadius = axisSize - bandWidth - RANGE_BAR_MARGIN;
const solidBarWidthValue = (solidBarWidth !== null && solidBarWidth !== void 0 ? solidBarWidth : outerRadius * 0.1);
const solidData = makeSolidData(outerRadius - circularAxisLabelMargin - maxLabelHeight - (circularAxisLabelMargin - 5), solidBarWidthValue, (_b = (_a = options) === null || _a === void 0 ? void 0 : _a.series) === null || _b === void 0 ? void 0 : _b.solid);
const centralAngle = totalAngle / (labels.length + (totalAngle < DEGREE_360 ? -1 : DEGREE_0));
const maxClockHandSize = outerRadius -
circularAxisLabelMargin -
maxLabelHeight -
CLOCK_HAND_MARGIN +
(solidData.visible ? -solidData.barWidth - CLOCK_HAND_MARGIN : 0);
return {
axisSize,
centerX,
centerY,
label: {
labels,
interval: labelInterval,
margin: circularAxisLabelMargin,
maxWidth: maxLabelWidth,
maxHeight: maxLabelHeight,
},
radius: {
inner: 0,
outer: outerRadius,
},
angle: {
start: startAngle,
end: endAngle,
total: totalAngle,
central: centralAngle,
drawingStart: drawingStartAngle,
},
band: {
width: bandWidth,
margin: RANGE_BAR_MARGIN,
},
tickInterval,
clockwise,
maxClockHandSize,
title: makeTitleOption((_d = (_c = options) === null || _c === void 0 ? void 0 : _c.circularAxis) === null || _d === void 0 ? void 0 : _d.title),
solidData,
};
}
function makeLabels(options, rawLabels, axisName) {
var _a, _b, _c;
const formatter = (_c = (_b = (_a = options[axisName]) === null || _a === void 0 ? void 0 : _a.label) === null || _b === void 0 ? void 0 : _b.formatter, (_c !== null && _c !== void 0 ? _c : ((value) => value)));
return rawLabels.map((label, index) => formatter(label, { index, labels: rawLabels, axisName }));
}
function getAxisLabels(isLabelOnVerticalAxis, options, categories, scale) {
const valueAxisName = isLabelOnVerticalAxis
? RadialAxisType.CIRCULAR
: RadialAxisType.VERTICAL;
const { limit, stepSize } = scale[valueAxisName];
const valueLabels = makeLabels(options, makeLabelsFromLimit(limit, stepSize), valueAxisName);
const categoryLabels = makeLabels(options, categories, isLabelOnVerticalAxis ? RadialAxisType.VERTICAL : RadialAxisType.CIRCULAR);
return isLabelOnVerticalAxis ? valueLabels : categoryLabels;
}
function getAxisLabelMargin(options) {
var _a, _b, _c, _d;
return _d = (_c = (_b = (_a = options) === null || _a === void 0 ? void 0 : _a.circularAxis) === null || _b === void 0 ? void 0 : _b.label) === null || _c === void 0 ? void 0 : _c.margin, (_d !== null && _d !== void 0 ? _d : DEFAULT_LABEL_PADDING);
}
function hasAxesLayoutChanged(previousAxes, currentAxes) {
var _a, _b, _c, _d;
const prevMaxWidth = (_b = (_a = previousAxes) === null || _a === void 0 ? void 0 : _a.label) === null || _b === void 0 ? void 0 : _b.maxWidth;
const prevMaxHeight = (_d = (_c = previousAxes) === null || _c === void 0 ? void 0 : _c.label) === null || _d === void 0 ? void 0 : _d.maxHeight;
const curMaxWidth = currentAxes.label.maxWidth;
const curMaxHeight = currentAxes.label.maxHeight;
return prevMaxHeight !== curMaxHeight || prevMaxWidth !== curMaxWidth;
}
const axes = {
name: 'gaugeAxes',
state: () => ({
radialAxes: {
circularAxis: {},
},
}),
action: {
setCircularAxisData({ state }) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
const { series, layout, scale } = state;
const categories = state.categories;
const { plot } = layout;
const isLabelOnVerticalAxis = isLabelAxisOnYAxis({ series, categories });
const options = state.options;
const theme = state.theme;
const circularAxisLabelFont = getTitleFontString(theme.circularAxis.label);
const circularAxisLabelMargin = getAxisLabelMargin(options);
const circularAxisLabels = getAxisLabels(isLabelOnVerticalAxis, options, categories, scale);
const { maxLabelWidth, maxLabelHeight } = getMaxLabelSize(circularAxisLabels, circularAxisLabelMargin, circularAxisLabelFont);
const defaultAxisData = getDefaultRadialAxisData(options, plot, maxLabelWidth, maxLabelHeight, isLabelOnVerticalAxis);
const dataLabelHeight = getFontHeight(getTitleFontString(theme.series.gauge.dataLabels));
const dataLabelOffsetY = (_d = (_c = (_b = (_a = options) === null || _a === void 0 ? void 0 : _a.series) === null || _b === void 0 ? void 0 : _b.dataLabels) === null || _c === void 0 ? void 0 : _c.offsetY, (_d !== null && _d !== void 0 ? _d : DATA_LABEL_MARGIN));
if (defaultAxisData.isSemiCircular) {
defaultAxisData.centerY =
defaultAxisData.centerY - (dataLabelOffsetY > 0 ? dataLabelOffsetY + dataLabelHeight : 0);
const diffHeight = defaultAxisData.centerY - defaultAxisData.axisSize;
defaultAxisData.axisSize += diffHeight < 0 ? diffHeight : 0;
}
const defualtBandWidth = ((_g = (_f = (_e = options) === null || _e === void 0 ? void 0 : _e.plot) === null || _f === void 0 ? void 0 : _f.bands) === null || _g === void 0 ? void 0 : _g.length) ? defaultAxisData.axisSize / 2 - RANGE_BAR_MARGIN
: 0;
const bandWidth = (_k = (_j = (_h = theme.plot) === null || _h === void 0 ? void 0 : _h.bands) === null || _j === void 0 ? void 0 : _j.barWidth, (_k !== null && _k !== void 0 ? _k : defualtBandWidth));
const circularAxisData = getCircularAxisData({
labels: circularAxisLabels,
intervalData: getInitAxisIntervalData(true, {
axis: options.circularAxis,
categories,
layout,
}),
defaultAxisData,
circularAxisLabelMargin,
circularAxisLabelFont,
bandWidth,
options,
solidBarWidth: (_m = (_l = theme.series.gauge) === null || _l === void 0 ? void 0 : _l.solid) === null || _m === void 0 ? void 0 : _m.barWidth,
});
if (hasAxesLayoutChanged((_o = state.radialAxes) === null || _o === void 0 ? void 0 : _o.circularAxis, circularAxisData)) {
this.notify(state, 'layout');
}
state.radialAxes = {
circularAxis: circularAxisData,
};
},
addGaugePlotBand({ state }, { data }) {
var _a, _b, _c;
const bands = (_c = (_b = (_a = state.options) === null || _a === void 0 ? void 0 : _a.plot) === null || _b === void 0 ? void 0 : _b.bands, (_c !== null && _c !== void 0 ? _c : []));
if (!isExistPlotId(bands, data)) {
this.dispatch('updateOptions', { options: { plot: { bands: [...bands, data] } } });
}
},
removeGaugePlotBand({ state }, { id }) {
var _a, _b, _c;
const bands = (_c = (_b = (_a = state.options) === null || _a === void 0 ? void 0 : _a.plot) === null || _b === void 0 ? void 0 : _b.bands, (_c !== null && _c !== void 0 ? _c : [])).filter(({ id: bandId }) => bandId !== id);
this.dispatch('updateOptions', { options: { plot: { bands } } });
},
},
observe: {
updateRadialAxes() {
this.dispatch('setCircularAxisData');
},
},
};
export default axes;