js图片增加水印,并上传服务器

目录标题

    • 一、前端代码
    • 二、完整前后端代码

一、前端代码

  1. watermark.js 工具类
/**
 * 添加水印 异步
 * @param {图片file,在inout中的file} file
 * @param {水印数组,比如名字,电话,时间,地址} watermarks
 */
function addWatermarkAndUpload(file, watermarks) {
    return new Promise(((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = function (event) {
            const img = new Image();
            img.onload = function () {
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');

                // 设置canvas尺寸与图片一致
                canvas.width = img.width;
                canvas.height = img.height;

                // 绘制图片到canvas
                ctx.drawImage(img, 0, 0, img.width, img.height);

                //水印大小和颜色
                let fontSize = 100
                ctx.font = fontSize + 'px Arial';
                ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
                //水印起始位置,默认左下角
                let x = 20
                let y = 20
                // 添加水印
                for (let i = 0; i < watermarks.length; i++) {
                    y = watermarkHandle(ctx, watermarks[i], canvas.width, canvas.height, fontSize, x, y)
                }
                // 将带有水印的canvas转换为Blob对象
                canvas.toBlob((blob) => {
                    if (blob) {
                        blob.name = file.name
                        resolve(blob);
                    } else {
                        reject(new Error('Failed to create blob from canvas'));
                    }
                }, 'image/png');
            };
            img.src = event.target.result;
        };
        reader.readAsDataURL(file);
    }));
}

/**
 * 写入水印,默认左下角 水印过长,换行 (x,y)=(0,0) 就是左下角的位置
 *  @param {canvas画布对象} ctx
 *  @param {单个水印} watermark
 *  @param {图片的长宽} height
 *  @param {图片的长宽} width
 *  @param {水印字体大小} fontSize
 *  @param {水印位置,默认左下角} x
 *  @param {水印位置,默认左下角} y
 */
function watermarkHandle(ctx, watermark, width, height, fontSize, x, y) {
    //添加水印
    let lineHeight = fontSize + 10
    let line = '';
    const list = [];
    for (let i = 0; i < watermark.length; i++) {
        const testLine = line + watermark[i];
        const metrics = ctx.measureText(testLine);
        const testWidth = metrics.width;
        if (testWidth < width - fontSize && i < watermark.length - 1) {
            line = testLine;
        } else {
            list.push(line)
            line = watermark[i];
        }
    }
    const testLine = line + list[list.length - 1];
    const metrics = ctx.measureText(testLine);
    const testWidth = metrics.width;
    if (testWidth < width - fontSize) {
        list[list.length - 1] = list[list.length - 1] + line
    } else {
        list.push(line)
    }
    for (let i = list.length - 1; i >= 0; i--) {
        ctx.fillText(list[i], x, height - y);
        y += lineHeight;
    }
    //位置
    return y;
}

  1. 使用
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片水印并上传示例</title>
</head>
<body>
<input type="file" id="imageFile" accept="image/*">
<button onclick="addWatermark()">添加水印并上传</button>

<script th:src="@{/js/watermark.js}"></script>
<script>
    function addWatermark() {
        const imageFileInput = document.getElementById('imageFile');
        const file = imageFileInput.files[0];

        if (!file) {
            alert('请先选择图片!');
            return;
        }
        var watermarks = []
        watermarks.push("广西壮族自2心2圩街2汇11111111111111111111111112")
        watermarks.push("2024-05-11 19:13:04 ")
        watermarks.push("李华 130733376")
        const promises = [];
        for (let i = 0; i < 3; i++) {
            promises.push(addWatermarkAndUpload(file, watermarks))
        }
        Promise.all(promises)
            .then(results => {
                // 当所有Promise都完成时,results数组包含所有结果
                console.log(results);
                // 在这里你可以一起处理所有结果
                const formData = new FormData();
                for (let i = 0; i < results.length; i++) {
                    console.log(results[i])
                    formData.append('files', results[i], results[i].name);
                }
                return formData;
            })
            .then(formData => {
                //上传,注意上传接口多个文件
               return  fetch('/common/uploads', {
                    method: 'POST',
                    body: formData
                });
            })
            .then(response => {
                // 处理响应
                return response.json();
            })
            .then(data => {
                // 处理返回的数据,url
                console.log(data);
                //其他操作操作
            })
            .catch(error => {
                // 处理错误
                console.error('Error:', error);
            })
    }
