在线水印生成源码

Blank
2024-10-19 / 0 评论 / 164 阅读 / 正在检测是否收录...
前言

演示网址:https://uurr.cn/myfile/page/watermark/
支持文字水印和图片水印,支持自定义水印大小,颜色,旋转方向,间距,透明度

效果

m2fq90pp.png

代码
<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>水印生成器</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      background-color: #f9f9f9;
      color: #333;
      display: flex;
      padding: 50px;
      margin: 0;
    }

    .image-container {
      flex: 1;
      display: flex;
      justify-content: center;
      align-items: center;
      border: 1px solid #ccc;
      background-color: white;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      margin-right: 50px;

    }

    .settings-container {
      flex: 0 0 350px;
      /* 允许放大,基础宽度为310px */
      display: flex;
      flex-direction: column;
      margin-right: 50px;

    }

    h1 {
      margin-bottom: 20px;
      font-size: 24px;
      text-align: center;
    }

    input[type="file"],
    input[type="text"],
    input[type="color"],
    input[type="range"],
    button {
      padding: 6px;
      margin: 6px 0;
      border: 1px solid #ccc;
      border-radius: 5px;
      width: 50%;
      font-size: 16px;
    }
    input[type="file"],
    input[type="text"],
    input[type="color"],
    input[type="range"],
    button {
      padding: 6px;
      margin: 6px 0;
      border: 1px solid #ccc;
      border-radius: 5px;
      width: 60%;
      font-size: 16px;
    }
    button {
      background-color: #007bff;
      color: white;
      border: none;
      cursor: pointer;
      transition: background-color 0.3s;
       width: 100%;
    }

    button:hover {
      background-color: #0056b3;
    }

    canvas {
      max-width: 90%;
      height: auto;
    }

    .slider-label {
        margin-top:10px ;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
  </style>
</head>

<body>
  <div class="image-container">
    <canvas id="canvas"></canvas>
  </div>
  <div class="settings-container">

    <h1>在线水印生成器</h1>
    
    <div class="slider-label">
        <label>选择图片</label>
      <input type="file" id="imageUpload" accept="image/*" placeholder="上传主图">
    </div>
    
    <div class="slider-label">
      <label>图片水印</label>
      <input type="text" id="watermarkText" placeholder="输入水印文字" value="输入水印文字">
    </div>

    <div class="slider-label">
      <span>图片水印</span>
      <input type="file" id="watermarkImageUpload" accept="image/*" placeholder="上传水印图片">
    </div>


    <div class="slider-label">
      <label for="watermarkColor">文字颜色</label>
      <input type="color" id="watermarkColor" value="#ffffff">
    </div>


    <div class="slider-label">
      <label for="watermarkSize">文字大小</label>
      <input type="range" id="watermarkSize" min="1" max="100" value="20">
      <span id="watermarkSizeValue">20</span>
    </div>

    <div class="slider-label">
      <label for="spacing">文字间距</label>
      <input type="range" id="spacing" min="90" max="300" value="100">
      <span id="spacingValue">100</span>
    </div>

    <div class="slider-label">
      <label for="rotation">水印角度</label>
      <input type="range" id="rotation" min="0" max="360" value="310">
      <span id="rotationValue">310</span>
    </div>

    <div class="slider-label">
      <label for="opacity">水印透明</label>
      <input type="range" id="opacity" min="0" max="100" value="50">
      <span id="opacityValue">50</span>
    </div>


    <button class="save" id="saveButton">保存图片</button>
  </div>

  <script>
    const imageUpload = document.getElementById('imageUpload');
    const watermarkImageUpload = document.getElementById('watermarkImageUpload');
    const watermarkText = document.getElementById('watermarkText');
    const watermarkColor = document.getElementById('watermarkColor');
    const watermarkSize = document.getElementById('watermarkSize');
    const spacing = document.getElementById('spacing');
    const rotation = document.getElementById('rotation');
    const opacity = document.getElementById('opacity');
    const saveButton = document.getElementById('saveButton');
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    let mainImage, watermarkImage;

    // 初始化数值显示
    const watermarkSizeValue = document.getElementById('watermarkSizeValue');
    const spacingValue = document.getElementById('spacingValue');
    const rotationValue = document.getElementById('rotationValue');
    const opacityValue = document.getElementById('opacityValue');

    imageUpload.addEventListener('change', handleImageUpload);
    watermarkImageUpload.addEventListener('change', handleWatermarkImageUpload);
    watermarkText.addEventListener('input', generateWatermarkedImage);
    watermarkColor.addEventListener('input', generateWatermarkedImage);
    watermarkSize.addEventListener('input', () => {
      watermarkSizeValue.textContent = watermarkSize.value; // 更新文字大小数值
      generateWatermarkedImage();
    });
    spacing.addEventListener('input', () => {
      spacingValue.textContent = spacing.value; // 更新间距数值
      generateWatermarkedImage();
    });
    rotation.addEventListener('input', () => {
      rotationValue.textContent = rotation.value; // 更新旋转角度数值
      generateWatermarkedImage();
    });
    opacity.addEventListener('input', () => {
      opacityValue.textContent = opacity.value; // 更新透明度数值
      generateWatermarkedImage();
    });
    saveButton.addEventListener('click', saveImage);

    function handleImageUpload(event) {
      const file = event.target.files[0];
      if (file) {
        const reader = new FileReader();
        reader.onload = function (e) {
          mainImage = new Image();
          mainImage.src = e.target.result;
          mainImage.onload = () => {
            canvas.width = mainImage.width;
            canvas.height = mainImage.height;
            generateWatermarkedImage();
          }
        }
        reader.readAsDataURL(file);
      }
    }

    function handleWatermarkImageUpload(event) {
      const file = event.target.files[0];
      if (file) {
        const reader = new FileReader();
        reader.onload = function (e) {
          watermarkImage = new Image();
          watermarkImage.src = e.target.result;
          watermarkImage.onload = generateWatermarkedImage; // 当图片加载完成时生成水印
        }
        reader.readAsDataURL(file);
      }
    }

    function generateWatermarkedImage() {
      if (!mainImage) return;

      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(mainImage, 0, 0);

      const size = parseInt(watermarkSize.value);
      const spacingValue = parseInt(spacing.value);
      const color = watermarkColor.value;
      const angle = parseInt(rotation.value) * (Math.PI / 180); // 角度转换为弧度
      const alpha = parseInt(opacity.value) / 100; // 透明度转换为小数

      const rows = Math.ceil(canvas.height / (size + spacingValue));
      const cols = Math.ceil(canvas.width / (size + spacingValue));

      for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
          const x = j * (size + spacingValue);
          const y = i * (size + spacingValue) + size; // +size 确保文字不会被遮挡

          ctx.save(); // 保存当前状态
          ctx.translate(x + size / 2, y - size / 2); // 移动到水印中心
          ctx.rotate(angle); // 旋转

          if (watermarkText.value) {
            ctx.font = `${size}px Arial`;
            ctx.fillStyle = color;
            ctx.globalAlpha = alpha; // 设置透明度
            ctx.fillText(watermarkText.value, -ctx.measureText(watermarkText.value).width / 2, 0); // 绘制文字,中心对齐
          }

          if (watermarkImage) {
            ctx.globalAlpha = alpha; // 设置透明度
            ctx.drawImage(watermarkImage, -size / 2, -size / 2, size, size); // 假设图片水印也是方形
          }

          ctx.restore(); // 恢复状态
        }
      }

      ctx.globalAlpha = 1; // 重置透明度
    }


    function saveImage() {
      const link = document.createElement('a');
      link.download = 'watermarked-image.png';
      link.href = canvas.toDataURL('image/png');
      link.click();
    }
  </script>
</body>

</html>
代码详解

HTML结构:

updateFileName()函数在用户选择文件时被调用。
input.files是一个FileList对象,包含用户选择的文件。如果用户选择了文件,就会更新的文本内容为文件名;如果没有选择文件,则保持默认提示。

0

评论 (0)

夸夸
取消