(分享)一个图片添加水印的小demo的页面,可自定义样式

有时候想给某张图片添加一个自己的水印,但是又懒的下载相应软件,用js canvas制作一个静态页面,对于单张图片添加自定义文字水印,大小 间距,角度可调。
页面如下:
在这里插入图片描述
选择图片,设置相应参数,点击添加水印:
在这里插入图片描述
效果:
在这里插入图片描述
完整程序如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>添加水印</title>
    <link rel="shortcut icon" href="https://img1.imgtp.com/2024/01/09/BKw2wjPL.png" type="image/x-icon">
    <style>
        body {
            background-color: #c8adc4;
        }

        .ml-5 {
            margin-left: 15px;
        }

        .container {
            display: flex;
            justify-content: space-between;
            /* 使两个 div 平均分布在容器中 */
        }

        .box {
            width: 49.5%;
            /* 或根据需要设置 */
            /* 其他样式 */
        }

        #canvas {
            border: 2px solid rgb(210, 208, 208);
            width: 95%;
            height: auto;
            overflow: hidden;
        }

        #p {
            margin-top: 20px;
            width: 95%;
            height: auto;
        }

        #canvas img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        #imageUpload {
            height: auto;
            width: auto;
            font-size: 16px;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="box">
            <div style="border: 2px solid #c9c9c9cc; padding: 10px;">
                <div>
                    <input type="file" id="imageUpload" style="color: rgb(249, 137, 109); margin-left: 40%;">
                </div>
                <div style="margin-left: 10%;margin-top: 30px;">
                    <span>大小:</span><input type="text" placeholder="修改水印大小" style="height: 24px;width: 100px;"
                        value="100" id="ipt1">
                    <span class="ml-5">透明度:</span><input type="text" placeholder="范围1~10"
                        style="height: 24px;width: 100px;" value="5" id="ipt2">
                    <span class="ml-5">间距:</span><input type="text" placeholder="范围1-10"
                        style="height: 24px;width: 100px;" value="5" id="ipt3">
                </div>
                <div style="margin-top: 20px;margin-left: 10%;">
                    <span class="ml-5">倾斜方向:</span>
                    <select id="s2">
                        <option value="left">左倾斜</option>
                        <option value="right">右倾斜</option>
                    </select>
                    <span class="ml-5">倾斜角度:</span>
                    <input type="text" placeholder="修改倾斜大小" style="height: 20px;width: 30px;" value="30" id="ipt4"><span
                        style="margin-left: 5px; ;"></span>
                </div>
                <div style="margin-left: 10%;margin-top: 40px;">
                    文本:<input type="text" id="watermarkText" placeholder="请输入水印内容" style="height: 24px;">
                    <button id="confirmButton"
                        style="margin-left: 100px; width: 80px;height: 30px;background-color: rgb(127, 214, 255);color: white;font-size: 16px;border: none;border-radius: 5px;">添加水印</button>
                    <button id="saveButton"
                        style="width: 60px;height: 30px;background-color: rgb(28, 119, 161);color: white;font-size: 16px;border: none;border-radius: 5px;">下载</button>
                    <button id="reflash" onclick="flush()"
                        style="width: 80px;height: 30px;background-color: rgb(248, 126, 81);color: white;font-size: 16px;border: none;border-radius: 5px;">重置页面</button>
                </div>
            </div>
            <span style="color: rgb(255, 255, 255); font-weight: bold;font-size: 20px;">原图:</span>
            <img id="p"></img>
        </div>
        <div class="box">
            <span style="color: rgb(255, 255, 255); font-weight: bold;font-size: 20px;">预览框:</span>
            <canvas id="canvas"></canvas>
        </div>
    </div>
    <script>

        //回显
        document.getElementById('imageUpload').addEventListener('change', function (e) {
            var reader = new FileReader();
            reader.onload = function (e) {
                document.getElementById('p').src = e.target.result;
                document.getElementById('p').style.display = 'block';
            }
            reader.readAsDataURL(e.target.files[0]);
        })

        //添加水印
        document.getElementById('confirmButton').addEventListener('click', function () {
            var image = document.getElementById('imageUpload').files[0]; //图片对象
            var watermarkText = document.getElementById('watermarkText').value; //水印对象
            var canvas = document.getElementById('canvas');  //canvas
            var ctx = canvas.getContext('2d');
            var img = new Image(); //img对象
            var fontsize = document.getElementById('ipt1').value; //初始大小
            var transparency = document.getElementById('ipt2').value / 10; //透明度
            var jianju = document.getElementById('ipt3').value; //间距
            //单行多行
            
            //倾斜方式
            var tilt = document.getElementById('s2').value;
            var angle = document.getElementById('ipt4').value;
            img.onload = function () {
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);
                ctx.font = fontsize + 'px Arial'; //大小 字体
                ctx.fillStyle = `rgba(170, 171, 172, ${transparency})`;
                if (tilt === 'left') painWatermarket_left(watermarkText, canvas, jianju, ctx, angle);
                if (tilt === 'right') painWatermarket_right(watermarkText, canvas, jianju, ctx, angle);
            };
            img.src = URL.createObjectURL(image);
        });

        // 单行左倾斜params: watermarkText canvas jianju\ 
        function painWatermarket_left(watermarkText, canvas, jianju, ctx, angle, lineNumber) {
            var txtLen = Math.ceil(ctx.measureText(watermarkText).width / 2);
            for (var i = 150 - txtLen, j = 150 - txtLen;
                i < canvas.width, j < canvas.height;
                i += canvas.width / jianju, j += canvas.height / jianju) {
                ctx.save();
                ctx.translate(i, j);
                ctx.rotate(angle * Math.PI / 180);
                ctx.fillText(watermarkText, 0, 0);
                ctx.restore();
            }

        }

        // 单行右倾斜params: watermarkText canvas jianju
        function painWatermarket_right(watermarkText, canvas, jianju, ctx, angle) {
            angle = -1 * angle;
            var txtLen = Math.ceil(ctx.measureText(watermarkText).width / 2); //文本宽度
            for (var i = 150 - txtLen, j = canvas.height; i < canvas.width, j > 150 - txtLen; i += canvas.width / jianju, j -= canvas.height / jianju) {
                ctx.save();
                ctx.translate(i, j);
                ctx.rotate(angle * Math.PI / 180);
                ctx.fillText(watermarkText, 0, 0);
                ctx.restore();
            }
        }

        //保存
        document.getElementById('saveButton').addEventListener('click', function () {
            var canvas = document.getElementById('canvas');
            var dataUrl = canvas.toDataURL('image/png');
            var blob = dataURItoBlob(dataUrl);
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = 'demo.png';
            link.click();
        });

        function dataURItoBlob(dataURI) {
            var byteString;
            if (dataURI.split(',')[0].indexOf('base64') >= 0)
                byteString = atob(dataURI.split(',')[1]);
            else
                byteString = unescape(dataURI.split(',')[1]);

            var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
            var ab = new ArrayBuffer(byteString.length);
            var ia = new Uint8Array(ab);
            for (var i = 0; i < byteString.length; i++) {
                ia[i] = byteString.charCodeAt(i);
            }
            return new Blob([ab], { type: mimeString });
        }
        //重置
        function flush() {
            location.reload();
        }
    </script>
