1- import React , { useEffect , useState } from 'react' ;
1+ import React , { useEffect , useMemo , useState } from 'react' ;
22
33interface WatermarkProps {
44 text : string ;
55 fontSize ?: number ;
66 fontFamily ?: string ;
7+ fontWeight ?: string ;
78 textColor ?: string ;
89 rotate ?: number ;
910 zIndex ?: number ;
1011 theme ?: 'light' | 'dark' ;
12+ density ?: number ;
1113}
1214
1315const Watermark : React . FC < WatermarkProps > = ( {
1416 text,
15- fontSize = 16 ,
17+ fontSize = 20 ,
1618 fontFamily = 'Arial' ,
1719 textColor = 'rgba(0, 0, 0, 0.1)' ,
1820 rotate = - 45 ,
1921 zIndex = 9999 ,
2022 theme = 'light' ,
23+ fontWeight = 'bold' ,
24+ density = 1 ,
2125} ) => {
22- const [ watermarkUrl , setWatermarkUrl ] = useState < string > ( '' ) ;
26+ const [ dimensions , setDimensions ] = useState ( { width : window . innerWidth , height : window . innerHeight } ) ;
2327
2428 useEffect ( ( ) => {
29+ const handleResize = ( ) => {
30+ setDimensions ( {
31+ width : window . innerWidth ,
32+ height : window . innerHeight ,
33+ } ) ;
34+ } ;
35+
36+ window . addEventListener ( 'resize' , handleResize ) ;
37+ return ( ) => window . removeEventListener ( 'resize' , handleResize ) ;
38+ } , [ ] ) ;
39+
40+ const watermarkDataUrl = useMemo ( ( ) => {
2541 const canvas = document . createElement ( 'canvas' ) ;
2642 const context = canvas . getContext ( '2d' ) ;
2743
2844 if ( context ) {
2945 const scale = window . devicePixelRatio ;
30- canvas . width = 300 * scale ;
31- canvas . height = 150 * scale ;
46+ canvas . width = dimensions . width * scale ;
47+ canvas . height = dimensions . height * scale ;
3248 context . scale ( scale , scale ) ;
3349
34- context . font = `${ fontSize } px ${ fontFamily } ` ;
50+ context . font = `${ fontWeight } ${ fontSize } px ${ fontFamily } ` ;
3551 context . fillStyle = theme === 'light' ? textColor : 'rgba(255, 255, 255, 0.1)' ;
3652 context . rotate ( ( rotate * Math . PI ) / 180 ) ;
3753 context . fillText ( text , 0 , 100 ) ;
3854
39- setWatermarkUrl ( canvas . toDataURL ( ) ) ;
55+ const metrics = context . measureText ( text ) ;
56+ const textWidth = metrics . width ;
57+ const textHeight = fontSize ;
58+
59+ const spacingX = ( textWidth + 180 ) / density ;
60+ const spacingY = ( textHeight + 180 ) / density ;
61+
62+ for ( let y = - canvas . height ; y < canvas . height * 2 ; y += spacingY ) {
63+ for ( let x = - canvas . width ; x < canvas . width * 2 ; x += spacingX ) {
64+ context . fillText ( text , x , y ) ;
65+ }
66+ }
67+ return canvas . toDataURL ( ) ;
4068 }
41- } , [ text , fontSize , fontFamily , textColor , rotate , theme ] ) ;
69+ return '' ;
70+ } , [ density , dimensions . height , dimensions . width , fontFamily , fontSize , fontWeight , rotate , text , textColor , theme ] ) ;
4271
4372 return (
4473 < div
@@ -50,7 +79,7 @@ const Watermark: React.FC<WatermarkProps> = ({
5079 height : '100%' ,
5180 zIndex,
5281 pointerEvents : 'none' ,
53- backgroundImage : `url(${ watermarkUrl } )` ,
82+ backgroundImage : `url(${ watermarkDataUrl } )` ,
5483 backgroundRepeat : 'repeat' ,
5584 } }
5685 />
0 commit comments