亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

使用JS代碼實現(xiàn)頁面添加水印的方法詳解

 更新時間:2024年05月01日 07:54:10   作者:日升  
這篇文章主要介紹了使用80 行 JS 代碼實現(xiàn)頁面添加水印:文字水印、多行文字水印、圖片水印、文字&圖片水印,文中通過代碼示例給大家介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下

一、水印概括

1. 添加水印的好處

  • 信息標識: 水印可以用于標識文檔的所有者、保密級別、狀態(tài)或其他相關信息,幫助用戶更好地理解文檔內(nèi)容的屬性。
  • 版權保護: 在文檔中添加水印可以幫助保護內(nèi)容的版權,防止他人未經(jīng)授權地復制、轉(zhuǎn)載或篡改內(nèi)容。
  • 安全保護: 對于敏感信息或機密文檔,添加水印可以幫助防止信息泄露,提高文檔的安全性。
  • 提升專業(yè)性: 在一些場景下,如商業(yè)報告、合同文件等,添加水印可以增加文檔的專業(yè)性和正式性。
  • 防止截屏或拷貝: 在網(wǎng)頁中添加水印可以防止用戶通過截屏或復制粘貼等方式非法獲取文檔內(nèi)容。

2. 添加水印的壞處

  • 視覺干擾: 過多或過顯眼的水印可能會影響頁面的美觀度和可讀性,甚至干擾用戶對頁面內(nèi)容的瀏覽和理解。
  • 性能影響: 在頁面中添加水印可能會增加頁面加載時間和資源消耗,特別是對于大型或復雜的水印圖案或動態(tài)水印。
  • 用戶體驗: 一些用戶可能會認為水印對頁面內(nèi)容的查看和操作產(chǎn)生不必要的干擾,從而降低他們的使用體驗。
  • 不適用于移動端: 在移動設備上,屏幕空間有限,添加水印可能會占用寶貴的屏幕空間,影響用戶的閱讀和操作。

二、技術方案

1. watermark 第三方庫

優(yōu)勢:已有 github 庫,可直接使用 劣勢:

  • 庫比較老,多年未更新
  • 只支持圖片水印,不支持文案水印
  • 不支持多行水印
  • 包比較重,增加 SDK 負擔

2. JS 簡單實現(xiàn)水印功能

優(yōu)勢:

  • 可支持圖片和文案水印
  • 封裝函數(shù)即可,輕量 劣勢:需要自己封裝

三、水印功能實現(xiàn)

1. 水印功能需求

  • 需要支持文案和圖片
  • 可設置文案顏色字體等樣式
  • 可支持多行文字水印
  • 可動態(tài)控制水印間隔
  • 能鋪滿全屏
  • 可旋轉(zhuǎn)
  • 不影響頁面其他模塊背景展示

2. 功能實現(xiàn)

/**
 * 水印功能代碼實現(xiàn)
 */
interface IWarterMarkProps{
  text?: string | string[]  // 水印文案
  imgUrl?: string           // 水印圖片
  imageOpacity?: number     // 圖片透明度
  fontStyle?: string        // 字體樣式
  fontVariant?: string      // 字體變體
  fontWeight?: number       // 字體粗細
  fontFamily?: string       // 字體
  fontSize?: number         // 字體大小
  lineHeight?: number       // 字體行高
  fontColor?: string        // 字體顏色
  rotate?: number           // 水印旋轉(zhuǎn)角度 deg
  canvasRotate?: number     // canvas 旋轉(zhuǎn)角度 deg
  imageWidth?: number       // 圖片寬度
  imageHeight?: number      // 圖片高度
  xOffset?: number          // 水印 x 偏移
  yOffset?: number          // 水印 y 偏移
  width?: number            // 寬度
  height?: number           // 高度
  zIndex: number            // 層級
}
interface ISetDomProps{
  url: string               // 圖片 URL
  rotate?: number           // 水印旋轉(zhuǎn)角度
  zIndex?: number           // 層級
  width?: number            // 寬度
}
/**
 * 設置 dom CSS 屬性
 * @param {ISetDomProps} props dom 數(shù)據(jù)類型
 */
