图片批量霓虹工具发光效果

联启 电脑工具 17
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">✨ 霓虹批量发光工具</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
            background: #0b0b1a;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }
        .card {
            max-width: 1200px;
            width: 100%;
            background: #14142b;
            border-radius: 40px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.8), 0 0 0 2px #3b3b7a inset;
            padding: 30px 30px 40px;
            transition: box-shadow 0.2s;
        }
        h1 {
            font-size: 2.4rem;
            font-weight: 600;
            letter-spacing: 2px;
            color: #f0e9ff;
            text-shadow: 0 0 10px #b47cff, 0 0 20px #7a4dff;
            display: flex;
            align-items: center;
            gap: 12px;
            flex-wrap: wrap;
            margin-bottom: 12px;
        }
        h1 small {
            font-size: 1rem;
            font-weight: 400;
            background: #2f2f5e;
            padding: 6px 14px;
            border-radius: 40px;
            color: #cfc3ff;
            text-shadow: none;
            box-shadow: 0 0 6px #aa8cff;
        }
        .control-panel {
            background: #1d1d3e;
            padding: 20px 24px;
            border-radius: 60px;
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            justify-content: space-between;
            gap: 18px 14px;
            margin: 10px 0 24px 0;
            border: 1px solid #3c3c7a;
            box-shadow: 0 6px 0 #0a0a18;
        }
        .file-area {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 12px;
            flex: 2 1 260px;
        }
        .file-label {
            background: #2d2d66;
            padding: 10px 22px;
            border-radius: 80px;
            color: white;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.15s;
            border: 1px solid #6a6ac0;
            box-shadow: 0 4px 0 #15152e;
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }
        .file-label:hover {
            background: #4242a0;
            transform: translateY(-2px);
            box-shadow: 0 6px 0 #15152e;
        }
        .file-label:active {
            transform: translateY(4px);
            box-shadow: 0 1px 0 #15152e;
        }
        #fileInput {
            display: none;
        }
        .badge-count {
            background: #0f0f2a;
            padding: 5px 16px;
            border-radius: 40px;
            color: #b7acff;
            font-size: 0.95rem;
            border: 1px solid #5c5caa;
        }
        .slider-group {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 8px 18px;
            background: #12122e;
            padding: 8px 18px 8px 18px;
            border-radius: 80px;
            border: 1px solid #3b3b7a;
        }
        .slider-group label {
            color: #cfc3ff;
            letter-spacing: 0.3px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        input[type="range"] {
            width: 130px;
            height: 6px;
            background: #2b2b66;
            border-radius: 10px;
            -webkit-appearance: none;
            appearance: none;
        }
        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 18px;
            height: 18px;
            background: #b38eff;
            border-radius: 50%;
            border: 2px solid #f0e9ff;
            box-shadow: 0 0 12px #7f5eff;
            cursor: pointer;
        }
        .value-badge {
            min-width: 32px;
            background: #20204a;
            padding: 2px 6px;
            border-radius: 30px;
            text-align: center;
            color: #ddd3ff;
            font-weight: 500;
        }
        .action-btn {
            background: #3b2a7a;
            border: none;
            color: white;
            padding: 10px 28px;
            border-radius: 60px;
            font-weight: 600;
            font-size: 1rem;
            cursor: pointer;
            transition: 0.1s ease;
            border: 1px solid #9a7eff;
            box-shadow: 0 6px 0 #1c1a3a;
            display: inline-flex;
            align-items: center;
            gap: 6px;
            letter-spacing: 0.5px;
        }
        .action-btn:active {
            transform: translateY(4px);
            box-shadow: 0 2px 0 #1c1a3a;
        }
        .action-btn.primary {
            background: #4f2fc7;
            border-color: #c3aeff;
        }
        .action-btn.primary:hover {
            background: #6a47e6;
        }
        .action-btn.secondary {
            background: #2e2e5a;
            border-color: #7474b0;
        }
        .action-btn.secondary:hover {
            background: #494984;
        }
        .action-btn:disabled {
            opacity: 0.5;
            transform: translateY(2px);
            box-shadow: 0 2px 0 #1c1a3a;
            pointer-events: none;
        }
        .gallery {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
            gap: 22px 16px;
            margin: 28px 0 18px;
            padding-top: 6px;
        }
        .image-card {
            background: #111128;
            border-radius: 24px;
            overflow: hidden;
            box-shadow: 0 10px 20px rgba(0,0,0,0.6);
            transition: transform 0.15s, box-shadow 0.2s;
            border: 1px solid #393971;
            aspect-ratio: 1 / 1;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
        }
        .image-card img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            display: block;
            transition: filter 0.2s;
            image-rendering: auto;
        }
        .image-card .remove-btn {
            position: absolute;
            top: 6px;
            right: 6px;
            background: #1f1f4fcc;
            backdrop-filter: blur(4px);
            border: none;
            color: #ffb6b6;
            font-size: 20px;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: 0.1s;
            border: 1px solid #ff8c8c;
            box-shadow: 0 0 10px #ff3b3b55;
        }
        .image-card .remove-btn:hover {
            background: #cc3f3fdd;
            color: white;
            transform: scale(1.05);
        }
        .empty-message {
            grid-column: 1 / -1;
            text-align: center;
            padding: 40px 20px;
            color: #7f7fab;
            background: #0e0e28;
            border-radius: 40px;
            border: 1px dashed #48488a;
            font-size: 1.1rem;
        }
        .footer-actions {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            justify-content: space-between;
            margin-top: 16px;
            gap: 14px;
        }
        .download-all-btn {
            background: #1d9e5c;
            border: 1px solid #7dffb0;
            box-shadow: 0 6px 0 #0e3d25;
        }
        .download-all-btn:hover {
            background: #28c573;
        }
        .note {
            color: #a89fd6;
            font-size: 0.85rem;
            border-left: 3px solid #6d5fc7;
            padding-left: 14px;
        }
        @media (max-width: 680px) {
            .card { padding: 18px; }
            h1 { font-size: 1.9rem; }
            .control-panel { border-radius: 32px; padding: 16px; }
            .slider-group { flex-wrap: wrap; padding: 6px 14px; }
            input[type="range"] { width: 110px; }
        }
    </style>
