html案例:制作一个图片水印生成器,防止复印件被滥用
使用HTML结合JavaScript,可以轻松创建一个图片水印生成器,离线版本的单页面工具。该工具允许用户上传图片并添加自定义文本水印,生成带有可见标记的图像提供下载。这样,当复印件被滥用时,水印能提供所有权证明和溯源依据,有效防止非法复制和使用。
界面效果图如下:
代码部分:
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>高级图片加水印工具</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {font-family: 'Segoe UI', Arial, sans-serif;background-color: #f4f4f4;height: 100vh;overflow: hidden;display: flex;}.container {width: 100%;height: 100%;display: flex;}/* 图片预览区域 - 左侧 */.preview-panel {flex: 1;display: flex;justify-content: center;align-items: center;background-color: #eee;overflow: auto;}#canvas {max-width: 95vw;max-height: 95vh;border: 1px solid #ccc;box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);border-radius: 8px;}/* 参数控制面板 - 右侧 */.form-panel {width: 320px;background-color: #fff;padding: 20px;border-left: 1px solid #ddd;overflow-y: auto;height: 100vh;}.form-group {margin-bottom: 16px;}label {display: block;margin-bottom: 6px;font-weight: 500;color: #333;}input[type="text"],input[type="number"],input[type="range"],input[type="file"],select {width: 100%;padding: 10px;border: 1px solid #ccc;border-radius: 4px;font-size: 14px;}input[type="color"] {width: 50px;height: 36px;cursor: pointer;}button {width: 100%;padding: 12px;background-color: #007bff;color: white;border: none;border-radius: 4px;font-size: 16px;cursor: pointer;margin-top: 10px;}button:disabled {background-color: #ccc;cursor: not-allowed;}button:hover:not(:disabled) {background-color: #0056b3;}.switch {position: relative;display: inline-block;width: 50px;height: 24px;}.switch input {opacity: 0;width: 0;height: 0;}.slider {position: absolute;cursor: pointer;top: 0;left: 0;right: 0;bottom: 0;background-color: #ccc;transition: .4s;border-radius: 24px;}.slider:before {position: absolute;content: "";height: 18px;width: 18px;left: 4px;bottom: 3px;background-color: white;transition: .4s;border-radius: 50%;}input:checked + .slider {background-color: #007bff;}input:checked + .slider:before {transform: translateX(26px);}.switch-label {display: flex;align-items: center;gap: 10px;}</style>
</head>
<body>
<div class="container"><!-- 左侧:图片预览 --><div class="preview-panel"><canvas id="canvas"></canvas></div><!-- 右侧:参数面板 --><div class="form-panel"><h2 style="margin-bottom: 20px; color: #333;">水印设置</h2><div class="form-group"><label for="imageInput">选择图片</label><input type="file" id="imageInput" accept="image/*" /></div><div class="form-group"><label for="presetSelect">选择预设:</label><select id="presetSelect" onchange="applyPreset()"><option value="">请选择...</option><!-- 预设选项将通过JavaScript动态生成 --></select></div><div class="form-group"><label for="watermarkText">水印文字</label><input type="text" id="watermarkText" placeholder="请输入水印文字" value="复印无效" /></div><div class="form-group"><label class="switch-label"><span>开启水印错位</span><label class="switch"><input type="checkbox" id="staggeredToggle" /><span class="slider"></span></label></label><small style="color: #666;">开启后奇数行和偶数行水印交错排列,防拼接</small></div><div class="form-group"><label for="angle">倾斜角度(度)</label><input type="number" id="angle" min="-360" max="360" step="1" value="45" /></div><div class="form-group"><label for="color">水印颜色</label><input type="color" id="color" value="#FF0000" /></div><div class="form-group"><label for="fontSize">字体大小(px)</label><input type="number" id="fontSize" min="10" max="100" step="1" value="32" /></div><div class="form-group"><label for="fontFamily">字体</label><select id="fontFamily"><option value="Arial">Arial</option><option value="SimHei">黑体</option><option value="SimSun">宋体</option><option value="Microsoft YaHei">微软雅黑</option></select></div><div class="form-group"><label for="opacity">透明度(0.0 - 1.0)</label><input type="range" id="opacity" min="0" max="1" step="0.05" value="0.3" /><span id="opacityValue" style="font-size:12px; color:#666;">0.3</span></div><div class="form-group"><label for="horizontalSpacing">横向间距(px)</label><input type="number" id="horizontalSpacing" min="0" value="100" /></div><div class="form-group"><label for="verticalSpacing">纵向间距(px)</label><input type="number" id="verticalSpacing" min="0" value="100" /></div><button id="downloadBtn" disabled>📥 下载带水印图片</button></div>
</div><script> // 定义预设配置const presets = [// 综合{ name: "租房合同使用", text: "本复印件仅用于租赁XX小区XX房使用,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "购房资格审核", text: "本件仅用于购房资格审查,不得用于其他用途。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "公司入职材料", text: "本复印件仅用于XX公司员工入职档案建立,不得外泄。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "子女入学报名", text: "本复印件仅用于XX小学2025年秋季入学报名使用,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "公积金提取", text: "本复印件仅用于住房公积金提取申请,不得挪作他用。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "社保办理", text: "本件仅用于社会保险参保登记,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "医保报销", text: "本复印件仅用于医疗保险费用报销,有效期至2025年12月31日。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "签证申请", text: "本复印件仅用于申办XX国旅游签证,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "营业执照办理", text: "本件仅用于个体工商户营业执照申请,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "婚姻登记", text: "本复印件仅用于结婚登记手续,不得用于其他用途。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "银行开户", text: "本复印件仅用于在XX银行开立个人账户,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "学历认证", text: "本复印件仅用于学信网学历认证,有效期至2025年12月。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "医院住院登记", text: "本复印件仅用于XX医院住院身份核验,不得外传。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "商业保险投保", text: "本复印件仅用于重大疾病保险投保审核,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "理赔材料提交", text: "本件仅用于意外伤害保险理赔,不得用于其他索赔。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "商标注册材料", text: "本复印件仅用于个体工商户商标注册申请,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "公司股东变更", text: "本件仅用于XX有限公司股东信息变更备案,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "招投标文件附件", text: "本复印件仅作为XX项目投标文件组成部分,不得单独使用。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "物业装修备案", text: "本件仅用于住宅装修手续登记,有效期至2025年11月30日。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "小区停车位登记", text: "本复印件仅用于业主固定停车位信息备案,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "社区志愿者登记", text: "本复印件仅用于社区志愿服务信息录入,不得外泄。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "遗产继承公证", text: "本件仅用于遗产继承公证程序,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "保险理赔", text: "本复印件仅用于XX保险公司意外险理赔申请,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "物业备案", text: "本复印件仅用于XX小区业主信息备案,不得外传。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "政府补贴申请", text: "本复印件仅用于2025年低收入家庭住房补贴申请,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "人才落户申请", text: "本复印件仅用于XX市人才引进落户申请,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "积分入户材料", text: "本件仅用于2025年XX市积分入户审核,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "公租房申请", text: "本复印件仅用于公共租赁住房资格审核,不得用于其他用途。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "低保申请", text: "本复印件仅用于城乡居民最低生活保障申请,有效期至2025年12月。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "出国定居材料", text: "本复印件仅用于移民XX国定居手续,不得另作他用。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "护照换发", text: "本件仅用于普通护照换发申请,有效期至2025年11月30日。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "法院立案材料", text: "本复印件仅用于XX民事案件立案,不得用于其他诉讼。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "仲裁申请", text: "本复印件仅用于劳动争议仲裁提交材料,他用无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "公证委托书附件", text: "本件仅作为委托公证的附件使用,不得单独使用。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "遗产分割协议备案", text: "本复印件仅用于遗产分割协议备案,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "驾校报名", text: "本复印件仅用于XX驾校C1驾驶证培训报名使用。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "电力开户", text: "本复印件仅用于住宅用电户名登记,不得外泄。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "燃气开户", text: "本件仅用于家庭燃气开户手续,仅限XX燃气公司使用。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "宽带安装", text: "本复印件仅用于XX运营商宽带业务办理,复印无效。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "手机实名制登记", text: "本复印件仅用于手机号码实名认证,不得用于其他业务。", color: "#0000FF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },// 银行类{ name: "银行贷款专用", text: "本复印件仅用于XX银行个人贷款申请,他用无效。", color: "#FFD700", fontFamily: "Microsoft YaHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "信用卡申请", text: "本件仅用于XX银行信用卡审批,他用无效。", color: "#FFD700", fontFamily: "Microsoft YaHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "贷款结清证明使用", text: "本复印件仅用于贷款结清后征信更新材料,不得挪用。", color: "#FFD700", fontFamily: "Microsoft YaHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },// 政务类{ name: "车辆年检", text: "本复印件仅用于机动车年度检验,复印无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "残疾证办理", text: "本件仅用于残疾人证申领,仅供残联审核使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "老年证办理", text: "本复印件仅用于60周岁以上老年人优待证办理,他用无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "驾驶证换证", text: "本件仅用于驾驶证期满换证手续,他用无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "房屋过户登记", text: "本复印件仅用于房产过户手续,复印无效,仅供XX不动产登记中心使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "车辆上牌", text: "本复印件仅用于机动车注册登记,仅供车管所使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "法律诉讼材料", text: "本复印件作为XX案件证据提交法院使用,不得另作他用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "学术论文查重材料", text: "本复印件仅用于职称评审论文查重,仅供人事部门使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "教师资格认定", text: "本复印件仅用于中小学教师资格认定申请,复印无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "职称评审材料", text: "本件仅用于2025年度高级工程师职称评审,不得另用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "科研项目申报", text: "本复印件仅用于国家自然科学基金项目申报材料。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "专利申请辅助材料", text: "本件仅用于发明人身份证明,仅供知识产权局审核。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "法人身份证明", text: "本复印件仅用于企业法人代表身份核验,仅供市场监管局使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "房屋租赁备案", text: "本复印件仅用于房屋租赁合同备案登记,有效期至2025年12月。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "房东缴税材料", text: "本件仅用于出租房屋个人所得税申报,仅供税务部门使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "港澳通行证签注", text: "本复印件仅用于个人旅游签注办理,仅供出入境管理部门使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "监护人资格证明", text: "本复印件仅用于未成年人监护关系确认,仅供民政部门使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "领养手续材料", text: "本件仅用于收养登记程序,不得用于其他用途。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "军人家属优待证办理", text: "本复印件仅用于现役军人家属优待政策申请,他用无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "退役军人补贴申领", text: "本件仅用于退役军人生活补贴申报,有效期至2025年12月。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "创业补贴申请", text: "本复印件仅用于高校毕业生创业补贴申请,不得挪用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "失业登记", text: "本件仅用于失业人员信息登记,仅供就业服务中心使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "灵活就业参保", text: "本复印件仅用于灵活就业人员社保参保,复印无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "生育津贴申领", text: "本复印件仅用于生育保险待遇申请,有效期至2025年12月31日。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "新生儿上户口", text: "本复印件仅用于新生儿出生登记,仅供派出所使用。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "疫苗接种证明", text: "本件仅用于儿童预防接种信息核验,他用无效。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },{ name: "工伤认定材料", text: "本件仅用于工伤事故认定申请,不得用于保险骗赔。", color: "#CCCCFF", fontFamily: "SimHei", fontSize: 50, opacity: 0.25, horizontalSpacing: 1200, verticalSpacing: 160, angle: 45 },];// 获取 DOM 元素const imageInput = document.getElementById('imageInput');const watermarkText = document.getElementById('watermarkText');const downloadBtn = document.getElementById('downloadBtn');const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');let originalImage = null;const opacitySlider = document.getElementById('opacity');const opacityValue = document.getElementById('opacityValue');const staggeredToggle = document.getElementById('staggeredToggle');// 错位开关// 显示当前透明度值opacityValue.textContent = opacitySlider.value;opacitySlider.addEventListener('input', () => {opacityValue.textContent = opacitySlider.value;updatePreview();});// === 动态填充预设选项 ===function populatePresets() {presets.forEach(preset => {const option = document.createElement('option');option.value = JSON.stringify(preset);option.textContent = preset.name;presetSelect.appendChild(option);});}// === 应用选中的预设 ===function applyPreset() {const selectedOption = presetSelect.options[presetSelect.selectedIndex];if (!selectedOption.value) return;const preset = JSON.parse(selectedOption.value);watermarkText.value = preset.text;document.getElementById('color').value = preset.color;document.getElementById('fontSize').value = preset.fontSize;document.getElementById('fontFamily').value = preset.fontFamily;document.getElementById('opacity').value = preset.opacity;document.getElementById('horizontalSpacing').value = preset.horizontalSpacing;document.getElementById('verticalSpacing').value = preset.verticalSpacing;document.getElementById('angle').value = preset.angle;updatePreview();}// === 更新预览 ===function updatePreview() {if (!originalImage) return;// 获取所有参数const text = watermarkText.value.trim() || '水印';const angle = parseInt(document.getElementById('angle').value);const color = document.getElementById('color').value;const fontSize = document.getElementById('fontSize').value + 'px';const fontFamily = document.getElementById('fontFamily').value;const opacity = parseFloat(document.getElementById('opacity').value);const horizontalSpacing = parseInt(document.getElementById('horizontalSpacing').value);const verticalSpacing = parseInt(document.getElementById('verticalSpacing').value);const isStaggered = staggeredToggle.checked; // 是否开启错位// 设置画布尺寸为原图大小canvas.width = originalImage.naturalWidth;canvas.height = originalImage.naturalHeight;// 清空画布ctx.clearRect(0, 0, canvas.width, canvas.height);// 绘制原始图片ctx.drawImage(originalImage, 0, 0);// 开始绘制水印ctx.save();ctx.font = `bold ${fontSize} ${fontFamily}`;ctx.textAlign = 'center';ctx.textBaseline = 'middle';// 解析颜色并设置透明度const r = parseInt(color.slice(1, 3), 16);const g = parseInt(color.slice(3, 5), 16);const b = parseInt(color.slice(5, 7), 16);ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${opacity})`;// 计算中心点用于旋转const centerX = canvas.width / 2;const centerY = canvas.height / 2;// 应用旋转ctx.translate(centerX, centerY);ctx.rotate(angle * Math.PI / 180);// 网格状绘制水印const stepX = horizontalSpacing;const stepY = verticalSpacing;// 平铺水印//for (let y = -canvas.height; y < canvas.height * 2; y += stepY) {// for (let x = -canvas.width; x < canvas.width * 2; x += stepX) {// ctx.fillText(text, x, y);// }//}// 错位水印let row = 0;for (let y = -canvas.height; y < canvas.height * 2; y += stepY) {const offsetX = isStaggered && row % 2 === 1 ? stepX / 2 : 0; // 奇数行偏移一半for (let x = -canvas.width; x < canvas.width * 2; x += stepX) {ctx.fillText(text, x + offsetX, y);}row++;}ctx.restore(); // 恢复变换// 启用下载按钮downloadBtn.disabled = false;}// === 图片上传:图片选择事件 ===imageInput.addEventListener('change', function (e) {const file = e.target.files[0];if (!file) return;const reader = new FileReader();reader.onload = function (event) {originalImage = new Image();originalImage.onload = function () {updatePreview(); // 图片加载完成后再绘制};originalImage.src = event.target.result;};reader.readAsDataURL(file);});// // === 所有输入绑定更新:监听所有参数输入事件 ===[watermarkText,document.getElementById('staggeredToggle'),document.getElementById('angle'),document.getElementById('color'),document.getElementById('fontSize'),document.getElementById('fontFamily'),document.getElementById('opacity'),document.getElementById('horizontalSpacing'),document.getElementById('verticalSpacing')].forEach(input => {input.addEventListener('input', updatePreview);});// === 下载功能:下载按钮点击事件 ===downloadBtn.addEventListener('click', function () {//const link = document.createElement('a');//link.href = canvas.toDataURL('image/png');//link.download = 'watermarked_image.png';//link.click();// 使用 JPEG 格式,质量设为 0.8(80% 质量,文件更小)const dataURL = canvas.toDataURL('image/jpeg', 0.8);const link = document.createElement('a');link.href = dataURL;link.download = `watermarked_image_${Date.now()}.jpg`;link.click();});// 页面加载时初始化window.onload = () => {populatePresets();};
</script>
</body>
</html>