diff --git a/src/component/axis/AxisBuilder.ts b/src/component/axis/AxisBuilder.ts index d01d20d660..65d33689e1 100644 --- a/src/component/axis/AxisBuilder.ts +++ b/src/component/axis/AxisBuilder.ts @@ -24,9 +24,9 @@ import {createTextStyle} from '../../label/labelStyle'; import Model from '../../model/Model'; import {isRadianAroundZero, remRadian} from '../../util/number'; import {createSymbol, normalizeSymbolOffset} from '../../util/symbol'; +import { estimateLabelUnionRect, shouldShowAllLabels } from '../../coord/axisHelper'; import * as matrixUtil from 'zrender/src/core/matrix'; import {applyTransform as v2ApplyTransform} from 'zrender/src/core/vector'; -import {shouldShowAllLabels} from '../../coord/axisHelper'; import { AxisBaseModel } from '../../coord/AxisBaseModel'; import { ZRTextVerticalAlign, ZRTextAlign, ECElement, ColorString } from '../../util/types'; import { AxisBaseOption } from '../../coord/axisCommonTypes'; @@ -234,7 +234,8 @@ interface AxisElementsBuilder { opt: AxisBuilderCfg, axisModel: AxisBaseModel, group: graphic.Group, - transformGroup: graphic.Group + transformGroup: graphic.Group, + labelGap?: number ):void } @@ -365,29 +366,47 @@ const builders: Record<'axisLine' | 'axisTickLabel' | 'axisName', AxisElementsBu }, axisName(opt, axisModel, group, transformGroup) { + function calcDistanceToAxis() { + const defaultMargin = 10; + const axis = axisModel.axis; + const isHorizontal = axis.isHorizontal(); + const labelUnionRect = estimateLabelUnionRect(axis); + if (!labelUnionRect) { + return 0; + } + const dim = isHorizontal ? 'height' : 'width'; + const margin = axisModel.getModel('axisLabel').get('margin'); + return labelUnionRect[dim] + margin + defaultMargin; + } const name = retrieve(opt.axisName, axisModel.get('name')); if (!name) { return; } - + const isOutside = name === 'outsideStart' || name === 'outsideMiddle' || name === 'outsideEnd'; + const labelGap = isOutside ? calcDistanceToAxis() : 0; const nameLocation = axisModel.get('nameLocation'); const nameDirection = opt.nameDirection; const textStyleModel = axisModel.getModel('nameTextStyle'); - const gap = axisModel.get('nameGap') || 0; - + const gap = (axisModel.get('nameGap') || 0); const extent = axisModel.axis.getExtent(); const gapSignal = extent[0] > extent[1] ? -1 : 1; + const pos = [ nameLocation === 'start' ? extent[0] - gapSignal * gap + : nameLocation === 'outsideStart' + ? extent[0] + gapSignal * (gap) + (nameDirection * labelGap) : nameLocation === 'end' ? extent[1] + gapSignal * gap - : (extent[0] + extent[1]) / 2, // 'middle' + : nameLocation === 'outsideEnd' + ? extent[1] - gapSignal * (gap) - (nameDirection * labelGap) + : (extent[0] + extent[1]) / 2, // 'middle' or 'outsideMiddle' // Reuse labelOffset. - isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0 + isNameLocationCenter(nameLocation) + ? opt.labelOffset + nameDirection * (gap + (isNameLocationOutside(nameLocation) ? labelGap : 0)) + : isNameLocationOutside(nameLocation) ? nameDirection * (gap + labelGap) : 0 ]; - let labelLayout; let nameRotation = axisModel.get('nameRotate'); @@ -475,15 +494,16 @@ const builders: Record<'axisLine' | 'axisTickLabel' | 'axisName', AxisElementsBu }; -function endTextLayout( - rotation: number, textPosition: 'start' | 'middle' | 'end', textRotate: number, extent: number[] -) { +function endTextLayout(rotation: number, + textPosition: 'start' | 'middle' | 'end' | 'outsideStart' | 'outsideMiddle' | 'outsideEnd', + textRotate: number, extent: number[]) { const rotationDiff = remRadian(textRotate - rotation); let textAlign: ZRTextAlign; let textVerticalAlign: ZRTextVerticalAlign; const inverse = extent[0] > extent[1]; - const onLeft = (textPosition === 'start' && !inverse) - || (textPosition !== 'start' && inverse); + const textIsStart = textPosition === 'start' || textPosition === 'outsideStart'; + const onLeft = ((textIsStart) && !inverse) + || (!textIsStart && inverse); if (isRadianAroundZero(rotationDiff - PI / 2)) { textVerticalAlign = onLeft ? 'bottom' : 'top'; @@ -600,9 +620,12 @@ function isTwoLabelOverlapped( } function isNameLocationCenter(nameLocation: string) { - return nameLocation === 'middle' || nameLocation === 'center'; + return nameLocation === 'middle' || nameLocation === 'center' || nameLocation === 'outsideMiddle'; } +function isNameLocationOutside(nameLocation: string) { + return nameLocation === 'outsideStart' || nameLocation === 'outsideMiddle' || nameLocation === 'outsideEnd'; +} function createTicks( ticksCoords: TickCoord[], diff --git a/src/coord/axisCommonTypes.ts b/src/coord/axisCommonTypes.ts index e3241cb02e..cd1a491667 100644 --- a/src/coord/axisCommonTypes.ts +++ b/src/coord/axisCommonTypes.ts @@ -35,7 +35,7 @@ export interface AxisBaseOptionCommon extends ComponentOption, inverse?: boolean; // Axis name displayed. name?: string; - nameLocation?: 'start' | 'middle' | 'end'; + nameLocation?: 'start' | 'middle' | 'end' | 'outsideStart' | 'outsideMiddle' | 'outsideEnd'; // By degree. nameRotate?: number; nameTruncate?: { diff --git a/test/axisLabel.html b/test/axisLabel.html index a3c5b97971..611f621b32 100644 --- a/test/axisLabel.html +++ b/test/axisLabel.html @@ -44,6 +44,8 @@
+
+
@@ -375,6 +377,77 @@ + + + \ No newline at end of file