</script>
</body>
</html>

二、完整前后端代码

全部代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/631870.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MacOS下载安装JDK8

一、前言 今天给苹果电脑安装JDK环境&#xff0c;后续打算把Mac系统也用起来&#xff0c;也体验一把用苹果系统开发。 JDK就不过多介绍了&#xff0c;大家都是JAVA开发&#xff0c;JDK就是JAVA开发的必要环境。目前已经更新到JDK20了&#xff0c;不过我是不会更新的&#xff0…

微服务中的鉴权怎么做?

大家好&#xff0c;我是苍何呀。 现在出去找工作&#xff0c;简历上不写上微服务的技术&#xff0c;仿佛自己跟不上时代了&#xff0c;面试官更是喜欢盯着微服务项目来提问。 但其实虽说微服务是主流&#xff0c;随着云原生架构的发展&#xff0c;微服务也是趋势&#xff0c;…

DOS学习-目录与文件应用操作经典案例-dir

欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.练习 一.前言 dir是"directory"&#xff08;目录&#xff09;的缩写&#xff0c;它主要用于展示某个磁盘上的全部或特定文件目录。在DOS操作系统中&#…

ES6中数组新增了哪些扩展?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:ES6中数组新增了哪些扩展&#xff1f; 目录 一、扩展运算符的应用 二、构造函数新…

Web3与物联网:构建智能连接的数字世界

引言 随着互联网的不断发展&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;作为一种新兴的信息技术&#xff0c;正在逐渐渗透到我们的生活和工作中。而随着Web3的兴起&#xff0c;物联网将迎来新的发展机遇。本文将探讨Web3与物联网的结合&#xff0c;如何…

全面解析防静电措施:保障工业安全,预防静电危害

静电是一种常见的物理现象&#xff0c;由于电荷的不平衡而产生。在特定的环境中&#xff0c;静电可能会带来危害&#xff0c;如损坏电子设备、引起火灾等。因此&#xff0c;采取适当的防静电措施是非常重要的。以下是一些常见的防静电方法&#xff1a; 增加环境湿度&#xff1a…

崆峒酥饼:佳节馈赠的美味之选

崆峒酥饼&#xff1a;佳节馈赠的美味之选 在即将到来的端午节&#xff0c;人们开始忙碌地准备着走亲访友的礼物。而崆峒酥饼&#xff0c;作为一种传统的美食&#xff0c;不仅是节日里的美味享受&#xff0c;更是传递情谊的佳品。 崆峒酥饼&#xff0c;以其酥脆的口感和独特的风…

使用httpx异步获取高校招生信息:一步到位的代理配置教程

概述 随着2024年中国高考的临近&#xff0c;考生和家长对高校招生信息的需求日益增加。了解各高校的专业、课程设置和录取标准对于高考志愿填报至关重要。通过爬虫技术&#xff0c;可以高效地从各高校官网获取这些关键信息。然而&#xff0c;面对大量的请求和反爬机制的挑战&a…

【Python】语句与众所周知【自我维护版】

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 本篇博客是在之前的基础上进行的维护 目录 条…

HP6V18、HP6V65电比例功率控制泵放大器

HP6V18、HP6V65电比例压力负控制&#xff0c;电比例功率控制泵通过由BEUEC比例放大器控制改变阀的输入电流&#xff0c;将泵设置为一定压力。改变负载压力&#xff0c;为使调订压力恒定&#xff0c;泵摆角会增大或减小&#xff0c;从而改变流量。因此泵只能输出执行器可以接受的…

