Browse Source

feat(watermark): Image loading abnormal display text watermark (#40770)

pull/40971/head
originRing 2 years ago
committed by GitHub
parent
commit
1130bf01ea
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      components/watermark/__tests__/__snapshots__/index.test.tsx.snap
  2. 11
      components/watermark/__tests__/index.test.tsx
  3. 19
      components/watermark/index.en-US.md
  4. 54
      components/watermark/index.tsx
  5. 19
      components/watermark/index.zh-CN.md

13
components/watermark/__tests__/__snapshots__/index.test.tsx.snap

@ -26,6 +26,19 @@ exports[`Watermark Interleaved watermark backgroundSize is correct 1`] = `
</div>
`;
exports[`Watermark Invalid image watermark 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
>
<div
style="z-index: 9; position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; background-repeat: repeat; background-position: 0px 0px; background-image: url('data:image/png;base64,00'); background-size: 440px;"
/>
</div>
</div>
`;
exports[`Watermark MutationObserver should work properly 1`] = `
<div>
<div

11
components/watermark/__tests__/index.test.tsx

@ -64,6 +64,17 @@ describe('Watermark', () => {
expect(container).toMatchSnapshot();
});
it('Invalid image watermark', () => {
mockSrcSet.mockImplementation(function fn() {
this.onerror?.();
});
const { container } = render(
<Watermark className="watermark" content="Ant Design" image="https://test.svg" />,
);
expect(container.querySelector('.watermark div')).toBeTruthy();
expect(container).toMatchSnapshot();
});
it('MutationObserver should work properly', async () => {
const { container } = render(<Watermark className="watermark" content="MutationObserver" />);
const target = container.querySelector<HTMLDivElement>('.watermark div');

19
components/watermark/index.en-US.md

@ -33,7 +33,7 @@ Add specific text or patterns to the page.
| height | The height of the watermark, the default value of `content` is its own height | number | 64 | |
| rotate | When the watermark is drawn, the rotation Angle, unit `°` | number | -22 | |
| zIndex | The z-index of the appended watermark element | number | 9 | |
| image | Image source, it is recommended to export 2x or 3x image, high priority | string | - | |
| image | Image source, it is recommended to export 2x or 3x image, high priority (support base64 format) | string | - | |
| content | Watermark text content | string \| string[] | - | |
| font | Text style | [Font](#font) | [Font](#font) | |
| gap | The spacing between watermarks | \[number, number\] | \[100, 100\] | |
@ -49,3 +49,20 @@ Add specific text or patterns to the page.
| fontWeight | font weight | `normal` \| `light` \| `weight` \| number | normal | |
| fontFamily | font family | string | sans-serif | |
| fontStyle | font style | `none` \| `normal` \| `italic` \| `oblique` | normal | |
## FAQ
### Handle abnormal image watermarks
When using an image watermark and the image loads abnormally, you can add `content` at the same time to prevent the watermark from becoming invalid (since 5.2.3).
```typescript jsx
<Watermark
height={30}
width={130}
content="Ant Design"
image="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*lkAoRbywo0oAAAAAAAAAAAAADrJ8AQ/original"
>
<div style={{ height: 500 }} />
</Watermark>
```

54
components/watermark/index.tsx

@ -164,6 +164,27 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
});
};
const drawText = (
canvas: HTMLCanvasElement,
ctx: CanvasRenderingContext2D,
drawX: number,
drawY: number,
drawWidth: number,
drawHeight: number,
alternateRotateX: number,
alternateRotateY: number,
alternateDrawX: number,
alternateDrawY: number,
markWidth: number,
) => {
fillTexts(ctx, drawX, drawY, drawWidth, drawHeight);
/** Fill the interleaved text after rotation */
ctx.restore();
rotateWatermark(ctx, alternateRotateX, alternateRotateY, rotate);
fillTexts(ctx, alternateDrawX, alternateDrawY, drawWidth, drawHeight);
appendWatermark(canvas.toDataURL(), markWidth);
};
const renderWatermark = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
@ -205,16 +226,37 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
ctx.drawImage(img, alternateDrawX, alternateDrawY, drawWidth, drawHeight);
appendWatermark(canvas.toDataURL(), markWidth);
};
img.onerror = () =>
drawText(
canvas,
ctx,
drawX,
drawY,
drawWidth,
drawHeight,
alternateRotateX,
alternateRotateY,
alternateDrawX,
alternateDrawY,
markWidth,
);
img.crossOrigin = 'anonymous';
img.referrerPolicy = 'no-referrer';
img.src = image;
} else {
fillTexts(ctx, drawX, drawY, drawWidth, drawHeight);
/** Fill the interleaved text after rotation */
ctx.restore();
rotateWatermark(ctx, alternateRotateX, alternateRotateY, rotate);
fillTexts(ctx, alternateDrawX, alternateDrawY, drawWidth, drawHeight);
appendWatermark(canvas.toDataURL(), markWidth);
drawText(
canvas,
ctx,
drawX,
drawY,
drawWidth,
drawHeight,
alternateRotateX,
alternateRotateY,
alternateDrawX,
alternateDrawY,
markWidth,
);
}
}
};

19
components/watermark/index.zh-CN.md

@ -34,7 +34,7 @@ demo:
| height | 水印的高度,`content` 的默认值为自身的高度 | number | 64 | |
| rotate | 水印绘制时,旋转的角度,单位 `°` | number | -22 | |
| zIndex | 追加的水印元素的 z-index | number | 9 | |
| image | 图片源,建议导出 2 倍或 3 倍图,优先级高 | string | - | |
| image | 图片源,建议导出 2 倍或 3 倍图,优先级高 (支持 base64 格式) | string | - | |
| content | 水印文字内容 | string \| string[] | - | |
| font | 文字样式 | [Font](#font) | [Font](#font) | |
| gap | 水印之间的间距 | \[number, number\] | \[100, 100\] | |
@ -50,3 +50,20 @@ demo:
| fontWeight | 字体粗细 | `normal` \| `light` \| `weight` \| number | normal | |
| fontFamily | 字体类型 | string | sans-serif | |
| fontStyle | 字体样式 | `none` \| `normal` \| `italic` \| `oblique` | normal | |
## FAQ
### 处理异常图片水印
当使用图片水印且图片加载异常时,可以同时添加 `content` 防止水印失效(自 5.2.3 开始支持)。
```typescript jsx
<Watermark
height={30}
width={130}
content="Ant Design"
image="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*lkAoRbywo0oAAAAAAAAAAAAADrJ8AQ/original"
>
<div style={{ height: 500 }} />
</Watermark>
```

Loading…
Cancel
Save