</body>

</html>

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

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

相关文章

内网靶机~~dc-2

一、信息收集 1.端口扫描&#xff1a; nmap -sV -p 1-10000 10.1.1.4 2.CMS识别 3.目录扫描&#xff1a; dirsearch http://10.1.1.4/ 4.FLAG1 似乎让我们用cewl生成密码字典&#xff0c;并爆破登录。 cewl -w rewl_passwd.txt http://dc-2/index.php/flag/ 总结&#xff…

MySQL文件系统解密:binlog、redolog与undolog如何守护数据安全与一致性

目录 一、MySQL文件组成 1.1 数据库层面的文件 错误日志文件 慢查询日志 查询日志 二进制日志(binlog) pid文件 表结构定义文件 1.2 存储引擎层面的文件 表空间文件 重做日志 撤销日志 二、MySQL 单机的二阶段提交 两阶段提交 从概念上说数据库是文件的集合&#xff0c;是依照…

基于java高校社团招新系统设计与实现

摘要 &#xff1a;大学学生社团的不断壮大发展&#xff0c;让对社团的招新管理越来越重要&#xff0c;如何高效的管理社团&#xff0c;促进社团有效的运行和发展变得尤为关键。学生社团在学生的成长发展过程中有着一定的积极作用&#xff0c;要发挥好社团的优势&#xff0c;管…

电脑ip地址如何改?这些修改方法请收好!

在数字化日益深入的今天&#xff0c;电脑作为我们日常工作和生活中的重要工具&#xff0c;其网络功能显得尤为关键。而在网络世界中&#xff0c;IP地址则是电脑连接互联网的身份证&#xff0c;它标识着电脑在网络中的位置与身份。然而&#xff0c;在某些特定情境下&#xff0c;…

基于jsp+mysql+Spring的SpringBoot招聘网站项目

基于jspmysqlSpring的SpringBoot招聘网站项目&#xff08;完整源码sql&#xff09;主要实现了管理员登录,简历管理,问答管理,职位管理,用户管理,职位申请进度更新,查看简历 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀…

线性回归模型

线性回归模型是一种用于建模因变量与一个或多个自变量之间线性关系的统计模型。它被广泛应用于回归分析中&#xff0c;用于预测或解释连续型因变量的取值。 线性回归模型假设因变量&#xff08;或称响应变量&#xff09; y 与自变量&#xff08;或称特征&#xff09; x 之间存…

【WEEK5】 【DAY4】数据库操作【中文版】

2024.3.28 Thursday 目录 2.数据库操作2.1.数据库2.1.1.新建数据库&#xff08;右键的方法&#xff09;2.1.2.查询&#xff1a;点击“查询”->“新建查询表”即可输入所需要的语句&#xff0c;点击“运行”&#xff0c;如&#xff1a; 2.2.结构化查询语句分类2.3.数据库操作…

CSS3 (一)

