图片批量模糊工具动态效果

联启 电脑工具 16
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">动态模糊 · 图片批量工具</title>
  <style>
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    body {
      background: #0b0d15;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
      padding: 20px;
    }
    .card {
      max-width: 1000px;
      width: 100%;
      background: rgba(20, 24, 32, 0.8);
      backdrop-filter: blur(4px);
      -webkit-backdrop-filter: blur(4px);
      border-radius: 48px;
      padding: 32px 28px;
      box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(255, 255, 255, 0.04);
      transition: box-shadow 0.2s;
    }
    h1 {
      display: flex;
      align-items: center;
      gap: 12px;
      font-weight: 500;
      font-size: 1.8rem;
      letter-spacing: -0.01em;
      color: #eef2ff;
      margin-bottom: 24px;
    }
    h1 span {
      background: #2b324a;
      padding: 4px 14px;
      border-radius: 80px;
      font-size: 0.9rem;
      font-weight: 400;
      color: #b3c2e2;
    }
    .toolbar {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 16px 20px;
      margin-bottom: 28px;
      background: #10131f;
      padding: 16px 20px;
      border-radius: 60px;
      border: 1px solid #2a3147;
    }
    .btn {
      background: #252d44;
      border: none;
      padding: 10px 20px;
      border-radius: 40px;
      font-weight: 450;
      font-size: 0.95rem;
      color: #d6e2ff;
      display: inline-flex;
      align-items: center;
      gap: 8px;
      cursor: pointer;
      transition: 0.2s;
      box-shadow: 0 2px 4px rgba(0,0,0,0.2);
      border: 1px solid #3e4762;
      flex-shrink: 0;
    }
    .btn-primary {
      background: #4a5bcd;
      border-color: #6e7ee0;
      color: white;
      box-shadow: 0 4px 10px rgba(74, 91, 205, 0.25);
    }
    .btn-primary:hover {
      background: #5d6fdf;
      transform: scale(1.02);
    }
    .btn-primary:active {
      transform: scale(0.96);
    }
    .btn-outline {
      background: transparent;
      border: 1px solid #3f4a6b;
      color: #b9c8f0;
    }
    .btn-outline:hover {
      background: #1c233b;
      border-color: #6574a8;
    }
    .btn:active {
      transform: scale(0.96);
    }
    .blur-slider {
      display: flex;
      align-items: center;
      gap: 14px;
      flex: 1;
      min-width: 160px;
    }
    .blur-slider label {
      color: #b5c5f0;
      font-size: 0.9rem;
      white-space: nowrap;
    }
    input[type="range"] {
      -webkit-appearance: none;
      appearance: none;
      background: #262f4a;
      height: 6px;
      border-radius: 6px;
      flex: 1;
      min-width: 80px;
      outline: none;
    }
    input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 18px;
      height: 18px;
      border-radius: 20px;
      background: #7f92f0;
      border: 2px solid #b6c6ff;
      cursor: pointer;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
      transition: 0.1s;
    }
    input[type="range"]::-webkit-slider-thumb:hover {
      transform: scale(1.12);
      background: #95a6ff;
    }
    .blur-value {
      min-width: 44px;
      text-align: center;
      font-weight: 500;
      color: #dce6ff;
      background: #1b2136;
      padding: 4px 8px;
      border-radius: 40px;
      font-size: 0.9rem;
    }
    .gallery {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
      gap: 20px;
      margin: 20px 0 10px;
    }
    .image-card {
      background: #141b2b;
      border-radius: 28px;
      overflow: hidden;
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
      transition: transform 0.2s, box-shadow 0.3s;
      aspect-ratio: 1 / 1;
      display: flex;
      align-items: center;
      justify-content: center;
      border: 1px solid #2b344f;
      position: relative;
    }
    .image-card img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
      transition: filter 0.2s ease;
      will-change: filter;
    }
    .image-card .remove-btn {
      position: absolute;
      top: 10px;
      right: 10px;
      background: #0f1322cc;
      backdrop-filter: blur(8px);
      border: none;
      width: 32px;
      height: 32px;
      border-radius: 40px;
      color: #f0f4ff;
      font-size: 20px;
      line-height: 26px;
      text-align: center;
      cursor: pointer;
      transition: 0.15s;
      opacity: 0;
      border: 1px solid #ffffff30;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .image-card:hover .remove-btn {
      opacity: 1;
    }
    .image-card .remove-btn:hover {
      background: #d2435ccc;
      transform: scale(1.05);
    }
    .empty-state {
      grid-column: 1 / -1;
      text-align: center;
      padding: 64px 20px;
      color: #8596c9;
      background: #101624;
      border-radius: 40px;
      border: 1px dashed #2f3c62;
      font-size: 1rem;
      display: flex;
      flex-direction: column;
      gap: 8px;
      align-items: center;
    }
    .empty-state svg {
      opacity: 0.6;
      margin-bottom: 8px;
    }
    .footer {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 18px;
      color: #6b7db0;
      font-size: 0.85rem;
      flex-wrap: wrap;
      gap: 8px;
    }
    .footer .count {
      background: #1b233b;
      padding: 6px 16px;
      border-radius: 40px;
      border: 1px solid #2c365a;
    }
    .clear-btn {
      background: transparent;
      border: none;
      color: #8899d4;
      text-decoration: underline dotted #3c4a78;
      padding: 6px 12px;
      cursor: pointer;
      border-radius: 30px;
      transition: 0.15s;
    }
    .clear-btn:hover {
      color: #bbc8ff;
      background: #181f38;
    }
    @media (max-width: 600px) {
      .card { padding: 20px 16px; }
      .toolbar { flex-wrap: wrap; padding: 14px; border-radius: 40px; }
      .btn { padding: 8px 16px; font-size: 0.85rem; }
      .gallery { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
      h1 { font-size: 1.4rem; }
    }
  </style>
</head>
<body>
<div class="card">
  <h1>
    ⚡ 模糊工坊
    <span>动态效果</span>
  </h1>
  <div class="toolbar">
    <button class="btn btn-primary" id="addImageBtn">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h3"/><path d="M15 6h6v6"/><path d="M10 14 21 3"/></svg>
      添加图片
    </button>
    <div class="blur-slider">
      <label>🌫️ 模糊</label>
      <input type="range" id="blurRange" min="0" max="20" step="0.2" value="4">
      <span class="blur-value" id="blurDisplay">4.0</span>
    </div>
    <button class="btn-outline btn" id="resetBlurBtn">重置</button>
  </div>
  <div class="gallery" id="galleryContainer">
    <div class="empty-state" id="emptyPlaceholder">
      <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#6574a8" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
      <span>点击「添加图片」导入照片</span>
      <span style="font-size: 0.8rem; opacity: 0.7;">支持 JPG / PNG / WebP</span>
    </div>
  </div>
  <div class="footer">
    <span class="count" id="imageCount">0 张图片</span>
    <div>
      <button class="clear-btn" id="clearAllBtn">清空全部</button>
    </div>
  </div>
</div>
<script>
  (function(){
    // DOM 元素
    const gallery       = document.getElementById('galleryContainer');
    const emptyState    = document.getElementById('emptyPlaceholder');
    const addBtn        = document.getElementById('addImageBtn');
    const blurRange     = document.getElementById('blurRange');
    const blurDisplay   = document.getElementById('blurDisplay');
    const resetBlurBtn  = document.getElementById('resetBlurBtn');
    const clearAllBtn   = document.getElementById('clearAllBtn');
    const imageCount    = document.getElementById('imageCount');
    // 状态管理
    let imageList = [];               // 存储图片数据: { id, src (dataUrl) }
    let currentBlur = 4;             // 默认模糊值
    let idCounter = 0;
    // 更新模糊值显示
    function updateBlurValue(val) {
      const v = parseFloat(val);
      blurDisplay.textContent = v.toFixed(1);
      currentBlur = v;
    }
    // 应用模糊到所有图片
    function applyBlurToAll() {
      const imgs = gallery.querySelectorAll('.image-card img');
      const blurValue = currentBlur;
      imgs.forEach(img => {
        img.style.filter = `blur(${blurValue}px)`;
      });
    }
    // 渲染画廊 (基于 imageList)
    function renderGallery() {
      // 清空 gallery 但保留 empty-placeholder 引用
      const items = gallery.querySelectorAll('.image-card');
      items.forEach(el => el.remove());
      if (imageList.length === 0) {
        emptyState.style.display = 'flex';
        imageCount.textContent = `0 张图片`;
        return;
      }
      emptyState.style.display = 'none';
      // 重新填充卡片
      imageList.forEach(item => {
        const card = document.createElement('div');
        card.className = 'image-card';
        card.dataset.id = item.id;
        const img = document.createElement('img');
        img.src = item.src;
        img.alt = '模糊图片';
        img.draggable = false;
        // 应用当前模糊
        img.style.filter = `blur(${currentBlur}px)`;
        img.style.transition = 'filter 0.15s ease';
        const removeBtn = document.createElement('button');
        removeBtn.className = 'remove-btn';
        removeBtn.innerHTML = '✕';
        removeBtn.setAttribute('aria-label', '移除图片');
        removeBtn.addEventListener('click', function(e) {
          e.stopPropagation();
          const id = parseInt(card.dataset.id);
          removeImageById(id);
        });
        card.appendChild(img);
        card.appendChild(removeBtn);
        gallery.appendChild(card);
      });
      imageCount.textContent = `${imageList.length} 张图片`;
    }
    // 根据 id 移除图片
    function removeImageById(id) {
      imageList = imageList.filter(item => item.id !== id);
      renderGallery();
    }
    // 清空全部图片
    function clearAllImages() {
      if (imageList.length === 0) return;
      imageList = [];
      renderGallery();
    }
    // 添加新图片 (从 File 对象)
    function addImageFromFile(file) {
      if (!file || !file.type.startsWith('image/')) return;
      const reader = new FileReader();
      reader.onload = function(e) {
        const src = e.target.result;
        const newItem = {
          id: ++idCounter,
          src: src
        };
        imageList.push(newItem);
        renderGallery();
      };
      reader.readAsDataURL(file);
    }
    // 打开文件选择器
    function openFilePicker() {
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = 'image/*';
      input.multiple = true;
      input.style.display = 'none';
      document.body.appendChild(input);
      input.addEventListener('change', function(e) {
        const files = Array.from(e.target.files);
        if (files.length === 0) {
          document.body.removeChild(input);
          return;
        }
        files.forEach(file => addImageFromFile(file));
        document.body.removeChild(input);
      });
      input.click();
    }
    // ------ 事件绑定 ------
    // 添加图片按钮
    addBtn.addEventListener('click', openFilePicker);
    // 模糊滑块
    blurRange.addEventListener('input', function(e) {
      const val = e.target.value;
      updateBlurValue(val);
      applyBlurToAll();
    });
    // 重置模糊 (设为0)
    resetBlurBtn.addEventListener('click', function() {
      blurRange.value = 0;
      updateBlurValue(0);
      applyBlurToAll();
    });
    // 清空按钮
    clearAllBtn.addEventListener('click', clearAllImages);
    // 额外: 点击空状态触发添加 (方便)
    emptyState.addEventListener('click', openFilePicker);
    // 初始化模糊显示
    blurRange.value = currentBlur;
    updateBlurValue(currentBlur);
    // 初始无图片,无需渲染
    renderGallery();
    // 演示:内置两张示例图片(动态效果展示)
    function loadDemoImages() {
      // 第一个示例 (SVG 矢量风格抽象图 1)
      const svg1 = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Crect width='200' height='200' fill='%231b253a'/%3E%3Ccircle cx='100' cy='90' r='60' fill='%233f5ec9' opacity='0.9'/%3E%3Ccircle cx='70' cy='70' r='30' fill='%237992f0' opacity='0.7'/%3E%3Cpolygon points='100,140 140,100 60,100' fill='%23ffb347' opacity='0.7'/%3E%3Ctext x='80' y='170' font-size='22' fill='%23bcccf0' font-weight='500'%3E🌆%3C/text%3E%3C/svg%3E`;
      const svg2 = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Crect width='200' height='200' fill='%23202b42'/%3E%3Crect x='30' y='30' width='140' height='140' rx='40' fill='%23344b92' opacity='0.8'/%3E%3Ccircle cx='110' cy='80' r='40' fill='%23f9d976' opacity='0.6'/%3E%3Cpath d='M40 170 L80 110 L120 140 L170 70' stroke='%237aa2ff' stroke-width='6' fill='none' stroke-linecap='round' /%3E%3Ctext x='60' y='180' font-size='24' fill='%23b0c8ff' %3E✨%3C/text%3E%3C/svg%3E`;
      // 以文件添加方式模拟 (以便展示移除效果)
      // 但直接用 item 推入更简洁
      const demoItem1 = { id: ++idCounter, src: svg1 };
      const demoItem2 = { id: ++idCounter, src: svg2 };
      imageList.push(demoItem1, demoItem2);
      renderGallery();
    }
    // 启动演示 (若用户无图片则显示示例)
    // 但我们可以考虑只在画廊为空时加载演示,并延迟片刻让用户看到空状态也可。
    setTimeout(() => {
      if (imageList.length === 0) {
        loadDemoImages();
      }
    }, 300);
  })();
</script>
</body>
</html>

图片模糊工具使用说明

您可以通过简单的操作,为多张图片添加统一的动态模糊效果。

图片批量模糊工具动态效果-第1张图片-电脑手机工具软件下载 - 免费实用工具合集 | 联启科技

  1. 图片管理:点击 “添加图片” 按钮,可从本地选择多张图片进行批量导入,每张图片右上角都有一个 按钮,方便您单独移除。
  2. 模糊调节:通过拖动 “模糊”滑块,您可以实时调整所有图片的模糊程度,数值范围从0到20,点击 “重置” 按钮可将模糊值快速归零。
  3. 状态反馈:页面底部会显示当前图片总数,当没有图片时,会显示引导提示,点击该区域也可触发图片添加。

标签: 批量处理

抱歉,评论功能暂时关闭!