Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { createStage } from '@visactor/vrender-core';
import { initBrowserEnv } from '@visactor/vrender-kits';
initBrowserEnv();
import { PointScale } from '@visactor/vscale';
import { LineAxis } from '../../../src';

const stage = createStage({
canvas: 'main',
width: 2000,
height: 1200,
autoRender: true,
disableDirtyBounds: true,
enableHtmlAttribute: true
});

(window as any).stage = stage;

const deltaAngle = Math.PI / 4;
const count = (Math.PI * 2) / deltaAngle;

{
let curX = 78;
for (let i = 0; i < count; i++) {
const axis = new LineAxis({
x: curX,
y: 27,
start: {
x: 0,
y: 0
},
end: {
x: 162,
y: 0
},
visible: true,
pickable: true,
orient: 'bottom',
line: {
visible: true,
style: {
lineWidth: 1,
stroke: '#d9dde4',
strokeOpacity: 1
}
},
label: {
visible: true,
inside: false,
space: 8,
autoLimit: true,
autoRotate: false,
overflowLimitLength: {
left: 78,
right: 20
},
style: {
fontSize: 12,
fill: '#89909d',
fontWeight: 'normal',
fillOpacity: 1,
angle: i * deltaAngle
}
},
tick: {
visible: true,
length: 4,
inside: false,
alignWithLabel: true,
style: {
lineWidth: 1,
stroke: '#d9dde4',
strokeOpacity: 1
}
},
subTick: {
visible: false
},
title: {
visible: false,
text: 'month',
maxWidth: null
},
panel: {
visible: false
},
verticalFactor: 1,
items: [
[
{
id: 'MondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMonday',
label: 'MondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMonday',
value: 0.13636363636363633,
rawValue: 'MondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMondayMonday'
},
{
id: 'TuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesday',
label: 'TuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesday',
value: 0.3181818181818181,
rawValue: 'TuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesdayTuesday'
},
{
id: 'WednesdayWednesdayWednesday',
label: 'WednesdayWednesdayWednesday',
value: 0.4999999999999999,
rawValue: 'WednesdayWednesdayWednesday'
},
{
id: 'ThursdayThursdayThursday',
label: 'ThursdayThursdayThursday',
value: 0.6818181818181818,
rawValue: 'ThursdayThursdayThursday'
},
{
id: 'FridayFridayFridayFriday',
label: 'FridayFridayFridayFriday',
value: 0.8636363636363636,
rawValue: 'FridayFridayFridayFriday'
}
]
],
verticalLimitSize: 267.6,
verticalMinSize: null,
_debug_bounds: true
});
stage.defaultLayer.add(axis);
if ((axis as any).AABBBounds.x1 < curX) {
axis.setAttributes({ dx: curX - (axis as any).AABBBounds.x1 });
}
curX = (axis as any).AABBBounds.x2 + 10;
}
}

