e4e3ca83be2164fbad63681c8387286e5c4bd39ccd9d33ac6268df583e42393cceaa35c9474382116dcac149a2364d1d32eb85acaeda3043e795663b39224c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { isArray } from '@vue/shared';
  2. const FontGap = 3;
  3. const TEXT_ALIGN_RATIO_MAP = {
  4. left: [0, 0.5],
  5. start: [0, 0.5],
  6. center: [0.5, 0],
  7. right: [1, -0.5],
  8. end: [1, -0.5]
  9. };
  10. function prepareCanvas(width, height, ratio = 1) {
  11. const canvas = document.createElement("canvas");
  12. const ctx = canvas.getContext("2d");
  13. const realWidth = width * ratio;
  14. const realHeight = height * ratio;
  15. canvas.setAttribute("width", `${realWidth}px`);
  16. canvas.setAttribute("height", `${realHeight}px`);
  17. ctx.save();
  18. return [ctx, canvas, realWidth, realHeight];
  19. }
  20. function useClips() {
  21. function getClips(content, rotate, ratio, width, height, font, gapX, gapY, space) {
  22. const [ctx, canvas, contentWidth, contentHeight] = prepareCanvas(width, height, ratio);
  23. if (content instanceof HTMLImageElement) {
  24. ctx.drawImage(content, 0, 0, contentWidth, contentHeight);
  25. } else {
  26. const {
  27. color,
  28. fontSize,
  29. fontStyle,
  30. fontWeight,
  31. fontFamily,
  32. textAlign,
  33. textBaseline
  34. } = font;
  35. const mergedFontSize = Number(fontSize) * ratio;
  36. ctx.font = `${fontStyle} normal ${fontWeight} ${mergedFontSize}px/${height}px ${fontFamily}`;
  37. ctx.fillStyle = color;
  38. ctx.textAlign = textAlign;
  39. ctx.textBaseline = textBaseline;
  40. const contents = isArray(content) ? content : [content];
  41. contents == null ? void 0 : contents.forEach((item, index) => {
  42. const [alignRatio, spaceRatio] = TEXT_ALIGN_RATIO_MAP[textAlign];
  43. ctx.fillText(item != null ? item : "", contentWidth * alignRatio + space * spaceRatio, index * (mergedFontSize + FontGap * ratio));
  44. });
  45. }
  46. const angle = Math.PI / 180 * Number(rotate);
  47. const maxSize = Math.max(width, height);
  48. const [rCtx, rCanvas, realMaxSize] = prepareCanvas(maxSize, maxSize, ratio);
  49. rCtx.translate(realMaxSize / 2, realMaxSize / 2);
  50. rCtx.rotate(angle);
  51. if (contentWidth > 0 && contentHeight > 0) {
  52. rCtx.drawImage(canvas, -contentWidth / 2, -contentHeight / 2);
  53. }
  54. function getRotatePos(x, y) {
  55. const targetX = x * Math.cos(angle) - y * Math.sin(angle);
  56. const targetY = x * Math.sin(angle) + y * Math.cos(angle);
  57. return [targetX, targetY];
  58. }
  59. let left = 0;
  60. let right = 0;
  61. let top = 0;
  62. let bottom = 0;
  63. const halfWidth = contentWidth / 2;
  64. const halfHeight = contentHeight / 2;
  65. const points = [
  66. [0 - halfWidth, 0 - halfHeight],
  67. [0 + halfWidth, 0 - halfHeight],
  68. [0 + halfWidth, 0 + halfHeight],
  69. [0 - halfWidth, 0 + halfHeight]
  70. ];
  71. points.forEach(([x, y]) => {
  72. const [targetX, targetY] = getRotatePos(x, y);
  73. left = Math.min(left, targetX);
  74. right = Math.max(right, targetX);
  75. top = Math.min(top, targetY);
  76. bottom = Math.max(bottom, targetY);
  77. });
  78. const cutLeft = left + realMaxSize / 2;
  79. const cutTop = top + realMaxSize / 2;
  80. const cutWidth = right - left;
  81. const cutHeight = bottom - top;
  82. const realGapX = gapX * ratio;
  83. const realGapY = gapY * ratio;
  84. const filledWidth = (cutWidth + realGapX) * 2;
  85. const filledHeight = cutHeight + realGapY;
  86. const [fCtx, fCanvas] = prepareCanvas(filledWidth, filledHeight);
  87. function drawImg(targetX = 0, targetY = 0) {
  88. fCtx.drawImage(rCanvas, cutLeft, cutTop, cutWidth, cutHeight, targetX, targetY, cutWidth, cutHeight);
  89. }
  90. drawImg();
  91. drawImg(cutWidth + realGapX, -cutHeight / 2 - realGapY / 2);
  92. drawImg(cutWidth + realGapX, +cutHeight / 2 + realGapY / 2);
  93. return [fCanvas.toDataURL(), filledWidth / ratio, filledHeight / ratio];
  94. }
  95. return getClips;
  96. }
  97. export { FontGap, useClips as default };
  98. //# sourceMappingURL=useClips.mjs.map