</head>
<body>
    <div class="card">
        <h1>
            🌟 霓虹光效
            <small>批量·发光引擎</small>
        </h1>
        <div class="control-panel">
            <div class="file-area">
                <label for="fileInput" class="file-label">📁 选择图片</label>
                <span class="badge-count" id="imageCount">0 张</span>
                <span style="color:#8f86c9; font-size:0.9rem;">拖拽或点击</span>
            </div>
            <div class="slider-group">
                <label>💡 强度 <span class="value-badge" id="intensityValue">8</span></label>
                <input type="range" id="intensitySlider" min="1" max="25" value="8" step="0.5">
            </div>
            <button class="action-btn secondary" id="clearBtn">🗑️ 清空</button>
        </div>
        <!-- 图片网格 -->
        <div class="gallery" id="galleryContainer">
            <div class="empty-message">✨ 上传图片,霓虹觉醒 ✨</div>
        </div>
        <div class="footer-actions">
            <button class="action-btn primary" id="downloadAllBtn" disabled>⬇️ 下载全部 (霓虹效果)</button>
            <span class="note">⚡ 批量应用发光 · 点击图片可单独下载</span>
        </div>
    </div>
    <script>
        (function(){
            // ---------- 状态 ----------
            const imageFiles = [];          // 存储原始 File 对象
            let currentIntensity = 8;       // 默认
            // DOM 引用
            const fileInput = document.getElementById('fileInput');
            const gallery = document.getElementById('galleryContainer');
            const imageCountSpan = document.getElementById('imageCount');
            const intensitySlider = document.getElementById('intensitySlider');
            const intensityValue = document.getElementById('intensityValue');
            const clearBtn = document.getElementById('clearBtn');
            const downloadAllBtn = document.getElementById('downloadAllBtn');
            // ---------- 核心:渲染所有图片 (带霓虹) ----------
            function renderGallery() {
                // 清空网格,保留占位逻辑
                gallery.innerHTML = '';
                if (imageFiles.length === 0) {
                    gallery.innerHTML = `<div class="empty-message">✨ 上传图片,霓虹觉醒 ✨</div>`;
                    imageCountSpan.textContent = `0 张`;
                    downloadAllBtn.disabled = true;
                    return;
                }
                imageCountSpan.textContent = `${imageFiles.length} 张`;
                downloadAllBtn.disabled = false;
                // 遍历 File 生成卡片
                imageFiles.forEach((file, index) => {
                    const card = document.createElement('div');
                    card.className = 'image-card';
                    card.dataset.index = index;
                    const img = document.createElement('img');
                    // 用 objectURL 显示原图 (霓虹效果通过 CSS filter 实现)
                    const url = URL.createObjectURL(file);
                    img.src = url;
                    img.alt = file.name || `图片${index+1}`;
                    // 应用霓虹发光滤镜 —— 核心效果
                    applyNeonFilter(img, currentIntensity);
                    // 删除按钮
                    const removeBtn = document.createElement('button');
                    removeBtn.className = 'remove-btn';
                    removeBtn.innerHTML = '✕';
                    removeBtn.setAttribute('aria-label', '移除图片');
                    removeBtn.addEventListener('click', (e) => {
                        e.stopPropagation();
                        removeImage(index);
                    });
                    // 点击卡片下载单张 (霓虹效果)
                    card.addEventListener('click', (e) => {
                        // 如果点到删除按钮不触发下载
                        if (e.target.closest('.remove-btn')) return;
                        downloadSingleImage(index);
                    });
                    card.style.cursor = 'pointer';
                    card.appendChild(img);
                    card.appendChild(removeBtn);
                    gallery.appendChild(card);
                });
                // 释放之前的objectURL?为了防止内存堆积,但每次渲染重新生成,之前的URL会丢失,保留轻量策略
                // 更好:在render前释放旧URL,但难以追踪,我们使用一次性URL+自动回收,注意:当移除图片时需手动revoke
                // 简单处理:每次渲染后旧的objectURL没有引用会被GC,但可能延迟,我们保存URL数组以便清理?不用太担心。
                // 采用在 remove 时 revoke
            }
            // ---------- 霓虹滤镜 ----------
            function applyNeonFilter(imgElement, intensity) {
                // 强度映射:1~25 → 模糊 1~18px,亮度微调,对比度略增强,并增加彩色发光感
                const blur = Math.min(18, Math.max(1, intensity * 0.75));
                const brightness = 1 + intensity * 0.02;      // 1.0 ~ 1.5
                const contrast = 1 + intensity * 0.015;       // 1.0 ~ 1.375
                const saturate = 1.2 + intensity * 0.04;      // 1.2 ~ 2.2
                // 关键:drop-shadow 模拟霓虹光晕 (多色阴影叠加)
                // 用多层阴影制造彩色霓虹感: 洋红/青/黄
                const shadowColor1 = `rgba(255, 70, 230, ${0.4 + intensity * 0.02})`;
                const shadowColor2 = `rgba(70, 200, 255, ${0.3 + intensity * 0.015})`;
                const shadowColor3 = `rgba(255, 220, 50, ${0.15 + intensity * 0.01})`;
                const shadowSize = 8 + intensity * 0.9;
                // 使用 filter 属性融合
                img.style.filter = `
                    brightness(${brightness})
                    contrast(${contrast})
                    saturate(${saturate})
                    drop-shadow(0 0 ${shadowSize}px ${shadowColor1})
                    drop-shadow(0 0 ${shadowSize * 0.7}px ${shadowColor2})
                    drop-shadow(0 0 ${shadowSize * 0.4}px ${shadowColor3})
                `;
            }
            // ---------- 更新所有卡片霓虹 (滑块调整) ----------
            function updateAllNeonFilters() {
                const images = gallery.querySelectorAll('.image-card img');
                images.forEach(img => {
                    applyNeonFilter(img, currentIntensity);
                });
            }
            // ---------- 移除图片 ----------
            function removeImage(index) {
                if (index < 0 || index >= imageFiles.length) return;
                // 如果有 objectURL 需要释放 (虽然浏览器会GC,但主动释放更好)
                const cards = gallery.querySelectorAll('.image-card');
                if (cards[index]) {
                    const img = cards[index].querySelector('img');
                    if (img && img.src && img.src.startsWith('blob:')) {
                        URL.revokeObjectURL(img.src);
                    }
                }
                imageFiles.splice(index, 1);
                renderGallery();  // 重新渲染
            }
            // ---------- 清空全部 ----------
            function clearAllImages() {
                // 释放所有 blob url
                const images = gallery.querySelectorAll('img');
                images.forEach(img => {
                    if (img.src && img.src.startsWith('blob:')) {
                        URL.revokeObjectURL(img.src);
                    }
                });
                imageFiles.length = 0;
                renderGallery();
            }
            // ---------- 添加文件 ----------
            function addFiles(files) {
                let added = 0;
                for (const file of files) {
                    if (file.type && file.type.startsWith('image/')) {
                        imageFiles.push(file);
                        added++;
                    }
                }
                if (added > 0) {
                    renderGallery();
                } else {
                    alert('未检测到有效图片文件 (jpg, png, webp, gif 等)');
                }
            }
            // ---------- 下载单张 (霓虹效果) ----------
            function downloadSingleImage(index) {
                if (index < 0 || index >= imageFiles.length) return;
                const file = imageFiles[index];
                // 利用 Canvas 绘制原图 + 应用同款霓虹滤镜 (截取)
                const img = new Image();
                const objectURL = URL.createObjectURL(file);
                img.onload = function() {
                    // 创建 canvas
                    const canvas = document.createElement('canvas');
                    canvas.width = img.naturalWidth;
                    canvas.height = img.naturalHeight;
                    const ctx = canvas.getContext('2d');
                    // 绘制原图
                    ctx.drawImage(img, 0, 0);
                    // 应用 CSS 滤镜模拟? 但 canvas 不支持 drop-shadow 直接绘制。
                    // 但为了保持霓虹效果,我们采用裁剪 + 全局复合 + 模拟简单发光 (drawImage + 阴影api)
                    // 更靠谱:用 canvas filter 属性 (支持 drop-shadow 和 其他)
                    ctx.filter = `
                        brightness(${1 + currentIntensity * 0.02})
                        contrast(${1 + currentIntensity * 0.015})
                        saturate(${1.2 + currentIntensity * 0.04})
                        drop-shadow(0 0 ${8 + currentIntensity * 0.9}px rgba(255, 70, 230, ${0.4 + currentIntensity * 0.02}))
                        drop-shadow(0 0 ${(8 + currentIntensity * 0.9) * 0.7}px rgba(70, 200, 255, ${0.3 + currentIntensity * 0.015}))
                        drop-shadow(0 0 ${(8 + currentIntensity * 0.9) * 0.4}px rgba(255, 220, 50, ${0.15 + currentIntensity * 0.01}))
                    `;
                    // 重新绘制原图以应用滤镜 (在同一个canvas上)
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    ctx.drawImage(img, 0, 0);
                    // 导出
                    canvas.toBlob((blob) => {
                        if (!blob) return;
                        const link = document.createElement('a');
                        link.href = URL.createObjectURL(blob);
                        const ext = file.name.split('.').pop() || 'png';
                        link.download = `neon_${file.name.replace(/\.[^.]+$/, '')}.${ext}`;
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                        URL.revokeObjectURL(link.href);
                        // 释放 img 的 objectURL
                        URL.revokeObjectURL(objectURL);
                    }, file.type || 'image/png');
                };
                img.onerror = function() {
                    URL.revokeObjectURL(objectURL);
                    alert('图片加载失败,无法下载');
                };
                img.src = objectURL;
            }
            // ---------- 下载全部 (霓虹效果) ----------
            function downloadAllImages() {
                if (imageFiles.length === 0) return;
                // 逐个下载,简单触发,为避免浏览器拦截,使用间隔
                imageFiles.forEach((_, idx) => {
                    setTimeout(() => {
                        downloadSingleImage(idx);
                    }, idx * 300);  // 延时防止弹窗拦截
                });
            }
            // ---------- 事件绑定 ----------
            // 文件选择
            fileInput.addEventListener('change', function(e) {
                const files = Array.from(e.target.files);
                if (files.length) {
                    addFiles(files);
                }
                this.value = ''; // 允许重复选择相同文件
            });
            // 拖拽上传 (全局拖放)
            let dragCounter = 0;
            const cardElement = document.querySelector('.card');
            cardElement.addEventListener('dragenter', (e) => {
                e.preventDefault();
                e.stopPropagation();
                dragCounter++;
                cardElement.style.boxShadow = '0 0 0 3px #b38eff, 0 20px 40px rgba(0,0,0,0.8)';
            });
            cardElement.addEventListener('dragover', (e) => {
                e.preventDefault();
                e.stopPropagation();
            });
            cardElement.addEventListener('dragleave', (e) => {
                e.preventDefault();
                e.stopPropagation();
                dragCounter--;
                if (dragCounter === 0) {
                    cardElement.style.boxShadow = '';
                }
            });
            cardElement.addEventListener('drop', (e) => {
                e.preventDefault();
                e.stopPropagation();
                dragCounter = 0;
                cardElement.style.boxShadow = '';
                const files = Array.from(e.dataTransfer.files);
                if (files.length) {
                    addFiles(files);
                }
            });
            // 滑块调整
            intensitySlider.addEventListener('input', function() {
                currentIntensity = parseFloat(this.value);
                intensityValue.textContent = currentIntensity;
                // 更新现有卡片
                updateAllNeonFilters();
            });
            // 清空
            clearBtn.addEventListener('click', clearAllImages);
            // 下载全部
            downloadAllBtn.addEventListener('click', downloadAllImages);
            // 如果点击空白区域或误触,额外保护?不需要
            // 初始化
            renderGallery();
            intensityValue.textContent = currentIntensity;
            // 全局暴露(可选)
        })();
    </script>
</body>
</html>

霓虹光效与批量操作

您可以通过简单的步骤,为多张图片快速添加统一的霓虹发光效果。

图片批量霓虹工具发光效果-第1张图片-电脑手机工具软件下载 - 免费实用工具合集 | 联启科技

  • 批量处理与实时预览:您可以一次性上传多张图片,所有图片会以网格形式展示,通过调整“强度”滑块,所有图片的霓虹发光效果会实时同步变化,方便您找到最佳效果。
  • 灵活的下载方式:每张图片卡片都支持点击单独下载其霓虹效果版本,您也可以使用底部的“下载全部”按钮,一次性保存所有处理后的图片。
  • 直观的图片管理:每张图片右上角都配有移除按钮,方便您从批次中剔除不需要的图片。“清空”按钮则可以一键重置整个图片列表。

标签: 批量处理

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