成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

詳解如何用JS實現(xiàn)覆蓋水印效果

廢話開篇:簡單實現(xiàn)一個覆蓋水印的小功能,水印一般都是添加在圖片上,然后直接加載處理過的圖片url即可,這里并沒有修改圖片,而是直接的在待添加水印的 dom 上添加一個 canvas 蒙版。

一、效果

處理之前

DIV

詳解如何用JS實現(xiàn)覆蓋水印效果

IMG

詳解如何用JS實現(xiàn)覆蓋水印效果

處理之后

DIV

詳解如何用JS實現(xiàn)覆蓋水印效果

IMG

詳解如何用JS實現(xiàn)覆蓋水印效果

這里添加 “水印”(其實并不是真正的水印) 到 DIV 的時候按鈕點擊事件并不會因為有蒙版遮擋而無法點擊

二、JS 代碼

class WaterMark{     //水印文字     waterTexts = []     //需要添加水印的dom集合     needAddWaterTextElementIds = null     //保存添加水印的dom     saveNeedAddWaterMarkElement = []     //初始化     constructor(waterTexts,needAddWaterTextElementIds){         if(waterTexts && waterTexts.length != 0){             this.waterTexts = waterTexts         } else {             this.waterTexts = ['水印文字哈哈哈哈','2022-12-08']         }         this.needAddWaterTextElementIds = needAddWaterTextElementIds     }          //開始添加水印     startWaterMark(){         const self = this         if(this.needAddWaterTextElementIds){             this.needAddWaterTextElementIds.forEach((id)=>{                 let el = document.getElementById(id)                 self.saveNeedAddWaterMarkElement.push(el)             })         } else {             this.saveNeedAddWaterMarkElement = Array.from(document.getElementsByTagName('img'))         }         this.saveNeedAddWaterMarkElement.forEach((el)=>{             self.startWaterMarkToElement(el)         })     }      //添加水印到到dom對象     startWaterMarkToElement(el){         let nodeName = el.nodeName         if(['IMG','img'].indexOf(nodeName) != -1){             //圖片,需要加載完成進行操作             this.addWaterMarkToImg(el)         } else {             //普通,直接添加             this.addWaterMarkToNormalEle(el)         }     }              //給圖片添加水印     async addWaterMarkToImg(img){         if(!img.complete){             await new Promise((resolve)=>{                 img.onload = resolve             })         }         this.addWaterMarkToNormalEle(img)     }          //給普通dom對象添加水印     addWaterMarkToNormalEle(el){         const self = this         let canvas = document.createElement('canvas')         canvas.width = el.width ? el.width : el.clientWidth         canvas.height = el.height ? el.height : el.clientHeight         let ctx = canvas.getContext('2d')         let maxSize = Math.max(canvas.height, canvas.width)         let font = (maxSize / 25)         ctx.font = font + 'px "微軟雅黑"'         ctx.fillStyle = "rgba(195,195,195,1)"         ctx.textAlign = "left"         ctx.textBaseline = "top"         ctx.save()         let angle = -Math.PI / 10.0         //進行平移,計算平移的參數(shù)         let translateX = (canvas.height) * Math.tan(Math.abs(angle))         let translateY = (canvas.width - translateX) * Math.tan(Math.abs(angle))         ctx.translate(-translateX / 2.0, translateY / 2.0)         ctx.rotate(angle)         //起始坐標         let x = 0         let y = 0         //一組文字之間間隔         let sepY = (font / 2.0)         while(y < canvas.height){             //當前行的y值             let rowCurrentMaxY = 0             while(x < canvas.width){                 let totleMaxX = 0                 let currentY = 0                 //繪制水印                 this.waterTexts.forEach((text,index)=>{                     currentY += (index * (sepY + font))                     let rect = self.drawWater(ctx,text,x,y + currentY)                     let currentMaxX = (rect.x + rect.width)                     totleMaxX = (currentMaxX > totleMaxX) ? currentMaxX: totleMaxX                     rowCurrentMaxY = currentY                 })                 x = totleMaxX + 20             }             //重置x,y值             x = 0             y += (rowCurrentMaxY + (sepY + font + (canvas.height / 5)))         }         ctx.restore()         //添加canvas         this.addCanvas(canvas,el)     }      //繪制水印     drawWater(ctx,text,x,y){         //繪制文字         ctx.fillText(text,x,y)         //計算尺度         let textRect = ctx.measureText(text)         let width = textRect.width         let height = textRect.height         return {x,y,width,height}     }      //添加canvas到當前標簽的父標簽上     addCanvas(canvas,el){         //創(chuàng)建div(canvas需要依賴一個div進行位置設置)         let warterMarDiv = document.createElement('div')         //關聯(lián)水印dom對象         el.warterMark = warterMarDiv         //添加樣式         this.resetCanvasPosition(el)         //添加水印         warterMarDiv.appendChild(canvas)         //添加到父標簽         el.parentElement.insertBefore(warterMarDiv,el)     }      //重新計算位置     resetCanvasPosition(el){         if(el.warterMark){             //設置父標簽的定位             el.parentElement.style.cssText = `position: relative;`             //設施水印載體的定位             el.warterMark.style.cssText = 'position: absolute;top: 0px;left: 0px;pointer-events:none'         }     } }
登錄后復制

用法

<div>     <!-- 待加水印的IMG -->     <img style="width: 100px;height: auto" src="" alt=""> </div>  let waterMark = new WaterMark() waterMark.startWaterMark();
登錄后復制

ctx.save()ctx.restore() 其實在這里的作用不是很大,但還是添加上了,目的是保存添加水印前的上下文,跟結束繪制后恢復水印前的上下文,這樣,這些斜體字只在這兩行代碼之間生效,下面如果再繪制其他,那么,將不受影響。

防止蒙版水印遮擋底層按鈕或其他事件,需要添加 pointer-events:none 屬性到蒙版標簽上。

添加水印的標簽外需要添加一個 父標簽 ,這個 父標簽 的作用就是添加約束 蒙版canvas 的位置,這里想通過 MutationObserver 觀察 body 的變化來進行更新 蒙版canvas 的位置,這個嘗試失敗了,因為復雜的布局只要變動會都在這個回調(diào)里觸發(fā)。因此,直接在添加水印的標簽外需要添加一個 父標簽 ,用這個 父標簽 來自動約束 蒙版canvas 的位置。

MutationObserver 邏輯如下,在監(jiān)聽回調(diào)里可以及時修改布局或者其他操作(暫時放棄)。

var MutationObserver = window.MutationObserver || window.webkitMutationObserver || window.MozMutationObserver; var mutationObserver = new MutationObserver(function (mutations) {     //修改水印位置 })  mutationObserver.observe(document.getElementsByTagName('body')[0], {     childList: true, // 子節(jié)點的變動(新增、刪除或者更改)     attributes: true, // 屬性的變動     characterData: true, // 節(jié)點內(nèi)容或節(jié)點文本的變動     subtree: true // 是否將觀察器應用于該節(jié)點的所有后代節(jié)點 })
登錄后復制

圖片的大小只有在加載完成之后才能確定,所以,對于 IMG 的操作,需要觀察它的 complete 事件。

三、總結與思考

canvas ctx.drawImage(img, 0, 0) 進行繪制,再將 canvas.toDataURL('image/png') 生成的 url 加載到之前的圖片上,也是一種方式,但是,有時候會因為圖片的原因導致最后的合成圖片的 base64 數(shù)據(jù)是空,所以,直接增加一個蒙版,本身只是為了顯示,并不是要生成真正的合成圖片。實現(xiàn)了簡單的偽水印,沒有特別復雜的代碼,代碼拙劣,大神勿笑[抱拳][抱拳][抱拳]

推薦學習:《JavaScript視頻教程》

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
熟女系列丰满熟妇AV| 嫩草影院网站进入| 林静公交车被做到高C| 免费人成视频X8X8入口| 欧美黑人XXXX性高清版| 日产乱码一二三区别免费一| 天天摸日日摸狠狠添| 亚洲AV无码一区二区三区人区| 亚洲欧洲精品无码AV| 中中文日产幕无线码一区| 锕锕锕锕锕锕锕好疼免费看网站| 多肉大尺寸小黄说说| 国产免费AV片在线无码免费看 | ★浪潮av无码一区二区| 波多野结衣AV在线无码中文观看| 国产高潮国产高潮久久久| 极品性荡少妇一区二区| 免费视频片多多视频免费高清 | 苍井空电影在线观看| 国产精品爽爽VA在线观看| 精品少妇人妻AV一区二区三区| 免费看美女脱精光的网站| 日韩AV在线一区二区| 亚洲AV狠狠爱一区二区三区| 永久黄网站色视频免费品善网| 被公疯狂进入的美丽人妻| 国产日产欧产精品精品蜜芽| 老汉粗大不带套怀孕| 日韩久久一区二区三区蜜桃| 亚洲AV无码一区二区三区少妇| 中文字幕在线不卡精品视频99| 东北少妇大叫高潮XXXⅩ| 狠狠色丁香久久婷婷综合五月| 女人张开腿让男人添| 无码精品人妻一区二区三区人妻斩| 亚洲色成人网站WWW永久男男| JαPαηeseHD熟女熟妇伦| 国产男男Gay做受| 妺妺窝人体色WWW精品知乎| 四虎成人精品无码永久在线| 野花大全在线观看免费高清| 成人AV无码一区二区三区| 娇妻在我面前被黑人撑爆| 欧洲美熟女乱又伦AV曰曰| 性色AV一区二区三区| 50多岁岳不让我戴套| 国产精品久久久久久福利| 美女脱个精光露出奶头和尿口| 天天做天天爱夜夜夜爽毛片 | 亚洲AV成人综合网伊人| 中文字幕日本六区小电影| 国产目拍亚洲精品一区| 欧美人与动XXXXZ0OZ| 亚洲MV国产MV在线MV综合试| 爆乳熟妇一区二区三区| 久久精品国产精品亚洲艾草网| 色欲色香天天天综合WWW| 曰韩无码二三区中文字幕| 国产精品毛片A∨一区二区三区| 男人的天堂AV网站| 亚洲成A人片在线观看天堂无码不 亚洲成A人片在线观看天堂 | 曰本BBWW高潮BBWR| 国产精品无圣光一区二区| 欧美老妇疯狂XXXXBBBB| 亚洲精品无码aⅴ中文字幕蜜桃 | 精品无码人妻一区二区免费蜜桃| 日本一道综合久久AⅤ久久| 野花日本大全免费观看10中文| 国产成A人亚洲精V品无码性色 | 日韩精品真人荷官无码| 在线观看无码AV网址| 国产日产欧产美韩系列| 忍着娇喘在公面前被夜袭| 夜夜高潮夜夜爽国产伦精品| 国产精品涩涩涩视频网站| 欧美性猛交aaaa乱大交| 野花影视大全在线观看免费| 国产女人水真多18毛片18精品| 人人人人人人一摸| 中文字幕色偷偷人妻久久| 激情综合色五月丁香六月亚洲| 书房双乳晃动干柴烈火视频| BBWBBW肥妇BBWBBW| 久久九九久精品国产| 亚洲AV女人18毛片水真多| 丁香五月天天综合亚洲| 欧美猛少妇色XXXXⅩ| 一本到无码AV专区无码不卡| 国产无遮挡裸体免费视频| 少妇高潮惨叫久久久久久| e无遮挡粉嫩小泬久久久久久久| 久久综合伊人77777麻豆| 亚洲国产精品无码久久一线| 国产精品毛片久久久久久久| 日韩VA中文字幕无码电影| A级毛片免费全部播放| 美女裸体无遮拦国产兔费网站| 亚洲男人第一AV网站| 国产真人无遮挡作爱免费视频| 十八禁无码免费网站| 不收费半夜年轻人看B站软件| 欧美V国产V亚洲V日韩九九| 再深点灬舒服灬太大了添视频软件| 精品少妇人妻AV免费久久洗澡| 亚洲AV无码国产丝袜在线观看| 国产精品色视频ⅩXXX| 特黄大片又粗又大又暴| 顶级欧美熟妇高清XXXXX| 人妻少妇精品中文字幕av蜜桃| A级毛片在线观看| 欧美成人免费全部网站| 综合一区无套内射中文字幕| 老司机久久一区二区三区| 野花在线高清视频| 久久久久免费看成人影片| 亚洲色成人网站WWW永久四虎| 精品国产乱码久久久久久1区2区| 亚洲VA在线∨A天堂VA欧美V| 国内精品一区二区三区| 亚洲AV麻豆AⅤ无码电影| 国产男男GAY做受ⅩXX软件| 无码精品人妻一区二区三区涩爱| 国产精品JIZZ在线观看| 无码吃奶揉捏奶头高潮视频| 国产精品多P对白交换绿帽| 玩小雪跪趴把腿分到最大影视频| 国产成人精品午夜福利APP色多| 熟睡被义子侵犯中文字幕| 国产成人无码AV在线播放DVD| 婷婷俺也去俺也去官网| 国产精品无码午夜福利| 亚洲AV高清在线观看一区二区三| 好爽…又高潮了毛片免费看| 亚洲成人无码AV| 久久精品国产精品亚洲艾草网| 一本大道久久香蕉成人网| 老熟女奶头好大呀| 99精品国产兔费观看久久| 欧美性猛交aaaa乱大交| 成人网站国产在线视频内射视频| 三个男人躁我一个爽视频免费| 国产FREEXXXX性播放麻豆| 无码熟熟妇丰满人妻啪啪喷水 | 亚洲AV成人无码精品网站按| 孩教小UXXXⅩ精品| 亚洲一本大道无码AV天堂| 乱码一卡二卡新区永久入口| ASIANMATURE老熟妇女| 日本熟妇厨房XXXXX乱| 丰满岳乱妇在线观看中字无码| 无码专区狠狠躁躁天天躁| 狠狠躁夜夜躁人人爽超碰97香蕉| 亚洲尤码不卡AV麻豆| 男女24式动态图| 成人精品一区二区三区网站| 特黄特色三级在线观看| 韩国三级在线观看完整版| 野花视频在线手机免费观看| 欧美成人v片一区二区三区激情| 成人AV无码乱码在线观看无码| 无码囯产精品一区二区免费| 交换玩弄两个美妇教师韩国电影| 英语老师的小兔子好大好软水| 欧美熟妇与小伙性欧美交| 工口全彩H肉无遮挡无翼乌| 亚洲AV成人无码AV小说| 久久天天躁夜夜躁狠狠85| GOGO高清大胆全人艺术| 偷玩朋友熟睡人妻| 久久99精品久久久久免费| 337P日本欧洲亚洲大胆裸体艺| 色噜噜狠狼综合在线视频| 国内精品人妻无码久久久影院 | 亚洲AV成人精品日韩一区| 久久久久无码精品国产AV蜜桃1| FREE性满足HD| 无人区码一码二码三码区别在哪里 | 久久夜色精品国产噜噜AV| 八戒八戒在线高清观看视频4| 无码纯肉视频在线观看喷水| 久久久久成人精品无码| ZZTT166.CCM黑料| 亚洲 欧美 中文 日韩AⅤ| 麻花豆传媒剧国产MV在线下载| 荡公乱妇第1章方情95| 亚洲国产成人久久综合一区77| 女生会把隐私透露给异性朋友 | 无码中文字幕AV久久专区| 久久久久免费精品国产| 纯肉无遮挡H肉动漫在线观看网址| 亚洲AV无码专区亚洲AV手机版 | 4虎CVT4WD| 无码人妻熟妇AV又粗又大| 毛很浓密超多黑毛| 国产福利萌白酱精品TV一区| 伊人色综合一区二区三区| 少妇高潮惨叫久久久久久| 久久亚洲精品成人AV无码网站| 嗯啊WW免费视频网站| 夜夜爽妓女8888视频免费观看|