size.ts 2.7 KB

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