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

有时候想给某张图片添加一个自己的水印,但是又懒的下载相应软件,用js canvas制作一个静态页面,对于单张图片添加自定义文字水印,大小 间距,角度可调。

页面如下:

选择图片,设置相应参数,点击添加水印:

效果:

完整程序如下:

html 复制代码
<!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>
相关推荐
特立独行的猫a5 分钟前
Pinia:Vue 2 和 Vue 3 中更好用的状态管理框架
前端·javascript·vue.js·pinia·vuex
武汉前端开发蓝风13 分钟前
纯前端低代码开发脚手架 - daelui/molecule
前端·低代码
奋斗吧程序媛26 分钟前
(接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
前端·javascript·vue.js
YANG-Live1 小时前
数据列表组件-报表
开发语言·javascript
kinlon.liu1 小时前
Web应用安全实用建议
前端·网络·网络协议·安全·centos
narukeu1 小时前
理解 React 的严格模式
前端·javascript·react.js
Bee.Bee.1 小时前
移动端如何调试本地运行的前端项目
前端
Tech Synapse1 小时前
java 如何暴露header给前端
java·开发语言·前端
卓卓没头发1 小时前
掌握Vue插槽:创建灵活且可复用的组件
前端·javascript·vue.js
白臻1 小时前
小程序 npm 支持
前端·小程序·npm