size.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { computed, type ComputedRef } from "vue";
  2. import { config } from "../config";
  3. /**
  4. * 字号管理类
  5. * 用于处理文本大小的缩放和样式
  6. */
  7. class Size {
  8. // 预设的字号类名
  9. public names = [
  10. "text-xs",
  11. "text-sm",
  12. "text-md",
  13. "text-lg",
  14. "text-xl",
  15. "text-2xl",
  16. "text-3xl",
  17. "text-4xl",
  18. "text-5xl",
  19. "text-6xl",
  20. "text-7xl",
  21. "text-8xl",
  22. "text-9xl"
  23. ];
  24. // 对应的字号大小
  25. public sizes = [20, 24, 28, 32, 36, 44, 52, 60, 72, 84, 96, 120, 152];
  26. // 对应的行高
  27. public lineHeights = [28, 36, 44, 52, 52, 1, 1, 1, 1, 1, 1, 1, 1];
  28. // 原始类名
  29. public className: ComputedRef<string> = computed(() => "");
  30. // 计算后的类名
  31. public ptClassName: ComputedRef<string>;
  32. constructor(cb: (() => string) | null) {
  33. this.className = computed(cb ?? (() => ""));
  34. // 根据全局字号配置动态计算类名
  35. this.ptClassName = computed(() => {
  36. if (config.fontSize == null) {
  37. return this.className.value;
  38. }
  39. const name = this.names[this.getIndex()];
  40. return this.className.value.replace(`-important-${name}`, "").replace(name, "");
  41. });
  42. }
  43. /**
  44. * 获取全局字号缩放比例
  45. */
  46. getScale = () => {
  47. return config.fontSize ?? 1;
  48. };
  49. /**
  50. * 根据缩放比例计算rpx值
  51. * @param val - 需要转换的值
  52. */
  53. getRpx = (val: number | string) => {
  54. const scale = this.getScale();
  55. if (typeof val == "number") {
  56. return val * scale + "rpx";
  57. } else {
  58. const num = parseFloat(val);
  59. const unit = val.replace(`${num}`, "");
  60. return num * scale + unit;
  61. }
  62. };
  63. /**
  64. * 获取当前字号在预设中的索引
  65. */
  66. getIndex = () => {
  67. let index = this.names.findIndex((name) => {
  68. if (this.className.value.includes(name)) {
  69. return true;
  70. }
  71. return false;
  72. });
  73. // 默认使用 text-md (14px)
  74. if (index < 0) {
  75. index = 2;
  76. }
  77. return index;
  78. };
  79. /**
  80. * 获取最终的字号大小
  81. * @param size - 指定字号大小,为空则使用预设值
  82. */
  83. getSize = (size: number | string | null): null | string => {
  84. // 如果未设置全局字号,且未指定size,直接返回null;否则返回对应rpx值
  85. if (config.fontSize == null && size == null) {
  86. return null;
  87. }
  88. return this.getRpx(size ?? this.sizes[this.getIndex()]);
  89. };
  90. /**
  91. * 获取当前行高
  92. */
  93. getLineHeight = (): null | string => {
  94. // 未设置全局字号时返回null
  95. if (config.fontSize == null) {
  96. return null;
  97. }
  98. const lineHeight = this.lineHeights[this.getIndex()];
  99. return lineHeight == 1 ? `1` : this.getRpx(lineHeight);
  100. };
  101. }
  102. /**
  103. * 字号管理Hook
  104. * @param className - 类名
  105. */
  106. export function useSize(cb: (() => string) | null = null): Size {
  107. return new Size(cb);
  108. }