mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
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:
@@ -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)
|
||||
)
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user