This document outlines the steps to create Watermark
component styled withTailwind CSS and using some npm dependency libraries.
Node.js
and npm
installed on your machine.Tailwind CSS
installed in your project.CVA(class-variance-authority)
is a utility for managing CSS class names based on various conditions.clsx
is a tiny utility for constructing className strings conditionally.1// watermark.component.tsx
2import clsx from "clsx";
3import { useEffect, useRef } from "react";
4
5export interface WatermarkProps {
6 children: React.ReactNode;
7 text: string;
8 width: number;
9 height: number;
10 color?: string;
11 className?: string;
12}
13
14const Watermark: React.FC<WatermarkProps> = ({
15 text,
16 width,
17 height,
18 color = "#000",
19 children,
20 className,
21}) => {
22 const watermarkRef = useRef<HTMLDivElement>(null);
23
24 useEffect(() => {
25 const updateWatermark = () => {
26 const container = watermarkRef.current!;
27
28 const textCoords = [0, height - 20];
29 const rotate = -20;
30
31 const canvas = document.createElement("canvas");
32 canvas.setAttribute("width", `${width}px`);
33 canvas.setAttribute("height", `${height}px`);
34 const ctx = canvas.getContext("2d")!;
35 ctx.globalAlpha = 0.1;
36 ctx.textAlign = "left";
37 ctx.textBaseline = "bottom";
38 ctx.font = "16px Arial";
39 ctx.fillStyle = color;
40 ctx.rotate((Math.PI / 180) * rotate);
41 ctx.fillText(text, textCoords[0], textCoords[1]);
42
43 const base64Url = canvas.toDataURL();
44
45 const watermarkDiv =
46 container.querySelector(".__wm") || document.createElement("div");
47 const styleStr = `
48 position: absolute;
49 top: 0;
50 left: 0;
51 width: 100%;
52 height: 100%;
53 pointer-events: none;
54 background-repeat: repeat;
55 background-image: url('${base64Url}')
56 `;
57 watermarkDiv.setAttribute("style", styleStr);
58 watermarkDiv.classList.add("__wm");
59
60 if (!container.querySelector(".__wm")) {
61 container.appendChild(watermarkDiv);
62 }
63 };
64
65 updateWatermark();
66 }, [text, color, width, height]);
67
68 return (
69 <div ref={watermarkRef} className={cn("relative", className)}>
70 {children}
71 </div>
72 );
73};
74
75export default Watermark;
76