const setDomCSSAttr = (props: ISetDomProps) => {
  const {
    url, rotate = 0, zIndex = 10, width = 32
  } = props
  let waterMarker = document.getElementById('water-marker')
  let isInitDom = true
  if (!waterMarker) {
    isInitDom = false
    waterMarker = document.createElement('div')
    waterMarker.id = 'water-marker'
  }
  Object.assign(waterMarker.style, {
    transform: rotate ? `rotate(${rotate}deg)` : '',
    backgroundSize: `${width}px`,
    backgroundImage: `url(${url}), url(${url})`,
    backgroundRepeat: 'repeat',
    position: 'fixed',
    left: 0,
    top: 0,
    zIndex,
    width: '100vw',
    height: '100vh',
    pointerEvents: 'none',
    mixBlendMode: 'multiply'
  });
  !isInitDom && document.body.appendChild(waterMarker)
}

/**
 * 獲取 canvas 像素比
 * @param {CanvasRenderingContext2D} context 
 * @returns 像素比
 */
const getRatio = (context: any) => {
  if (!context) {
    return 1;
  }
  const backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1
  return (window.devicePixelRatio || 1) / backingStore
}

/**
 * 設置水印
 * @param {IWarterMarkProps} props 水印各種屬性
 */
const setWarterMarker = (props: IWarterMarkProps) => {
  const {
    imgUrl = '', imageOpacity = 1, imageWidth = 0, imageHeight = 0, fontColor = 'rgba(128, 128, 128, .2)',
    fontVariant = 'normal', fontWeight = 400, fontSize = 14, lineHeight = 14, fontStyle = 'normal', fontFamily = 'arial', rotate = 0, canvasRotate = 0,
    yOffset = 0, xOffset = 0, width = 200, height = 200, zIndex = 10,
  } = props
  const text = typeof props.text === 'object' ? props.text : props.text ? [props.text] : []
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
  const ratio = getRatio(ctx);
  const canvasWidth = width * ratio
  const canvasHeight = height * ratio
  const canvasOffsetLeft = xOffset * ratio
  const canvasOffsetTop = yOffset * ratio
  canvas.width = canvasWidth
  canvas.height = canvasHeight
  ctx.rotate(canvasRotate * (Math.PI / 180));
  let url = ''
  if (text.length) {
    ctx.font = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize * ratio}px/${lineHeight * ratio}px ${fontFamily || getComputedStyle(document.body).fontFamily}`
    ctx.fillStyle = fontColor
    text.forEach((content, index) => {
      ctx.fillText(content, canvasOffsetLeft, index * lineHeight + canvasOffsetTop + lineHeight * ratio)
    })
    url = canvas.toDataURL()
  }
  if (imgUrl) {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.referrerPolicy = 'no-referrer';
    img.src = imgUrl;
    img.onload = () => {
      ctx.globalAlpha = imageOpacity
      ctx.drawImage(img, canvasOffsetLeft, canvasOffsetTop, (imageWidth || (imageHeight ? img.width * imageHeight / img.height : img.width)) * ratio, (imageHeight || (imageWidth ? img.height * imageWidth / img.width : img.height)) * ratio)
      setDomCSSAttr({
        url: canvas.toDataURL(),
        rotate,
        zIndex,
        width
      })
      return
    };
    return
  }
  setDomCSSAttr({
    url,
    rotate,
    zIndex,
    width
  })
}

3. 步驟解析

3.1. setWarterMarker 方法

setWarterMarker 是使用水印的方法,參數(shù)是一個對象,包含以下內(nèi)容

interface IWarterMarkProps{
  text?: string | string[]  // 水印文案
  imgUrl?: string           // 水印圖片
  imageOpacity?: number     // 圖片透明度
  fontStyle?: string        // 字體樣式
  fontVariant?: string      // 字體變體
  fontWeight?: number       // 字體粗細
  fontFamily?: string       // 字體
  fontSize?: number         // 字體大小
  lineHeight?: number       // 字體行高
  fontColor?: string        // 字體顏色
  rotate?: number           // 水印旋轉(zhuǎn)角度 deg
  canvasRotate?: number     // canvas 旋轉(zhuǎn)角度 deg
  imageWidth?: number       // 圖片寬度
  imageHeight?: number      // 圖片高度
  xOffset?: number          // 水印 x 偏移
  yOffset?: number          // 水印 y 偏移
  width?: number            // 寬度
  height?: number           // 高度
  zIndex: number            // 層級
}
  • 獲取各個參數(shù)值
  • 創(chuàng)建 canvas,獲取 canvas 的像素比,設置 canvas 的各種參數(shù)
  • 如果存在 text 屬性,則進行遍歷繪制
  • 如果有圖片,則創(chuàng)建 image,再進行繪制
  • 生成 url,通過 setDomCSSAttr 方法進行 dom 渲染

3.2. getRatio 方法

獲取 canvas 的像素比,更清晰的繪制 canvas

3.3. setDomCSSAttr 方法

接收一個對象,包含以下內(nèi)容

interface ISetDomProps{
  url: string               // 圖片 URL
  rotate?: number           // 水印旋轉(zhuǎn)角度
  zIndex?: number           // 層級
  width?: number            // 寬度
}
  • 查找/創(chuàng)建 dom 元素
  • 設置 style 屬性
    • transform: 旋轉(zhuǎn)
    • backgroundSize:背景大小
    • backgroundImage:背景圖片
    • backgroundRepeat:背景重復
    • position:定位
    • zIndex:層級
    • pointerEvents:不能被選中
    • mixBlendMode:控制元素的混合模式

3.4. CSS mix-blend-mode 屬性

mix-blend-modeCSS 中的一個屬性,用于控制元素的混合模式。它可以讓元素的背景色和內(nèi)容色以一種特定的方式混合在一起,從而產(chǎn)生各種視覺效果。 以下是一些常用的 mix-blend-mode 值:

  • normal:默認值,內(nèi)容色完全覆蓋背景色。
  • multiply:將內(nèi)容色與背景色相乘。通常用于創(chuàng)建暗色效果。
  • screen:將內(nèi)容色與背景色相除,并取反。通常用于創(chuàng)建亮色效果。
  • overlay:結合了 multiplyscreen 模式,根據(jù)背景色的亮度來決定內(nèi)容色的混合模式。
  • darken:內(nèi)容色和背景色中的每個像素值,取對應像素值的較小者。
  • lighten:內(nèi)容色和背景色中的每個像素值,取對應像素值的較大者。
  • color-dodge:顏色減淡,通過減少背景色的值來增加內(nèi)容色的亮度。
  • color-burn:顏色加深,通過增加背景色的值來降低內(nèi)容色的亮度。
  • difference:計算內(nèi)容色和背景色之間的差異,產(chǎn)生顏色反轉(zhuǎn)的效果。
  • exclusion:將內(nèi)容色和背景色相減,并添加其結果的兩倍。
  • hue:保留內(nèi)容色的色相,并使用背景色的飽和度和亮度。
  • saturation:保留內(nèi)容色的飽和度,并使用背景色的色相和亮度。
  • color:保留內(nèi)容色的色相和飽和度,并使用背景色的亮度。
  • luminosity:保留內(nèi)容色的亮度,并使用背景色的色相和飽和度。

使用 mix-blend-mode 屬性,可以輕松地創(chuàng)建各種視覺效果,例如顏色混合、遮罩效果等。

三、水印使用

1. 文字

setWarterMarker({
  text: '這是水印, 這是水印, 這是水印',
  width: 200,
  height: 200,
  fontColor: 'red',
  fontSize: 8,
  lineHeight: 10,
})

2. 圖片

setWarterMarker({
  imgUrl: 'https://sponsors.vuejs.org/images/chrome_frameworks_fund.png',
  imageHeight: 50,
  imageWidth: 50,
  imageOpacity: 0.1,
})

3. 圖片和文字結合

setWarterMarker({
  text: '這是水印, 這是水印, 這是水印',
  width: 200,
  height: 200,
  fontColor: 'red',
  fontSize: 8,
  lineHeight: 10,
  imgUrl: 'https://sponsors.vuejs.org/images/chrome_frameworks_fund.png',
  imageHeight: 50,
  imageWidth: 50,
  imageOpacity: 0.1,
  canvasRotate: 15
})

4. 多行水印和圖片

setWarterMarker({
  text: ['這是水印, 這是水印, 這是水印', '第二行水印', '第三行水印', '第四行水印'],
  width: 200,
  height: 200,
  fontColor: 'red',
  fontSize: 8,
  lineHeight: 40,
  imgUrl: 'https://sponsors.vuejs.org/images/chrome_frameworks_fund.png',
  imageHeight: 50,
  imageWidth: 50,
  imageOpacity: 0.1,
})

四、總結

  • 水印技術調(diào)研顯示,水印在保護版權、信息標識和安全保護方面具有重要作用。
  • 通過CSS、JavaScript或第三方庫,可以實現(xiàn)頁面水印功能。
  • 過多或顯眼的水印可能影響用戶體驗,而性能和兼容性也是考慮的因素。
  • 綜合評估水印的利弊,可結合實際需求謹慎選擇適合的實現(xiàn)方式。
  • 如果需求有更復雜的水印,可以按步驟去改即可。

以上就是使用JS代碼實現(xiàn)頁面添加水印的方法詳解的詳細內(nèi)容,更多關于JS頁面添加水印的資料請關注腳本之家其它相關文章!

相關文章

  • js實現(xiàn)文字在按鈕上滾動的方法

    js實現(xiàn)文字在按鈕上滾動的方法

    這篇文章主要介紹了js實現(xiàn)文字在按鈕上滾動的方法,涉及javascript動態(tài)定時操作頁面元素樣式的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • 輸入密碼檢測大寫是否鎖定js實現(xiàn)代碼

    輸入密碼檢測大寫是否鎖定js實現(xiàn)代碼

    網(wǎng)站登錄為了更好的用戶體驗都會在輸入密碼的時候檢測是否開啟大寫,這樣有助于提醒用戶,需要學習的朋友可以參考下
    2012-12-12
  • JS判斷點是否在線段上的代碼

    JS判斷點是否在線段上的代碼

    這篇文章主要介紹了JS判斷點是否在線段上的相關資料,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-11-11
  • JavaScript中的事件與異常捕獲詳析

    JavaScript中的事件與異常捕獲詳析

    這篇文章主要給大家介紹了關于JavaScript中事件與異常捕獲的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-02-02
  • 走進javascript——不起眼的基礎,值和分號

    走進javascript——不起眼的基礎,值和分號

    本文主要介紹了javascript的基礎知識--值和分號,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • JavaScript生成驗證碼并實現(xiàn)驗證功能

    JavaScript生成驗證碼并實現(xiàn)驗證功能

    這篇文章主要介紹了JavaScript生成驗證碼并實現(xiàn)驗證功能的相關資料,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • JS實現(xiàn)隨機抽選獲獎者

    JS實現(xiàn)隨機抽選獲獎者

    這篇文章主要介紹了JS實現(xiàn)隨機抽選獲獎者,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • uniapp頁面回到頂部兩種實現(xiàn)方法

    uniapp頁面回到頂部兩種實現(xiàn)方法

    這篇文章主要給大家介紹了關于uniapp頁面回到頂部兩種實現(xiàn)方法的相關資料,在uniapp中要實現(xiàn)回到頂部的效果有兩種方法實現(xiàn),文中給出了詳細的代碼示例,需要的朋友可以參考下
    2023-08-08
  • js中數(shù)組常用方法總結(推薦)

    js中數(shù)組常用方法總結(推薦)

    這篇文章主要介紹了js中數(shù)組常用方法總結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • js實現(xiàn)頂部可折疊的菜單工具欄效果實例

    js實現(xiàn)頂部可折疊的菜單工具欄效果實例

    這篇文章主要介紹了js實現(xiàn)頂部可折疊的菜單工具欄效果,可實現(xiàn)鼠標滑過菜單工具欄出現(xiàn)折疊與展開效果,涉及javascript鼠標事件及樣式的操作技巧,需要的朋友可以參考下
    2015-05-05

最新評論