绘制页面水印-vue

830 阅读1分钟

最近接了个需求,要求在页面上添加水印,水印内容是变化的(每个用户的信息是不一样的),要均匀规则的分布在页面上,并且不能影响页面其他功能的正常使用。在参考了百度各位大佬的实现方式之后,终于做出一个自认为比较简单好用的水印组件。

核心是两点

1、使用canvas绘制文字,并且将toDataURL()方法输出的数据设置为dom的背景图片。设置背景图片的好处是,图片平铺之后,会很规则

2、给要平铺的dom元素设置pointer-events: none;样式。这个样式是元素穿透,意味着这个dom上面所有的事件全部失效。把该元素覆盖在整个页面上,加上了水印,也不影响页面其他功能的使用。完美!!!

这里是template

<template>  
    <div class="wrterMarkWrap" ref="wrterMarkWrap"></div>
</template>

这里是方法,也就是canvas绘图的实现

<script>
    const canWidth = 400 // 定义图片的宽
    const canHeight = 250 // 定义图片的高
    export default {  
        props: {    
            textColor: { // 水印文字颜色      
                type: String,      
                default: 'rgba( 80, 119, 146, .7)'    
            },    
            rotateDeg: { // 文字旋转角度      
                type: Number,      
                default: -25,    
            },    
            markTxt: { // 水印内容      
                type: String,      
                default: ''    
            },  
        },  
        data () {    
            return {      
                can: null, // 画布      
                textSize: 14, // 文字大小      
                showMark: true, // 是否使用水印    
            }  
        },  
        watch: {    
            markTxt: { // 监视绘制文字      
                immediate: true,      
                handler ( newVal, oldVal ) {        
                    if ( newVal && newVal != oldVal && this.showMark ) {          // 此处可加定时器,防止dom未生成,获取不到组件实例          
                        this.initCanvas()        
                    }      
                }    
            },  
        },  
        methods: {    
            initCanvas () {      
                this.createMark()      
                this.drawWarterMark()    
            },    
        
            // 使用canvas绘制文字,并保存    
            createMark () {      
                let writetxt = '自制水印-' + this.markTxt // 设置水印文字      
                this.can = document.createElement('canvas') // 创建canvas      
                this.can.width = canWidth // 定义canvas的width      
                this.can.height = canHeight // 定义canvas的height      
                let ctx = this.can.getContext('2d')      
                let txtWidth = ctx.measureText(writetxt).width // 绘制文字所占宽度      
                ctx.translate( (canWidth - txtWidth) / 2, canHeight / 2); // 移动canvas的绘制起始点      
                ctx.rotate(this.rotateDeg * Math.PI / 180) // 旋转canvas      
                ctx.font = `${this.textSize}px 微软雅黑` // 设置字体信息      
                ctx.fillStyle = this.textColor   // 字体颜色      
                ctx.textBaseline = 'hanging' // 设置文字基准线      
                ctx.fillText(writetxt, 0, 0) // 绘制文字    
            },    

            drawWarterMark () {      // 把canvas的输出文字设置为元素的背景图      
                this.$refs.wrterMarkWrap.style.background = 'url(' + this.can.toDataURL('image/png') + ') left top repeat'    
            },  
        }
}</script>

这里是样式,不要忘记了给元素设置事件穿透

<style lang="scss" scoped>
    .wrterMarkWrap {  
        width: 100%;  
        height: 100%;  
        position: fixed;  
        left: 0;  
        top: 0;  
        z-index: 20;  
        pointer-events: none; // 事件穿透,该元素所有的事件全部失效,最重要的
    }
</style>

以上就是全部代码,代码是按照自己习惯写的,有什么不对之处,请指出。本人是canvas菜鸟,只会做点简单的东西,刚好就是应用自己会的折腾出了水印组件。