stage.render();
4 changes: 4 additions & 0 deletions packages/vrender-components/__tests__/browser/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const specs = [
path: 'axis-labels',
name: '轴标签各种角度'
},
{
path: 'axis-label-limit',
name: '轴标签长度限制'
},
{
path: 'size-legend',
name: '连续尺寸图例'
Expand Down
6 changes: 4 additions & 2 deletions packages/vrender-components/src/axis/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ export class LineAxis extends AxisBase<LineAxisAttributes> {
autoHideMethod,
autoHideSeparation,
lastVisible,
autoWrap
autoWrap,
overflowLimitLength
} = label;

if (isFunction(layoutFunc)) {
Expand Down Expand Up @@ -469,7 +470,8 @@ export class LineAxis extends AxisBase<LineAxisAttributes> {
verticalLimitLength,
ellipsis: limitEllipsis,
orient,
axisLength
axisLength,
overflowLimitLength
});
}
if (autoHide) {
Expand Down
38 changes: 32 additions & 6 deletions packages/vrender-components/src/axis/overlap/auto-limit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,47 @@
* 自动省略
*/
import type { IText } from '@visactor/vrender-core';
import { isEmpty, isNil, isNumberClose, isValidNumber } from '@visactor/vutils';
import { isAngleHorizontal, isAngleVertical } from './util';
import type { AxisLabelOverlap } from '../type';
import { isEmpty, isNil, isObject, isValidNumber } from '@visactor/vutils';

type LimitConfig = {
orient: string;
limitLength: number;
axisLength: number;
verticalLimitLength?: number;
ellipsis?: string;
overflowLimitLength?: AxisLabelOverlap['overflowLimitLength'];
};

function normalizeOverflowLimitLength(overflowLimitLength?: AxisLabelOverlap['overflowLimitLength']) {
if (isValidNumber(overflowLimitLength)) {
return {
left: overflowLimitLength,
right: overflowLimitLength
// top: overflowLimitLength,
// bottom: overflowLimitLength
};
} else if (isObject(overflowLimitLength)) {
return {
left: overflowLimitLength.left || 0,
right: overflowLimitLength.right || 0
// top: overflowLimitLength.top || 0,
// bottom: overflowLimitLength.bottom || 0
};
}
return { left: 0, right: 0 };
}

export function autoLimit(labels: IText[], config: LimitConfig) {
const { limitLength, verticalLimitLength, ellipsis = '...', orient, axisLength } = config;
if (isEmpty(labels) || !isValidNumber(limitLength)) {
return;
}
const DELTA = Math.sin(Math.PI / 10);

const overflowLimitLength = normalizeOverflowLimitLength(config.overflowLimitLength);

labels.forEach(label => {
const angle = label.attribute.angle;

Expand Down Expand Up @@ -63,19 +86,22 @@ export function autoLimit(labels: IText[], config: LimitConfig) {
if (isX) {
const { x1, x2 } = label.AABBBounds;
const tan = sin / cos;

const verticalSizeLimit = Math.abs(limitLength / sin);
if (tan > 0 && x1 <= axisLength && limitLength / tan + x1 > axisLength) {
limitLabelLength = (axisLength - x1) / Math.abs(cos);
// 以 x1 近似为锚点,文字在 x1 右侧
const lengthLimit = (axisLength - x1) / Math.abs(cos) + overflowLimitLength.right;
limitLabelLength = Math.min(lengthLimit, verticalSizeLimit);
} else if (tan < 0 && x2 >= 0 && limitLength / tan + x2 < 0) {
limitLabelLength = x2 / Math.abs(cos);
// 以 x2 近似为锚点,文字在 x2 左侧
const lengthLimit = x2 / Math.abs(cos) + overflowLimitLength.left;
limitLabelLength = Math.min(lengthLimit, verticalSizeLimit);
} else {
limitLabelLength = Math.abs(limitLength / sin);
limitLabelLength = verticalSizeLimit;
}
} else {
// y轴暂时不限制在平行于坐标轴的矩形内,后续可以考虑通过配置开启
// const { y1, y2 } = label.AABBBounds;
// const tan = sin / cos;

// if (tan > 0 && y2 >= 0 && y2 - tan * limitLength < 0) {
// limitLabelLength = y2 / Math.abs(sin);
// } else if (tan < 0 && y1 <= axisLength && y1 - tan * limitLength > axisLength) {
Expand Down
16 changes: 16 additions & 0 deletions packages/vrender-components/src/axis/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export interface LineAxisAttributes extends Omit<AxisBaseAttributes, 'label'> {
* 如果同时声明了 verticalLimitSize,请保证 verticalMinSize <= verticalLimitSize,否则会以 verticalLimitSize 为准。
*/
verticalMinSize?: number;

/**
* 轴标签配置
*/
Expand Down Expand Up @@ -396,6 +397,21 @@ export interface AxisLabelOverlap {
* @default '...'
*/
limitEllipsis?: string;
/**
* 文字超出坐标轴范围时,两侧可以提供扩充的空间大小。
* 例如,x 轴坐标 135 度旋转时,左侧第一个标签可能超出坐标轴范围,导致文本被缩略,此时可以通过配置 `overflowLimitLength` 优化效果。
* 仅当 `autoLimit` 为 true 时生效。
* @default 0
* @since 0.20.3 支持 X 轴配置生效
*/
overflowLimitLength?:
| number
| {
left?: number;
right?: number;
// top?: number;
// bottom?: number;
};

/**
* 自定义布局配置,如果声明了 `layoutFunc`,则默认提供的防重叠相关的配置(`autoHide`, `autoRotate`, `autoLimit`)均不生效
Expand Down