上来先放一张成果图

一起给图片盖个章吧_图片盖章

背景

有一天突然想着给图片加水印的事情,就想着来实现一下.

环境

使用vue-cli建了一个简单项目

思路

使用canvas技术, 先将图片导入至canvas,在canvas中加水印图片,达到盖章的效果。

实现

导入图片

// 导入图片importImg() {const input = document.createElement("input");const context = this.$refs.canvas.getContext("2d"); // this.$refs.canvas是canvas的dom对象input.type = "file";
    input.click();
    input.onchange = () => {const file = input.files[0];if (file.type.indexOf("image") == 0) {const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => {const img = new Image();
                img.src = reader.result;
                img.onload = () => {let imgW = img.width;let imgH = img.height;const width = this.$refs.main.offsetWidth;const height = this.$refs.main.offsetHeight;if (imgH > imgW) {this.$refs.canvas.width = (imgW * height) / imgH;this.$refs.canvas.height = height;
                        context.drawImage(img, 0, 0, (imgW * height) / imgH, height);console.log((imgW * height) / imgH, height);
                    } else {this.$refs.canvas.width = width;this.$refs.canvas.height = (imgH * width) / imgW;
                        context.drawImage(img, 0, 0, width, (imgH * width) / imgW);console.log(width, (imgH * width) / imgW);
                    }
                };
            };
        }
    };复制代码

解析: 创建一个input,type 为 file,获取选取的文件。 在读取到图片后,根据页面大小缩放一下。

FileReade解释Image对象

盖章

import icon from "./assets/logo.png";// 印章addMark(e) { // addMark为canvas点击事件const img = new Image();
    img.src = icon;  // icon是要盖的图片img.onload = () => {const context = this.$refs.canvas.getContext("2d");
        context.drawImage(
            img,
            e.offsetX - this.markWidth / 2, // markWidth是印章的宽度e.offsetY - this.markHeight / 2, // markHeight是印章的高度this.markWidth,this.markHeight
        );
    };
},复制代码

解析: 监听点击事件,将印章定位到对应位置

转换

// 生成图片downImg() {this.$refs.canvas.toBlob((blob) => {let url = window.URL.createObjectURL(blob);let link = document.createElement("a");
        link.href = url;
        link.download = "加水印";
        link.target = "_blank";
        link.click();
    });
},复制代码

解析:将canvas转为blob,然后下载, 可通过toBlob控制图片的类型, 默认为png

注意:别转base64, 很麻烦

HTMLCanvasElement.toBlob()

加一个拖拽载入图片的效果

利用 dragover事件和drop事件加入效果

给容器添加事件

<main ref="main" @dragover.prevent="dragover" @drop.prevent="drop"><canvas ref="canvas" @click="addMark"></canvas></main>复制代码

注意这里的prevent事件修饰符,是用来阻止浏览器默认打开图片的行为的,dragover函数为空函数就好

drop(e) {if (e.dataTransfer.files[0].type.indexOf("image") === -1) return;const reader = new FileReader();const context = this.$refs.canvas.getContext("2d");
    reader.readAsDataURL(e.dataTransfer.files[0]);
    reader.onload = () => {const img = new Image();
        img.src = reader.result;
        img.onload = () => {let imgW = img.width;let imgH = img.height;const width = this.$refs.main.offsetWidth;const height = this.$refs.main.offsetHeight;if (imgH > imgW) {this.$refs.canvas.width = (imgW * height) / imgH;this.$refs.canvas.height = height;
                context.drawImage(img, 0, 0, (imgW * height) / imgH, height);
            } else {this.$refs.canvas.width = width;this.$refs.canvas.height = (imgH * width) / imgW;
                context.drawImage(img, 0, 0, width, (imgH * width) / imgW);
            }
        };
    };
}复制代码

解析: 操作和载入图片的操作一致, e.dataTransfer.files[0]是你拖入的文件

成果

一起给图片盖个章吧_图片盖章_02