Permulaan karut: hanya melaksanakan fungsi kecil untuk menutup tera air biasanya ditambahkan pada gambar, dan kemudian memuatkan terus gambar yang diproses url Sebaliknya, gambar tidak diubah suai. terus tambahkan topeng kanvas pada dom untuk ditambahkan.
1 Kesan
Sebelum diproses
DIV
IMG
Selepas diproses
DIV
IMG
Tambah "tera air" di sini (sebenarnya ia bukan tera air sebenar Apabila pergi ke DIV, acara klik butang tidak akan menjadi disekat oleh topeng. Dan tidak boleh klik
2. Kod 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 //进行平移,计算平移的参数 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){ //创建div(canvas需要依赖一个div进行位置设置) let warterMarDiv = document.createElement('div') //关联水印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' } } }
Penggunaan
<div> <!-- 待加水印的IMG --> <img style="max-width:90%" src="" alt=""> </div> let waterMark = new WaterMark() waterMark.startWaterMark();
ctx.save( ) dengan ctx.restore() Sebenarnya, ia tidak begitu berguna di sini, tetapi ia ditambah pula tujuannya adalah untuk menyimpan konteks sebelum menambah tera air, dan untuk memulihkan konteks sebelum ini tera air selepas selesai melukis Dengan cara ini, perkataan miring ini Ia hanya berkuat kuasa di antara dua baris kod ini Jika anda melukis garisan lain di bawah, ia tidak akan terjejas.
Untuk menghalang tera air topeng daripada menyekat butang asas atau acara lain, anda perlu menambahkan atribut pointer-events:none pada teg topeng.
Anda perlu menambah tag induk di luar teg untuk menambah tera air Fungsi tag induk ini adalah untuk menambah kekangan pada kedudukan topeng. kanvas, di sini saya ingin menggunakan MutationObserver untuk memerhati perubahan dalam badan untuk mengemas kini kedudukan kanvas topeng Percubaan ini gagal kerana reka letak kompleks akan diubah dalam pencetus panggilan balik ini. Oleh itu, anda perlu menambah tag induk terus di luar teg tempat tera air ditambahkan dan gunakan tag induk ini untuk mengekang kedudukan kanvas topeng<🎜 secara automatik >.
MutationObserver Logiknya adalah seperti berikut Anda boleh mengubah suai reka letak atau operasi lain dalam masa dalam panggilan balik mendengar (berputus asa buat sementara waktu).
var MutationObserver = window.MutationObserver || window.webkitMutationObserver || window.MozMutationObserver; var mutationObserver = new MutationObserver(function (mutations) { //修改水印位置 }) mutationObserver.observe(document.getElementsByTagName('body')[0], { childList: true, // 子节点的变动(新增、删除或者更改) attributes: true, // 属性的变动 characterData: true, // 节点内容或节点文本的变动 subtree: true // 是否将观察器应用于该节点的所有后代节点 })
IMG, anda perlu memerhatikan acara lengkapnya.
3. Ringkasan dan Pemikiran
Gunakankanvas ctx.drawImage(img, 0, 0) untuk melukis, dan kemudian gunakan canvas .toDataURL('image/png') Memuatkan url yang dihasilkan ke imej sebelumnya juga merupakan satu cara, bagaimanapun, kadangkala imej komposit akhir akan menjadi Data kosong, jadi menambah topeng secara langsung hanyalah untuk paparan, bukan untuk menjana imej komposit sebenar. tanda air pseudo yang mudah telah dilaksanakan Tiada kod yang sangat rumit. Kod itu kekok. >Pembelajaran yang disyorkan: "Tutorial video JavaScript 》
Atas ialah kandungan terperinci Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!