(分享)一个图片添加水印的小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>
相关推荐
web1350858863523 分钟前
前端node.js
前端·node.js·vim
m0_5127446424 分钟前
极客大挑战2024-web-wp(详细)
android·前端
若川33 分钟前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
潜意识起点1 小时前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛1 小时前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿1 小时前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256563 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@3 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
F-2H7 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++