feat: 优化泡泡玛特的图表

This commit is contained in:
R524809
2026-09-10 17:44:09 +08:00
parent a6387f8220
commit 417116b928
14 changed files with 327 additions and 299 deletions
+55 -36
View File
@@ -1,16 +1,45 @@
import { col } from '../csv.js';
import {
PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, legendStyle,
financialViewLabel,
financialViewLabel, niceAxisMax, fanTinyLabelOffsets, stackedSharePoint,
lineSeries, footnote, watermarks, LAYOUT,
} from '../theme.js';
const KEYS = ['cash_like', 'receivables', 'investment', 'operating_assets'];
const NAMES = {
cash_like: '类现金',
receivables: '应收账款',
investment: '投资资产',
operating_assets: '经营类资产',
};
const COLORS = {
cash_like: PALETTE.blue,
receivables: PALETTE.orange,
investment: PALETTE.purple,
operating_assets: PALETTE.sage,
};
// 段内标签文字色:浅色段(经营类资产灰绿)用深字,深色段用白字
const INSIDE_LABEL_COLORS = {
cash_like: '#fff',
receivables: '#fff',
investment: '#fff',
operating_assets: PALETTE.ink,
};
/**
* 泡泡玛特资产结构演变图
* 堆叠柱状图展示资产配置,折线图展示总资产增长
* 堆叠柱状图展示资产配置(每段标数值),折线图展示总资产增长
*/
export function assetsChart(rows, { width, height, view = 'all' }) {
const periods = col(rows, 'period');
const totalMax = Math.max(...rows.map((r) => r.total_assets));
// 轴上限随数据走(2025H2 总资产已 321 亿),矮段像素判定才有确定基准
const axisMax = niceAxisMax(totalMax);
const interval = axisMax % 7 === 0 ? axisMax / 7 : axisMax / 5;
// 绘图区像素高:画布高 − grid top 145 − grid bottom 90
const pxPerUnit = (height - LAYOUT.gridTop - 90) / axisMax;
// 早期年份应收/投资不足 1 亿,矮段标签外置到柱体右侧扇形排开
const rowOffsets = fanTinyLabelOffsets(rows, KEYS, pxPerUnit);
return {
backgroundColor: '#fff',
@@ -22,7 +51,7 @@ export function assetsChart(rows, { width, height, view = 'all' }) {
legend: {
...legendStyle,
top: LAYOUT.legendTop,
data: ['类现金', '应收账款', '投资资产', '经营类资产', '资产总计'],
data: [...KEYS.map((key) => NAMES[key]), '资产总计'],
},
grid: { left: 78, right: 82, top: LAYOUT.gridTop, bottom: 90 },
tooltip: {
@@ -40,8 +69,8 @@ export function assetsChart(rows, { width, height, view = 'all' }) {
nameGap: 52,
nameTextStyle: { color: PALETTE.grey, fontSize: 13, fontFamily: FONT },
min: 0,
max: 350,
interval: 50,
max: axisMax,
interval,
},
{
...axisCommon,
@@ -52,44 +81,34 @@ export function assetsChart(rows, { width, height, view = 'all' }) {
nameRotate: -90,
nameTextStyle: { color: PALETTE.grey, fontSize: 13, fontFamily: FONT },
min: 0,
max: 350,
interval: 50,
max: axisMax,
interval,
splitLine: { show: false },
},
],
series: [
{
name: '类现金',
...KEYS.map((key, ci) => ({
name: NAMES[key],
type: 'bar',
stack: 'assets',
data: col(rows, 'cash_like'),
itemStyle: { color: PALETTE.blue },
// 每段都标数值:矮段塞不进字的,外置到柱体右侧(机制同渠道金额图)
data: rows.map((row, ri) => stackedSharePoint(row[key], {
pxPerUnit,
labelColor: INSIDE_LABEL_COLORS[key],
dy: rowOffsets[ri][ci] ?? 0,
})),
itemStyle: { color: COLORS[key] },
emphasis: { focus: 'series' },
},
{
name: '应收账款',
type: 'bar',
stack: 'assets',
data: col(rows, 'receivables'),
itemStyle: { color: PALETTE.orange },
emphasis: { focus: 'series' },
},
{
name: '投资资产',
type: 'bar',
stack: 'assets',
data: col(rows, 'investment'),
itemStyle: { color: PALETTE.purple },
emphasis: { focus: 'series' },
},
{
name: '经营类资产',
type: 'bar',
stack: 'assets',
data: col(rows, 'operating_assets'),
itemStyle: { color: PALETTE.sage },
emphasis: { focus: 'series' },
},
label: {
show: true,
position: 'inside',
color: INSIDE_LABEL_COLORS[key],
fontSize: 11,
fontFamily: FONT,
overflow: 'none',
formatter: (p) => `${p.value.toFixed(1)}`,
},
})),
{
...lineSeries({
name: '资产总计',