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.

  1. 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