ubuntu下gcc编译器的安装

.gcc编译器的安装 一般linux下是覆盖含有的&#xff0c;如果没有执行更新命令 sudo apt update gcc安装成功&#xff0c;可以检查一下版本 可以看出我的gcc是9.4.0版本的

地表最强ChatGPT爆了!我来告诉你,它都有什么用

OpenAI刚刚发布了全新的 "GPT-4o"&#xff0c;它不仅可以通过语音、视觉和文本进行推理&#xff0c;还在速度和价格上有了巨大的突破。它的速度提高了2倍&#xff0c;价格却降低了50%&#xff0c;而且生成速率比GPT-4 Turbo高出5倍。最令人惊喜的是&#xff0c;它将对…

Verilog基础语法——条件语句if-else与case

Verilog基础语法——条件语句case、if-else 写在前面一、if-else语句二、case语句2.1 case语句2.2 casez语句2.3 casex语句 写在后面 写在前面 在Verilog语法中&#xff0c;常用的条件语句有if-else语句和case语句&#xff0c;用于判断条件是否为真&#xff0c;并执行判断条件后…

【NLP】文本分类

n-gram 的局限性 n-gram 只能对于填空这样的通顺性问题做出推测&#xff0c;但是没有办法完全解决句子的语义问题&#xff0c;从而无法实现文本的分类 文本的分类&#xff0c;就是将文本在语义的理解下划分到特定的主题下 手工规则 如一些垃圾过滤系统&#xff0c;需要人工制…

PHP开发中的不安全反序列化

序列化是开发语言中将某个对象转换为一串字节流的过程&#xff0c;转换后的字节流可以方便存储在数据库中&#xff0c;也可以方便在网络中进行传输。而反序列化则是将数据库取出的字节流或从网络上接收到的字节流反向转换为对象的过程。概念虽如此&#xff0c;但不同的开发语言…

【JavaEE 初阶(七)】网络原理 TCP与UDP协议

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多网络知识 目录 1.前言2.应用层2.1xml2.2json 3.传输层3.1UDP协议3.2TCP协议3.2.1确认响应3.2.2超时重…

【c++】map和set的封装

1.红黑树源码 我们使用上节课的红黑树源码来封装map和set. 因为map存的是&#xff08;key,value&#xff09;,set存的是&#xff08;key&#xff09;,为了我们set和map使用同一个类模板&#xff08;红黑树&#xff09;&#xff0c;所以我们先要修改红黑树结点中存的数据类型&a…

苹果永久版安装PD虚拟机:Parallels Desktop 19 一键激活版

Parallels Desktop 19是一款功能强大的虚拟机软件&#xff0c;专为Mac用户设计&#xff0c;允许用户在同一台Mac电脑上同时运行Windows、Linux等多个操作系统&#xff0c;而无需额外的硬件设备。 下载地址&#xff1a;https://www.macz.com/mac/9581.html?idOTI2NjQ5Jl8mMjcuM…

Java环境搭建(二)Notepad++和IDEA的下载

Notepad&#xff08;不推荐使用&#xff09; 高级记事本 下载地址 Notepad (juxinwk1.cn) 下载安装后一直下一步就可以了 注&#xff1a;改一下路径还有建立快捷方式&#xff08;自己选择&#xff09; IDEA 集成环境 下载地址 IntelliJ IDEA – the Leading Java and Kotl…

展馆展厅设计施工流程

1、需求分析和确定&#xff1a; 与客户沟通&#xff0c;了解客户需求&#xff0c;对展馆展厅的用途、面积、功能、展品特点等进行分析&#xff0c;并确定设计方案。 2、方案设计 根据需求确定设计方案&#xff0c;包括平面布局、展品陈列、展示方式、照明等。设计师需要提供设计…