關(guān)于JS前端實現(xiàn)水印的代碼操作
網(wǎng)頁水印
實現(xiàn)思路
- 通過canvas生成一張水印圖片
- 通過css將圖片設(shè)置為目標(biāo)節(jié)點的背景圖
- 通過MutationObserver監(jiān)聽目標(biāo)節(jié)點的類名變化,防止水印被刪除
代碼操作
- 通過canvas生成一張水印圖片
function createImgBase(options) {
const { content, width, height } = options;
const canvasDom = document.createElement("canvas");
let ctx = canvasDom.getContext("2d");
canvasDom.width = width;
canvasDom.height = height;
if (ctx) {
// 設(shè)置畫筆的方向
ctx.rotate((-14 * Math.PI) / 180);
// 設(shè)置水印樣式
ctx.fillStyle = "rgba(100,100,100,0.4)";
ctx.font = "italic 20px Arial";
// 渲染水印
content.forEach((text, index) => {
ctx.fillText(text, 10, 30 * (index + 1)); // 縱向拉開30的間距
});
}
// document.body.appendChild(canvasDom);
// 將canvas轉(zhuǎn)為圖片
return canvasDom.toDataURL("image/png");
}
// createImgBase({
// content: ["介四嘛呀", "介四sui印", "內(nèi)部機(jī)密材料", "嚴(yán)禁外泄!"],
// width: 200,
// height: 200,
// });
- 將水印設(shè)置為目標(biāo)節(jié)點的背景圖片
function getWaterMark({
content,
className,
canvasHeight = 140,
canvasWidth = 150,
}) {
// 生成圖片
const data_url = createImgBase({
content,
width: canvasWidth,
height: canvasHeight,
});
// 通過設(shè)置偽元素樣式,添加水印圖片為背景圖
const defaultStyle = `
.${className} {
position: relative;
}
.${className}::after {
content: "";
background-image: url(${data_url});
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
pointer-events: none;
}`;
const styleDom = document.createElement("style");
styleDom.innerHTML = defaultStyle;
document.head.appendChild(styleDom);
}
// getWaterMark({
// content: ["介四嘛呀", "介四sui印", "內(nèi)部機(jī)密材料", "嚴(yán)禁外泄!"],
// className: "content",
// });
- 添加mutationObserver監(jiān)聽節(jié)點的變化
function listenerDOMChange(className) {
// 獲取要監(jiān)聽的節(jié)點
const targetNode = document.querySelector(`.${className}`);
// 創(chuàng)建監(jiān)聽器
const observer = new MutationObserver(mutationList => {
// 遍歷變化記錄
for (let mutationRecord of mutationList) {
// 如果目標(biāo)節(jié)點的class屬性發(fā)生變化,判斷是不是類名被刪了,是的話把類名加回去
if (mutationRecord.attributeName === "class") {
if(!Array.from(targetNode.classList).includes(className)) {
targetNode.classList.add(className)
}
}
}
});
// 啟動監(jiān)聽
observer.observe(targetNode, {
attributes: true,
});
}
function getWaterMark({
content,
className,
canvasHeight = 140,
canvasWidth = 150,
}) {
// 監(jiān)聽
listenerDOMChange(className);
const data_url = createImgBase({
content,
width: canvasWidth,
height: canvasHeight,
});
// ...
const styleDom = document.createElement("style");
styleDom.innerHTML = defaultStyle;
document.head.appendChild(styleDom);
}
關(guān)于MutationObserver
MutationObserver 用來監(jiān)聽DOM的變化,DOM的增刪、DOM屬性的變化,子結(jié)點和文本內(nèi)容的變化,都可以被監(jiān)聽。
MutationObserver 的監(jiān)聽和事件不同,事件是同步的,DOM的變化會立即觸發(fā)對應(yīng)的事件,而 MutationObserver 是異步的,會在下一個微任務(wù)執(zhí)行時觸發(fā)監(jiān)聽回調(diào)。
- 創(chuàng)建MutationObserver
const observer = new MutationObserver((mutationsList, observer) => {
// mutationsList mutationRecord數(shù)組 記錄了DOM的變化
// observer MutationObserver的實例
// 監(jiān)聽回調(diào)
console.log(mutationsList, observer);
})
mutationObserver.observe(document.documentElement, {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
});
- 開啟監(jiān)聽
// node 監(jiān)聽的節(jié)點
// config 監(jiān)聽配置(要監(jiān)聽哪些內(nèi)容)
// observer.observe(node, config);
mutationObserver.observe(document.documentElement, {
attributes: true, // 屬性變化
attributeOldValue: true, // 觀察attributes變動時,是否需要記錄變動前的屬性值
attributeFilter: [‘class',‘src'] // 需要觀察的特定屬性
characterData: true, // 節(jié)點內(nèi)容、文本的變化
characterDataOldValue: true, // 觀察characterData變動時,是否需要記錄變動前的屬性值
childList: true, // 子結(jié)點變化
subtree: true, // 所有后代節(jié)點
});
// 停止監(jiān)聽
mutationObserver.disconnect()
// 清除變動記錄
mutationObserver.takeRecords()
圖片水印
實現(xiàn)思路
方案一:通過oss添加水印 方案二:通過canvas生成帶有水印的圖片
oss實現(xiàn)
oss方式不做過多描述了 簡單來說就是通過在獲取圖片時,在圖片鏈接上增加參數(shù),讓oss生成一張帶水印的圖片。 注意點:
png圖片的透明區(qū)域無法被添加水印。 解決方式: 可通過添加參數(shù)的方式,讓oss將圖片轉(zhuǎn)為jpg格式(jpg格式會對透明區(qū)域做顏色填充)。
字體大小寫為定值,原圖大小會影響到水印字體的顯示大小。 解決方式:通過創(chuàng)建img標(biāo)簽,onLoad獲取圖片后,根據(jù)圖片寬高計算合適的字體大小,然后再一次獲取帶水印的圖片。
用戶通過刪除參數(shù)的方式可以刪除水印 解決方式:設(shè)置oss的安全級別,不帶水印不可訪問。
canvas實現(xiàn)
- 將img轉(zhuǎn)為canvas
async function imgToCanvas(cav, imgSrc) {
const img = new Image();
img.src = imgSrc;
// 防止因跨域?qū)е碌膱D片加載失敗(該方法有局限性)
img.setAttribute("crossOrigin", "anonymous");
// 等待圖片加載
await new Promise(resolve => (img.onload = resolve));
cav.width = img.width;
cav.height = img.height;
const ctx = cav.getContext("2d");
if (ctx) {
ctx.drawImage(img, 0, 0);
}
return cav;
}
- 添加水印
function addWaterMask(cav, content) {
const ctx = cav.getContext("2d");
ctx.fillStyle = "rgba(100,100,100,0.2)";
ctx.font = `24px serif`;
ctx.translate(0, 0);
ctx.rotate((5 * Math.PI) / 180);
// 生成水印
let x = 0, y = 0;
while (x < cav.width) {
y = 0;
while (y < cav.height) {
ctx.fillText(content, x, y);
y += 100;
}
x += 150;
}
}
- 使用
(async function () {
const canvas = document.createElement("canvas");
await imgToCanvas(
canvas,
"https://pp.myapp.com/ma_pic2/0/shot_54360764_1_1716462139/0"
);
addWaterMask(canvas, "介四sui印");
// document.body.appendChild(canvas);
return canvas.toDataUrl("image/png")
})();
到此這篇關(guān)于關(guān)于JS前端實現(xiàn)水印的代碼操作的文章就介紹到這了,更多相關(guān)JS實現(xiàn)水印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript滿天星導(dǎo)航欄實現(xiàn)方法
本篇文章給大家分享了JavaScript滿天星導(dǎo)航欄實現(xiàn)方法,以前也介紹過很多關(guān)于特效導(dǎo)航的制作方法,對此有興趣的朋友參考學(xué)習(xí)下。2018-03-03
input輸入框限制只能輸入數(shù)字的方法實例(個人認(rèn)為最好的)
在很多業(yè)務(wù)中需要對輸入框進(jìn)行字符限制,比如金額輸入框、手機(jī)號碼輸入框等,下面這篇文章主要給大家介紹了關(guān)于input輸入框限制只能輸入數(shù)字的相關(guān)資料,文中介紹的方法個人認(rèn)為最好的,需要的朋友可以參考下2022-10-10
如何實現(xiàn)修改密碼時密碼框顯示保存到cookie的密碼
修改密碼時密碼框顯示保存到cookie的密碼,只要在input框中加入AUTOCOMPLETE="OFF" 即可,感興趣的朋友可以了解下2013-12-12
Bootstrap下拉菜單Dropdowns的實現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Bootstrap下拉菜單Dropdowns的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03

