Skip to content

Commit

Permalink
Merge pull request #1396 from VisActor/fix/axis-label-angle
Browse files Browse the repository at this point in the history
Fix/axis label angle
  • Loading branch information
xile611 authored Aug 27, 2024
2 parents 519771f + 8cc3c0a commit 6313aff
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "fix: fix textAlign of label when set different angle\n\n",
"type": "none",
"packageName": "@visactor/vrender-components"
}
],
"packageName": "@visactor/vrender-components",
"email": "dingling112@gmail.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "fix: fix textAlign of label when set different angle\n\n",
"type": "none",
"packageName": "@visactor/vrender-core"
}
],
"packageName": "@visactor/vrender-core",
"email": "dingling112@gmail.com"
}
117 changes: 117 additions & 0 deletions packages/vrender-components/__tests__/browser/examples/axis-labels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { createStage } from '@visactor/vrender-core';
import { initBrowserEnv } from '@visactor/vrender-kits';
initBrowserEnv();
import render from '../../util/render';
import { LineAxis } from '../../../src';

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

const axies: any[] = [];

[false, true].forEach((inside, insideIndex) => {
['left', 'right'].forEach(orient => {
let currentX: number = orient === 'left' ? (inside ? 20 : 600) : inside ? 1180 : 650;
new Array(9).fill(0).map((entry, index) => {
const axis = new LineAxis({
x: currentX,
y: 40 + insideIndex * 600,
start: {
x: 0,
y: 0
},
end: {
x: 0,
y: 408
},
pickable: true,
visible: true,
orient: orient,
line: {
visible: true
},
label: {
visible: true,
// containerAlign: 'left',
inside,
space: 12,
style: {
// textAlign: 'right',
angle: (index * Math.PI) / 4,
fontSize: 10,
fill: '#000000',
fontWeight: 'normal',
fillOpacity: 1
}
},
tick: {
visible: true,
inside
},
subTick: {
visible: false
},
title: {
visible: true,
text: `测试label旋转角度${index * 45}`,
maxWidth: null
},
panel: {
visible: true,
style: {
background: 'pink'
}
},
verticalFactor: orient === 'left' ? 1 : -1,
items: [
[
{
id: 0,
label: 0,
value: 1,
rawValue: 0
},
{
id: 5,
label: 500,
value: 0.75,
rawValue: 500
},
{
id: 10,
label: 1000,
value: 0.5,
rawValue: 1000
},
{
id: 15,
label: 1500,
value: 0.25,
rawValue: 1500
},
{
id: 20,
label: 2000,
value: 0,
rawValue: 2000
}
]
],
verticalLimitSize: 87,
verticalMinSize: null as any
});

stage.defaultLayer.add(axis);
currentX += (orient === 'left' ? -1 : 1) * (inside ? -1 : 1) * ((axis as any).AABBBounds.width() + 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 @@ -38,6 +38,10 @@ const specs = [
path: 'interactive-axis',
name: '带交互的坐标轴'
},
{
path: 'axis-labels',
name: '轴标签各种角度'
},
{
path: 'size-legend',
name: '连续尺寸图例'
Expand Down
93 changes: 55 additions & 38 deletions packages/vrender-components/__tests__/unit/axis/line.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -895,14 +895,18 @@ describe('Line Axis', () => {
});
stage.defaultLayer.add(axis as unknown as IGraphic);
stage.render();
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('left');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('right');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.x).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x1
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x2
);

axis.setAttribute('label', { containerAlign: 'center' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('center');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.x).toBe(
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('right');
expect(
(axis.getElementsByName('axis-label')[0] as IText).attribute.x +
(axis.getElementsByName('axis-label')[0] as IText).attribute.dx -
(axis.getElementsByName('axis-label')[0] as IText).AABBBounds.width() / 2
).toBeCloseTo(
((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x1 +
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x2) *
0.5
Expand All @@ -921,10 +925,12 @@ describe('Line Axis', () => {
},
verticalMinSize: null
});
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('left');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.x).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x1
);
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('right');
expect(
(axis.getElementsByName('axis-label')[0] as IText).attribute.x +
(axis.getElementsByName('axis-label')[0] as IText).attribute.dx -
(axis.getElementsByName('axis-label')[0] as IText).AABBBounds.width()
).toBeCloseTo((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x1);
expect((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.width()).toBeCloseTo(
11.16
);
Expand Down Expand Up @@ -983,18 +989,24 @@ describe('Line Axis', () => {
);

axis.setAttribute('label', { containerAlign: 'center' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('center');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.x).toBe(
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('left');
expect(
(axis.getElementsByName('axis-label')[0] as IText).attribute.x +
(axis.getElementsByName('axis-label')[0] as IText).attribute.dx +
(axis.getElementsByName('axis-label')[0] as IText).AABBBounds.width() / 2
).toBe(
((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x1 +
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x2) *
0.5
);

axis.setAttribute('label', { containerAlign: 'right' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('right');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.x).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x2
);
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textAlign).toBe('left');
expect(
(axis.getElementsByName('axis-label')[0] as IText).attribute.x +
(axis.getElementsByName('axis-label')[0] as IText).attribute.dx +
(axis.getElementsByName('axis-label')[0] as IText).AABBBounds.width()
).toBeCloseTo((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.x2);

axis.setAttribute('verticalMinSize', 400);
expect(axis.AABBBounds.width()).toBeLessThan(400);
Expand Down Expand Up @@ -1035,23 +1047,26 @@ describe('Line Axis', () => {
stage.defaultLayer.add(axis as unknown as IGraphic);
stage.render();

expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textBaseline).toBe('bottom');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.y).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y2 - 2
);
let firstLabel = axis.getElementsByName('axis-label')[0] as IText;
let firstLayer = axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup;
expect(firstLabel.attribute.textBaseline).toBe('bottom');
expect(firstLabel.attribute.y).toBe(firstLayer.AABBBounds.y2 - 2);

axis.setAttribute('label', { containerAlign: 'middle' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textBaseline).toBe('middle');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.y).toBe(
((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y1 +
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y2) *
0.5
firstLabel = axis.getElementsByName('axis-label')[0] as IText;
firstLayer = axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup;
expect(firstLabel.attribute.textBaseline).toBe('bottom');
expect((firstLabel.AABBBounds.y1 + firstLabel.AABBBounds.y2) / 2).toBeCloseTo(
(firstLayer.AABBBounds.y1 + firstLayer.AABBBounds.y2) * 0.5 - 2
);

axis.setAttribute('label', { containerAlign: 'top' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textBaseline).toBe('top');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.y).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y1

firstLabel = axis.getElementsByName('axis-label')[0] as IText;
firstLayer = axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup;
expect(firstLabel.attribute.textBaseline).toBe('bottom');
expect(firstLabel.attribute.y + firstLabel.attribute.dy - firstLabel.AABBBounds.height()).toBeCloseTo(
firstLayer.AABBBounds.y1
);
});

Expand Down Expand Up @@ -1089,24 +1104,26 @@ describe('Line Axis', () => {
stage.defaultLayer.add(axis as unknown as IGraphic);
stage.render();

expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textBaseline).toBe('bottom');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.y).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y2 - 2
let firstLabel = axis.getElementsByName('axis-label')[0] as IText;
let firstLayer = axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup;
expect(firstLabel.attribute.textBaseline).toBe('top');
expect(firstLabel.attribute.y + firstLabel.attribute.dy + firstLabel.AABBBounds.height()).toBe(
firstLayer.AABBBounds.y2
);

axis.setAttribute('label', { containerAlign: 'middle' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textBaseline).toBe('middle');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.y).toBe(
((axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y1 +
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y2) *
0.5
firstLabel = axis.getElementsByName('axis-label')[0] as IText;
firstLayer = axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup;
expect(firstLabel.attribute.textBaseline).toBe('top');
expect(firstLabel.attribute.y + firstLabel.attribute.dy + firstLabel.AABBBounds.height() / 2).toBe(
(firstLayer.AABBBounds.y1 + firstLayer.AABBBounds.y2) * 0.5
);

axis.setAttribute('label', { containerAlign: 'top' });
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.textBaseline).toBe('top');
expect((axis.getElementsByName('axis-label')[0] as IText).attribute.y).toBe(
(axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup).AABBBounds.y1
);
firstLabel = axis.getElementsByName('axis-label')[0] as IText;
firstLayer = axis.getElementsByName('axis-label-container-layer-0')[0] as IGroup;
expect(firstLabel.attribute.textBaseline).toBe('top');
expect(firstLabel.attribute.y + firstLabel.attribute.dy).toBe(firstLayer.AABBBounds.y1);
});
});
});
16 changes: 14 additions & 2 deletions packages/vrender-components/src/axis/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ export abstract class AxisBase<T extends AxisBaseAttributes> extends AbstractCom
protected data: TransformedAxisItem[] = [];
protected tickLineItems: TickLineItem[] = [];
protected subTickLineItems: TickLineItem[] = [];
protected axisLabelLayerSize: Dict<{ width: number; height: number; textAlign: string; textBaseline: string }> = {};
protected axisLabelLayerSize: Dict<{
width: number;
height: number;
textAlign: string;
textBaseline: string;
labelPos: number;
}> = {};
protected axisLabelsContainer: IGroup | null = null;
protected axisContainer: IGroup;

Expand Down Expand Up @@ -203,8 +209,10 @@ export abstract class AxisBase<T extends AxisBaseAttributes> extends AbstractCom
let maxTextHeight = 0;
let textAlign = 'center';
let textBaseline = 'middle';
labels.forEach((label: IText) => {
let labelPos: number = 0;
labels.forEach((label: IText, index) => {
const labelStyle = label.attribute;

const angle = labelStyle.angle ?? 0;
const textBounds = label.AABBBounds;
let textWidth = textBounds.width();
Expand All @@ -218,11 +226,15 @@ export abstract class AxisBase<T extends AxisBaseAttributes> extends AbstractCom

textAlign = labelStyle.textAlign as string;
textBaseline = labelStyle.textBaseline as string;
if (index === 0) {
labelPos = labelStyle.x;
}
});
this.axisLabelLayerSize[layer] = {
width: maxTextWidth,
height: maxTextHeight,

labelPos,
textAlign,
textBaseline
};
Expand Down
Loading

0 comments on commit 6313aff

Please sign in to comment.