update at 2026-01-21 21:48:08

This commit is contained in:
douboer@gmail.com
2026-01-21 21:48:08 +08:00
parent 54f3fd93f2
commit 78d8801a07
8 changed files with 184 additions and 271 deletions

View File

@@ -10,8 +10,6 @@ import {
annularSectorCentroid,
annularSectorPath,
annularSectorInsetPath,
calculateLabelRotation,
generateSectorColor,
generateTextPath,
generateVerticalTextPath,
getTextColorForBackground,
@@ -142,73 +140,6 @@ describe('annularSectorPath', () => {
});
});
describe('calculateLabelRotation', () => {
it('应该在上半圆不进行翻转', () => {
expect(calculateLabelRotation(0)).toBe(0);
expect(calculateLabelRotation(45)).toBe(45);
expect(calculateLabelRotation(90)).toBe(90);
expect(calculateLabelRotation(180)).toBe(180);
});
it('应该在下半圆翻转180°避免倒字', () => {
expect(calculateLabelRotation(181)).toBe(361); // 181 + 180
expect(calculateLabelRotation(270)).toBe(450); // 270 + 180
expect(calculateLabelRotation(359)).toBe(539); // 359 + 180
});
it('应该在边界值正确处理', () => {
expect(calculateLabelRotation(180)).toBe(180); // 等于180不翻转
expect(calculateLabelRotation(360)).toBe(360); // 等于360不翻转
});
});
describe('generateSectorColor', () => {
it('应该生成有效的 HSL 颜色', () => {
const color = generateSectorColor(0, 0);
expect(color).toMatch(/^hsl\(\d+(\.\d+)? \d+% \d+%\)$/);
});
it('应该根据层索引改变亮度', () => {
const color1 = generateSectorColor(0, 0);
const color2 = generateSectorColor(1, 0);
const color3 = generateSectorColor(2, 0);
// 提取亮度值
const light1 = parseInt(color1.match(/(\d+)%\)$/)?.[1] || '0');
const light2 = parseInt(color2.match(/(\d+)%\)$/)?.[1] || '0');
const light3 = parseInt(color3.match(/(\d+)%\)$/)?.[1] || '0');
expect(light1).toBeGreaterThan(light2);
expect(light2).toBeGreaterThan(light3);
});
it('应该根据扇区索引改变色相', () => {
const color1 = generateSectorColor(0, 0);
const color2 = generateSectorColor(0, 6);
// 提取色相值
const hue1 = parseInt(color1.match(/^hsl\((\d+(\.\d+)?)/)?.[1] || '0');
const hue2 = parseInt(color2.match(/^hsl\((\d+(\.\d+)?)/)?.[1] || '0');
expect(hue1).not.toBe(hue2);
});
it('应该为单层生成颜色', () => {
const color = generateSectorColor(0, 0, 1, 24);
expect(color).toMatch(/^hsl\(\d+(\.\d+)? \d+% \d+%\)$/);
});
it('应该处理大量层数', () => {
const color1 = generateSectorColor(0, 0, 31, 24);
const color2 = generateSectorColor(30, 0, 31, 24);
const light1 = parseInt(color1.match(/(\d+)%\)$/)?.[1] || '0');
const light2 = parseInt(color2.match(/(\d+)%\)$/)?.[1] || '0');
expect(light1).toBeGreaterThan(light2);
});
});
describe('annularSectorInsetPath', () => {
it('应该生成内缩路径', () => {
const path = annularSectorInsetPath(50, 100, 0, 90, 2);
@@ -236,33 +167,33 @@ describe('annularSectorInsetPath', () => {
describe('generateTextPath', () => {
it('应该生成正向文字路径', () => {
const path = generateTextPath(50, 100, 0, 90, false, 'middle', 12);
const path = generateTextPath(50, 100, 0, 90, 'middle');
expect(path).toContain('M ');
expect(path).toContain('A ');
expect(path).toContain('0 1'); // 正向扫描
});
it('应该生成反向文字路径', () => {
const path = generateTextPath(50, 100, 0, 90, true, 'middle', 12);
const path = generateTextPath(50, 100, 120, 240, 'middle');
expect(path).toContain('M ');
expect(path).toContain('A ');
expect(path).toContain('0 0'); // 反向扫描
});
it('应该在 centroid 模式下使用形心半径', () => {
const pathCentroid = generateTextPath(50, 100, 0, 90, false, 'centroid', 12);
const pathMiddle = generateTextPath(50, 100, 0, 90, false, 'middle', 12);
const pathCentroid = generateTextPath(50, 100, 0, 90, 'centroid');
const pathMiddle = generateTextPath(50, 100, 0, 90, 'middle');
expect(pathCentroid).not.toBe(pathMiddle);
});
it('应该处理跨越360°的扇区', () => {
const path = generateTextPath(50, 100, 315, 45, false, 'middle', 12);
const path = generateTextPath(50, 100, 315, 45, 'middle');
expect(path).toContain('M ');
expect(path).toContain('A ');
});
it('应该处理大角度扇区', () => {
const path = generateTextPath(50, 100, 0, 270, false, 'middle', 12);
const path = generateTextPath(50, 100, 0, 270, 'middle');
expect(path).toContain('M ');
expect(path).toContain('A ');
});
@@ -270,25 +201,25 @@ describe('generateTextPath', () => {
describe('generateVerticalTextPath', () => {
it('应该生成竖排文字路径', () => {
const path = generateVerticalTextPath(50, 100, 0, 30, 15, 'middle', 12);
const path = generateVerticalTextPath(50, 100, 0, 30, 'middle');
expect(path).toContain('M ');
expect(path).toContain('L ');
});
it('应该在 centroid 模式下使用形心', () => {
const pathCentroid = generateVerticalTextPath(50, 100, 0, 30, 15, 'centroid', 12);
const pathMiddle = generateVerticalTextPath(50, 100, 0, 30, 15, 'middle', 12);
const pathCentroid = generateVerticalTextPath(50, 100, 0, 30, 'centroid');
const pathMiddle = generateVerticalTextPath(50, 100, 0, 30, 'middle');
expect(pathCentroid).not.toBe(pathMiddle);
});
it('应该处理不同的角度', () => {
const path1 = generateVerticalTextPath(50, 100, 0, 30, 15, 'middle', 12);
const path2 = generateVerticalTextPath(50, 100, 0, 30, 180, 'middle', 12);
const path1 = generateVerticalTextPath(50, 100, 0, 30, 'middle');
const path2 = generateVerticalTextPath(50, 100, 150, 180, 'middle');
expect(path1).not.toBe(path2);
});
it('应该处理窄扇区', () => {
const path = generateVerticalTextPath(80, 100, 0, 10, 5, 'middle', 12);
const path = generateVerticalTextPath(80, 100, 0, 10, 'middle');
expect(path).toContain('M ');
expect(path).toContain('L ');
});
@@ -296,22 +227,17 @@ describe('generateVerticalTextPath', () => {
describe('getTextColorForBackground', () => {
it('应该为深色背景返回白色', () => {
const color = getTextColorForBackground('hsl(180 70% 25%)');
const color = getTextColorForBackground('#111111');
expect(color).toBe('#ffffff');
});
it('应该为浅色背景返回深色', () => {
const color = getTextColorForBackground('hsl(180 70% 85%)');
const color = getTextColorForBackground('#f9fafb');
expect(color).toBe('#111827');
});
it('应该处理边界值50%', () => {
const color = getTextColorForBackground('hsl(180 70% 50%)');
expect(color).toBe('#111827');
});
it('应该处理边界值49%', () => {
const color = getTextColorForBackground('hsl(180 70% 49%)');
it('应该支持 HSL 输入', () => {
const color = getTextColorForBackground('hsl(180 70% 25%)');
expect(color).toBe('#ffffff');
});