fix(components): [watermark] resolve text clipping caused by textAlign (#21639)

* fix(components): [watermark] resolve text clipping caused by textAlign

* refactor(components): [watermark] update based on review feeddback

* fix: update
This commit is contained in:
Zhong
2025-08-06 17:55:33 +08:00
committed by GitHub
parent 99dacaaaec
commit 2d089b19d1
2 changed files with 19 additions and 6 deletions

View File

@@ -4,6 +4,15 @@ import type { WatermarkProps } from './watermark'
export const FontGap = 3
// [alignRatio, spaceRatio]
const TEXT_ALIGN_RATIO_MAP = {
left: [0, 0.5],
start: [0, 0.5],
center: [0.5, 0],
right: [1, -0.5],
end: [1, -0.5],
} as const
function prepareCanvas(
width: number,
height: number,
@@ -39,7 +48,8 @@ export default function useClips() {
height: number,
font: Required<NonNullable<WatermarkProps['font']>>,
gapX: number,
gapY: number
gapY: number,
space: number
): [dataURL: string, finalWidth: number, finalHeight: number] {
// ================= Text / Image =================
const [ctx, canvas, contentWidth, contentHeight] = prepareCanvas(
@@ -70,9 +80,10 @@ export default function useClips() {
ctx.textBaseline = textBaseline
const contents = isArray(content) ? content : [content]
contents?.forEach((item, index) => {
const [alignRatio, spaceRatio] = TEXT_ALIGN_RATIO_MAP[textAlign]
ctx.fillText(
item ?? '',
contentWidth / 2,
contentWidth * alignRatio + space * spaceRatio,
index * (mergedFontSize + FontGap * ratio)
)
})

View File

@@ -112,6 +112,7 @@ const appendWatermark = (base64Url: string, markWidth: number) => {
const getMarkSize = (ctx: CanvasRenderingContext2D) => {
let defaultWidth = 120
let defaultHeight = 64
let space = 0
const { image, content, width, height, rotate } = props
@@ -144,12 +145,12 @@ const getMarkSize = (ctx: CanvasRenderingContext2D) => {
maxHeight * contents.length + (contents.length - 1) * FontGap
const angle = (Math.PI / 180) * Number(rotate)
const space = Math.ceil(Math.abs(Math.sin(angle) * defaultHeight) / 2)
space = Math.ceil(Math.abs(Math.sin(angle) * defaultHeight) / 2)
defaultWidth += space
}
return [width ?? defaultWidth, height ?? defaultHeight] as const
return [width ?? defaultWidth, height ?? defaultHeight, space] as const
}
const getClips = useClips()
@@ -167,7 +168,7 @@ const renderWatermark = () => {
}
const ratio = getPixelRatio()
const [markWidth, markHeight] = getMarkSize(ctx)
const [markWidth, markHeight, space] = getMarkSize(ctx)
const drawCanvas = (
drawContent?: NonNullable<WatermarkProps['content']> | HTMLImageElement
@@ -188,7 +189,8 @@ const renderWatermark = () => {
textBaseline: textBaseline.value,
},
gapX.value,
gapY.value
gapY.value,
space
)
appendWatermark(textClips, clipWidth)