一、CSS3 2D转换 转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果。转换&#xff08;transform&#xff09;你可以简单理解为变形。 移动&#xff1a;translate 、旋转&#xff1a;rotate 、缩放&#xf…

双向长短期BiLSTM的回归预测-附MATLAB代码

BiLSTM是一种带有正反向连接的长短期记忆网络&#xff08;LSTM&#xff09;。 BiLSTM通过两个独立的LSTM层&#xff0c;一个按时间顺序处理输入&#xff0c;另一个按时间倒序处理输入&#xff0c;分别从正向和反向两个方向捕捉输入序列的特征。具体地&#xff0c;正向LSTM按时…

接口自动化框架搭建(三):pytest库安装

1&#xff0c;使用命令行安装 前提条件&#xff1a;已安装python环境 pip install pytest 或者 pip3 install pytest2&#xff0c;从编译器pycharme中安装

物理寻址和功能寻址,服务器不同的应答策略和NRC回复策略

1&#xff1a;功能寻址&#xff0c;服务器应答与NRC回复策略 详细策略上&#xff0c;又分为服务有子功能&#xff0c;和不存在子功能。 1.1功能寻址&#xff0c;存在子功能 存在子功能的情况下&#xff0c;又分为supress postive response &#xff08;即子功能字节的bit7&a…

WMware虚拟机配置静态IP

注意&#xff1a;如果是克隆的虚拟机&#xff0c;需要先重新生成mac地址&#xff0c;如下图所示 修改配置文件 &#xff1a;/etc/sysconfig/network-scripts/ifcfg-ens33 注意&#xff1a;1. BOOTPROTO设置为static 2.将下面的IPADDR地址替换为你实际要设置的ip地址 3.NAT模式…

聚酰亚胺PI材料难于粘接,用什么胶水粘接?那么让我们先一步步的从认识它开始(十三): 聚酰亚胺PI纤维的缺点

聚酰亚胺PI纤维的缺点 聚酰亚胺PI纤维虽然是一种具有许多优异特性的高性能纤维&#xff0c;但也存在一些缺点和局限性&#xff0c;这些缺点可能会影响其在某些应用领域的适用性。主要缺点包括&#xff1a; 1.成本高&#xff1a;聚酰亚胺PI纤维的生产过程复杂&#xff0c;原料成…

【倪琴神品品鉴】全新倪诗韵神品级古琴

倪琴朱砂神品仲尼&#xff0c;仅此放漏一张&#xff1b;龙池侧签海门倪诗韵制&#xff0c;雁足上方刻“雷音琴坊”方章&#xff0c;凤沼下方有随形章“神品”二字&#xff1b;老木材纹理竖直&#xff0c;共振良好&#xff0c;是难得的佳器&#xff1b;附带倪老师亲笔签名收藏证…

以太网/USB 数据采集卡 24位16通道 labview 256K同步采样

XM7016以太网SUB数据采集卡 XM7016是一款以太网/USB高速数据采集卡&#xff0c;具有16通道真差分输入&#xff0c;24位分辨率&#xff0c;单通道最高采样率256ksps. 16通道同步共计4.096Msps、精密前置增益放大、集成IEPE/ICP硬件支持的特点。本产品采用了多个高精度24位ADC单元…

想做跨境电商测评自养号需要满足什么条件?

测评对于卖家来说算是一种低成本&#xff0c;高回报的推广营销方式&#xff0c;对于商品流量&#xff0c;转化率&#xff0c;关键词质量分&#xff0c;链接权重等都起到了一定的辅助作用&#xff0c;但凡事都有好坏&#xff0c;倘若处理不得当&#xff0c;很容易影响店铺&#…

jupyter 设置工作目录

本博客主要介绍&#xff1a; 如何为jupyter设置工作目录 1.打开 anaconda prompt , 执行 jupyter notebook --generate-config 执行这个命令后会生成一个配置文件 2. 打开jupyter_notebook_config.py文件编辑 搜索notebook_dir&#xff0c;把这行代码的注释取消&#xff0c;…

HN热帖|替换Redis的一场赛跑

3 月 21 日&#xff0c; Redis Ltd. 宣布了一项重大决定&#xff1a;Redis “内存数据存储”项目从 Redis 7.4 版本开始将以非自由的、源代码可用的许可证发布。这一消息并不受欢迎&#xff0c;但也并非完全意外。这次的变化的不同寻常之处是市面上已经有了多个 Redis 替代品可…

FreeRTOS day1

1.总结keil5下载代码和编译代码需要注意的事项 需要与板子连通 配置完成后才点击下载 2.总结STM32Cubemx的使用方法和需要注意的事项 下载支持包 打开芯片配置界面 3.总结STM32Cubemx配置GPIO的方法

笔记本电脑上部署LLaMA-2中文模型

尝试在macbook上部署LLaMA-2的中文模型的详细过程。 &#xff08;1&#xff09;环境准备 MacBook Pro(M2 Max/32G); VMware Fusion Player 版本 13.5.1 (23298085); Ubuntu 22.04.2 LTS; 给linux虚拟机分配8*core CPU 16G RAM。 我这里用的是16bit的量化模型&#xff0c;…