React page watermark implementation
1. Why SVG instead of Cavans?
Because cavans in high resolution screen, need to do according to devicePixelRatio width and height adaptation, otherwise it will be very fuzzy, and SVG is a vector graph, native support for various resolutions, will not produce fuzzy situation.
-
Use the sample
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import WaterMarkContent from './components/WaterMarkContent'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<WaterMarkContent>
<App />
</WaterMarkContent>
</React.StrictMode>.document.getElementById('root'))Copy the code
2. Implementation process
- Construct a watermark diagram
- Spread the watermark image all over the container
- Watermark component: Supports sub-component content slots
Construct an SVG watermark
const { text = 'waterMark', fontSize = 16, fillOpacity = '0.2', fillColor = '# 000' } = props
const res = `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="180px" height="180px" viewBox="0 0 180 180">
<text x="-100" y="-30" fill='${fillColor}' transform = "rotate(-35 220 -220)" fill-opacity='${fillOpacity}' font-size='${fontSize}'> ${text}</text>
</svg>`
Copy the code
From the above code, we can get an SVG XML string, which we can then turn into a URL resource
const blob = new Blob([res], {
type: 'image/svg+xml',})const url = URL.createObjectURL(blob)
Copy the code
From this, we have an SVG resource address, which we now use in the div background image
<div
style={{
position: 'absolute'.width: '100%'.height: '100%'.backgroundImage: `url(${url}) `.top: 0.left: 0.zIndex: 999.pointerEvents: 'none'.// Click Through
}}
></div>
Copy the code
At this point, we easily have a watermarked DIV. Let’s assemble the code and encapsulate it as a component.
3. Component code
import React from 'react'
import { ReactNode, useMemo } from 'react'
typesvgPropsType = { text? :stringfontSize? :numberfillOpacity? :numberfillColor? :string
}
const SvgTextBg = (props: svgPropsType) = > {
const { text = 'waterMark', fontSize = 16, fillOpacity = '0.2', fillColor = '# 000' } = props
const res = `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="180px" height="180px" viewBox="0 0 180 180">
<text x="-100" y="-30" fill='${fillColor}' transform = "rotate(-35 220 -220)" fill-opacity='${fillOpacity}' font-size='${fontSize}'> ${text}</text>
</svg>`
const blob = new Blob([res], {
type: 'image/svg+xml',})const url = URL.createObjectURL(blob)
return (
<div
style={{
position: 'absolute',
width: '100% ',height: '100% ',backgroundImage: `url(${url`}),top: 0.left: 0.zIndex: 999.pointerEvents: 'none', // Click through}} ></div>)}typepropsType = { children? : ReactNode } & Partial<svgPropsType>const WaterMarkContent = (props: propsType) = > {
const { text, fontSize, fillOpacity, fillColor } = props
const memoInfo = useMemo(
() = > ({
text,
fontSize,
fillOpacity,
fillColor,
}),
[text, fontSize, fillOpacity, fillColor]
)
return (
<div style={{ position: 'relative', width: '100% ',height: ' 100'}} % >
{props.children}
<SvgTextBg {. memoInfo} / >
</div>)}export default WaterMarkContent
Copy the code