Rumah > hujung hadapan web > tutorial js > Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan

Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan

藏色散人
Lepaskan: 2023-03-03 19:57:44
ke hadapan
2224 orang telah melayarinya

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

Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan

IMG

Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan

Selepas diproses

DIV

Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan

IMG

Penjelasan terperinci tentang cara menggunakan JS untuk mencapai kesan tera air tindanan

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(&#39;div&#39;)
        //关联水印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 = &#39;position: absolute;top: 0px;left: 0px;pointer-events:none&#39;
        }
    }
}
Salin selepas log masuk

Penggunaan

<div>
    <!-- 待加水印的IMG -->
    <img   style="max-width:90%" src="" alt="">
</div>

let waterMark = new WaterMark()
waterMark.startWaterMark();
Salin selepas log masuk

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(&#39;body&#39;)[0], {
    childList: true, // 子节点的变动(新增、删除或者更改)
    attributes: true, // 属性的变动
    characterData: true, // 节点内容或节点文本的变动
    subtree: true // 是否将观察器应用于该节点的所有后代节点
})
Salin selepas log masuk
Saiz imej hanya boleh ditentukan selepas pemuatan selesai, jadi untuk pengendalian

IMG, anda perlu memerhatikan acara lengkapnya.

3. Ringkasan dan Pemikiran

Gunakan

kanvas 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!

Label berkaitan:
sumber:juejin.im
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan