搜索结果

×

搜索结果将在这里显示。

💫 酷咔图片转ICO工具

主要新增功能:

尺寸选择网格:提供了9个常用ICO尺寸选项(16×16 到 512×512)
自定义尺寸输入:可以输入任意宽度和高度(1-1024像素)
预设尺寸快捷按钮:快速设置常见尺寸
实时显示已选尺寸:在顶部显示当前选择的尺寸列表
尺寸管理:可以随时添加或删除尺寸
尺寸选择反馈:选中的尺寸有视觉高亮效果

代码分享


<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>酷咔图片转ICO工具 - 支持自定义尺寸</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            color: #333;
        }

        .container {
            max-width: 1000px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            text-align: center;
            margin-bottom: 40px;
            color: white;
        }

        h1 {
            font-size: 2.8rem;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
        }

        .subtitle {
            font-size: 1.2rem;
            opacity: 0.9;
        }

        .app-card {
            background: white;
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
        }

        .upload-area {
            border: 3px dashed #667eea;
            border-radius: 15px;
            padding: 60px 20px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            background: #f8f9ff;
            margin-bottom: 30px;
        }

        .upload-area:hover {
            border-color: #764ba2;
            background: #f0f3ff;
        }

        .upload-area.dragover {
            border-color: #764ba2;
            background: #e8ebff;
        }

        .upload-icon {
            font-size: 4rem;
            color: #667eea;
            margin-bottom: 20px;
        }

        .upload-text {
            font-size: 1.3rem;
            margin-bottom: 10px;
            color: #555;
        }

        .upload-hint {
            color: #888;
            font-size: 0.9rem;
        }

        .settings-section {
            background: #f8f9ff;
            border-radius: 15px;
            padding: 25px;
            margin-bottom: 30px;
            display: none;
        }

        .settings-title {
            font-size: 1.2rem;
            margin-bottom: 20px;
            color: #555;
            font-weight: 600;
        }

        .size-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
            gap: 15px;
            margin-bottom: 20px;
        }

        .size-option {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 12px;
            background: white;
            border-radius: 10px;
            cursor: pointer;
            transition: all 0.3s ease;
            border: 2px solid #e0e0e0;
        }

        .size-option:hover {
            border-color: #667eea;
            transform: translateY(-2px);
        }

        .size-option.selected {
            border-color: #764ba2;
            background: #f0e6ff;
        }

        .size-checkbox {
            width: 20px;
            height: 20px;
            border-radius: 4px;
            border: 2px solid #667eea;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .size-checkbox.checked::after {
            content: '✓';
            color: #764ba2;
            font-weight: bold;
        }

        .size-label {
            font-weight: 500;
            color: #555;
        }

        .custom-size {
            margin-top: 20px;
        }

        .custom-size-inputs {
            display: flex;
            gap: 15px;
            align-items: center;
            flex-wrap: wrap;
        }

        .size-input-group {
            display: flex;
            flex-direction: column;
            gap: 5px;
        }

        .size-input-group label {
            font-size: 0.9rem;
            color: #666;
        }

        .size-input {
            padding: 8px 12px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-size: 1rem;
            width: 100px;
        }

        .size-input:focus {
            outline: none;
            border-color: #667eea;
        }

        .add-custom-btn {
            background: #667eea;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 8px;
            cursor: pointer;
            font-weight: 500;
            transition: background 0.3s ease;
        }

        .add-custom-btn:hover {
            background: #764ba2;
        }

        .preset-sizes {
            display: flex;
            gap: 10px;
            margin-top: 10px;
            flex-wrap: wrap;
        }

        .preset-btn {
            padding: 6px 12px;
            background: #f0f0f0;
            border: 1px solid #ddd;
            border-radius: 6px;
            cursor: pointer;
            font-size: 0.9rem;
        }

        .preset-btn:hover {
            background: #e0e0e0;
        }

        .controls {
            display: flex;
            gap: 15px;
            justify-content: center;
            margin-top: 20px;
        }

        .btn {
            padding: 15px 40px;
            border: none;
            border-radius: 12px;
            font-size: 1.1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 10px 20px rgba(102, 126, 234, 0.4);
        }

        .btn-primary:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }

        .btn-secondary {
            background: #f0f0f0;
            color: #666;
        }

        .btn-secondary:hover {
            background: #e0e0e0;
        }

        .progress-container {
            margin-top: 20px;
            text-align: center;
            display: none;
        }

        .progress-bar {
            height: 8px;
            background: #e0e0e0;
            border-radius: 4px;
            overflow: hidden;
            margin-bottom: 10px;
        }

        .progress-fill {
            height: 100%;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            width: 0%;
            transition: width 0.3s ease;
        }

        .progress-text {
            text-align: center;
            color: #666;
            font-size: 0.9rem;
        }

        .status-message {
            padding: 15px;
            border-radius: 10px;
            margin: 20px 0;
            text-align: center;
            font-weight: 500;
        }

        .status-success {
            background: #e8f5e9;
            color: #2e7d32;
            border: 1px solid #c8e6c9;
        }

        .status-error {
            background: #ffebee;
            color: #c62828;
            border: 1px solid #ffcdd2;
        }

        .download-link {
            display: inline-block;
            padding: 10px 20px;
            background: #4CAF50;
            color: white;
            text-decoration: none;
            border-radius: 5px;
            margin: 10px 5px;
            transition: background 0.3s ease;
        }

        .download-link:hover {
            background: #388e3c;
        }

        .download-links {
            margin-top: 20px;
            text-align: center;
        }

        .error-details {
            background: #f5f5f5;
            border-radius: 5px;
            padding: 10px;
            margin-top: 10px;
            font-family: monospace;
            font-size: 0.9rem;
            color: #666;
            text-align: left;
        }

        .current-sizes {
            margin-top: 20px;
            padding: 15px;
            background: #f8f9ff;
            border-radius: 10px;
        }

        .current-sizes-title {
            font-weight: 600;
            margin-bottom: 10px;
            color: #555;
        }

        .size-badge {
            display: inline-block;
            padding: 4px 12px;
            background: #667eea;
            color: white;
            border-radius: 20px;
            margin: 5px;
            font-size: 0.9rem;
        }

        .remove-size {
            background: #ff6b6b;
            color: white;
            border: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            margin-left: 5px;
            font-size: 12px;
        }

        @media (max-width: 768px) {
            .container {
                padding: 10px;
            }

            .app-card {
                padding: 20px;
            }

            .controls {
                flex-direction: column;
            }

            .btn {
                width: 100%;
            }

            .size-grid {
                grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
            }

            .custom-size-inputs {
                flex-direction: column;
                align-items: stretch;
            }

            .size-input {
                width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>酷咔图片转ICO工具</h1>
            <p class="subtitle">支持自定义尺寸设置</p>
        </header>

        <div class="app-card">
            <div class="upload-area" id="uploadArea">
                <div class="upload-icon">📁</div>
                <div class="upload-text">点击或拖放图片文件到这里</div>
                <div class="upload-hint">支持PNG、JPG、JPEG格式,单文件最大5MB</div>
                <input type="file" id="fileInput" accept=".png,.jpg,.jpeg" style="display: none;">
            </div>

            <div class="settings-section" id="settingsSection">
                <div class="settings-title">选择ICO尺寸</div>

                <div class="current-sizes" id="currentSizes" style="display: none;">
                    <div class="current-sizes-title">已选择尺寸:</div>
                    <div id="selectedSizesList"></div>
                </div>

                <div class="size-grid" id="sizeGrid">
                    <!-- 尺寸选项会由JS动态生成 -->
                </div>

                <div class="custom-size">
                    <div class="settings-title">自定义尺寸</div>
                    <div class="custom-size-inputs">
                        <div class="size-input-group">
                            <label for="customWidth">宽度 (px)</label>
                            <input type="number" id="customWidth" class="size-input" min="1" max="512" value="64" placeholder="宽度">
                        </div>
                        <div class="size-input-group">
                            <label for="customHeight">高度 (px)</label>
                            <input type="number" id="customHeight" class="size-input" min="1" max="512" value="64" placeholder="高度">
                        </div>
                        <button class="add-custom-btn" id="addCustomBtn">添加自定义尺寸</button>
                    </div>

                    <div class="preset-sizes">
                        <button class="preset-btn" onclick="setPresetSize(16, 16)">16×16</button>
                        <button class="preset-btn" onclick="setPresetSize(32, 32)">32×32</button>
                        <button class="preset-btn" onclick="setPresetSize(48, 48)">48×48</button>
                        <button class="preset-btn" onclick="setPresetSize(64, 64)">64×64</button>
                        <button class="preset-btn" onclick="setPresetSize(128, 128)">128×128</button>
                        <button class="preset-btn" onclick="setPresetSize(256, 256)">256×256</button>
                        <button class="preset-btn" onclick="setPresetSize(512, 512)">512×512</button>
                    </div>
                </div>
            </div>

            <div class="controls">
                <button class="btn btn-secondary" id="resetBtn" style="display: none;">
                    重置
                </button>
                <button class="btn btn-primary" id="convertBtn" disabled>
                    转换为ICO
                </button>
            </div>

            <div class="progress-container" id="progressContainer">
                <div class="progress-bar">
                    <div class="progress-fill" id="progressFill"></div>
                </div>
                <div class="progress-text" id="progressText">准备转换...</div>
            </div>

            <div id="statusArea"></div>

            <div id="downloadArea" style="display: none;"></div>
        </div>
    </div>

    <script>
        class ICOSizeConverter {
            constructor() {
                this.currentFile = null;
                this.isProcessing = false;
                this.selectedSizes = new Set(['16x16', '32x32', '48x48', '256x256']);
                this.availableSizes = [
                    {width: 16, height: 16, label: '16×16'},
                    {width: 24, height: 24, label: '24×24'},
                    {width: 32, height: 32, label: '32×32'},
                    {width: 48, height: 48, label: '48×48'},
                    {width: 64, height: 64, label: '64×64'},
                    {width: 96, height: 96, label: '96×96'},
                    {width: 128, height: 128, label: '128×128'},
                    {width: 256, height: 256, label: '256×256'},
                    {width: 512, height: 512, label: '512×512'}
                ];
                this.init();
            }

            init() {
                this.setupEventListeners();
                this.generateSizeOptions();
                this.updateSelectedSizesDisplay();
            }

            setupEventListeners() {
                const uploadArea = document.getElementById('uploadArea');
                const fileInput = document.getElementById('fileInput');
                const convertBtn = document.getElementById('convertBtn');
                const resetBtn = document.getElementById('resetBtn');
                const addCustomBtn = document.getElementById('addCustomBtn');
                const sizeGrid = document.getElementById('sizeGrid');

                // 点击上传区域
                uploadArea.addEventListener('click', () => fileInput.click());

                // 文件选择变化
                fileInput.addEventListener('change', (e) => this.handleFileSelect(e.target.files));

                // 拖放功能
                uploadArea.addEventListener('dragover', (e) => {
                    e.preventDefault();
                    uploadArea.classList.add('dragover');
                });

                uploadArea.addEventListener('dragleave', () => {
                    uploadArea.classList.remove('dragover');
                });

                uploadArea.addEventListener('drop', (e) => {
                    e.preventDefault();
                    uploadArea.classList.remove('dragover');
                    this.handleFileSelect(e.dataTransfer.files);
                });

                // 转换按钮
                convertBtn.addEventListener('click', () => this.convertToICO());

                // 重置按钮
                resetBtn.addEventListener('click', () => this.reset());

                // 添加自定义尺寸按钮
                addCustomBtn.addEventListener('click', () => this.addCustomSize());

                // 尺寸选择
                sizeGrid.addEventListener('click', (e) => {
                    const sizeOption = e.target.closest('.size-option');
                    if (sizeOption) {
                        const width = parseInt(sizeOption.dataset.width);
                        const height = parseInt(sizeOption.dataset.height);
                        this.toggleSize(width, height);
                    }
                });
            }

            generateSizeOptions() {
                const sizeGrid = document.getElementById('sizeGrid');
                sizeGrid.innerHTML = '';

                this.availableSizes.forEach(size => {
                    const sizeKey = `${size.width}x${size.height}`;
                    const isSelected = this.selectedSizes.has(sizeKey);

                    const option = document.createElement('div');
                    option.className = `size-option ${isSelected ? 'selected' : ''}`;
                    option.dataset.width = size.width;
                    option.dataset.height = size.height;

                    option.innerHTML = `
                        <div class="size-checkbox ${isSelected ? 'checked' : ''}"></div>
                        <div class="size-label">${size.label}</div>
                    `;

                    sizeGrid.appendChild(option);
                });
            }

            toggleSize(width, height) {
                const sizeKey = `${width}x${height}`;

                if (this.selectedSizes.has(sizeKey)) {
                    this.selectedSizes.delete(sizeKey);
                } else {
                    this.selectedSizes.add(sizeKey);
                }

                this.generateSizeOptions();
                this.updateSelectedSizesDisplay();
                this.updateConvertButton();
            }

            addCustomSize() {
                const widthInput = document.getElementById('customWidth');
                const heightInput = document.getElementById('customHeight');

                const width = parseInt(widthInput.value);
                const height = parseInt(heightInput.value);

                if (!width || !height || width < 1 || height < 1 || width > 1024 || height > 1024) {
                    this.showError('请输入有效的尺寸(1-1024像素)');
                    return;
                }

                const sizeKey = `${width}x${height}`;

                // 检查是否已存在
                if (!this.selectedSizes.has(sizeKey)) {
                    this.selectedSizes.add(sizeKey);

                    // 添加到可选尺寸列表
                    const exists = this.availableSizes.some(s => s.width === width && s.height === height);
                    if (!exists) {
                        this.availableSizes.push({
                            width,
                            height,
                            label: `${width}×${height}`
                        });
                        this.availableSizes.sort((a, b) => a.width - b.width);
                    }

                    this.generateSizeOptions();
                    this.updateSelectedSizesDisplay();
                    this.updateConvertButton();

                    // 清空输入框
                    widthInput.value = '';
                    heightInput.value = '';
                }
            }

            removeSize(sizeKey) {
                this.selectedSizes.delete(sizeKey);
                this.generateSizeOptions();
                this.updateSelectedSizesDisplay();
                this.updateConvertButton();
            }

            updateSelectedSizesDisplay() {
                const currentSizes = document.getElementById('currentSizes');
                const selectedSizesList = document.getElementById('selectedSizesList');

                if (this.selectedSizes.size === 0) {
                    currentSizes.style.display = 'none';
                    return;
                }

                currentSizes.style.display = 'block';
                selectedSizesList.innerHTML = '';

                Array.from(this.selectedSizes).sort().forEach(sizeKey => {
                    const sizeBadge = document.createElement('span');
                    sizeBadge.className = 'size-badge';
                    sizeBadge.innerHTML = `
                        ${sizeKey}
                        <button class="remove-size" onclick="icoConverter.removeSize('${sizeKey}')">×</button>
                    `;
                    selectedSizesList.appendChild(sizeBadge);
                });
            }

            handleFileSelect(files) {
                if (files.length === 0) return;

                const file = files[0];

                // 文件大小检查
                if (file.size > 5 * 1024 * 1024) {
                    this.showError('文件大小不能超过5MB');
                    return;
                }

                // 文件类型检查
                if (!file.type.match('image.*')) {
                    this.showError('请选择图片文件(PNG、JPG、JPEG格式)');
                    return;
                }

                this.currentFile = file;
                document.getElementById('convertBtn').disabled = false;
                document.getElementById('resetBtn').style.display = 'inline-block';
                document.getElementById('settingsSection').style.display = 'block';

                this.showStatus(`已选择文件: ${file.name} (${this.formatFileSize(file.size)})`, 'success');
            }

            async convertToICO() {
                if (!this.currentFile || this.isProcessing) return;

                if (this.selectedSizes.size === 0) {
                    this.showError('请至少选择一个尺寸');
                    return;
                }

                this.isProcessing = true;
                const convertBtn = document.getElementById('convertBtn');
                const progressContainer = document.getElementById('progressContainer');
                const progressFill = document.getElementById('progressFill');
                const progressText = document.getElementById('progressText');

                // 显示进度条
                progressContainer.style.display = 'block';
                progressFill.style.width = '0%';
                convertBtn.disabled = true;

                try {
                    // 更新进度
                    progressText.textContent = '正在读取文件...';
                    progressFill.style.width = '10%';

                    // 读取图片文件
                    const img = await this.loadImage(this.currentFile);

                    // 更新进度
                    progressText.textContent = '正在处理图片...';
                    progressFill.style.width = '20%';

                    // 解析选择的尺寸
                    const sizes = Array.from(this.selectedSizes).map(sizeKey => {
                        const [width, height] = sizeKey.split('x').map(Number);
                        return { width, height };
                    });

                    // 创建不同尺寸的图片
                    const canvases = [];
                    const totalSizes = sizes.length;

                    for (let i = 0; i < totalSizes; i++) {
                        const size = sizes[i];
                        const progressPercent = 20 + (i / totalSizes) * 60;
                        progressText.textContent = `生成 ${size.width}x${size.height} 图标...`;
                        progressFill.style.width = `${progressPercent}%`;

                        const canvas = await this.resizeImageToCanvas(img, size.width, size.height);
                        canvases.push(canvas);

                        // 避免UI卡顿
                        await new Promise(resolve => setTimeout(resolve, 50));
                    }

                    // 更新进度
                    progressText.textContent = '生成ICO文件...';
                    progressFill.style.width = '90%';

                    // 生成ICO数据
                    const icoData = await this.createICOData(canvases, sizes);

                    // 更新进度
                    progressText.textContent = '转换完成!';
                    progressFill.style.width = '100%';

                    // 提供下载
                    const filename = this.currentFile.name.replace(/\.[^/.]+$/, "") + '.ico';
                    await this.downloadICOFile(icoData, filename);

                    this.showStatus(`转换成功!生成了${sizes.length}个尺寸的ICO文件。`, 'success');

                } catch (error) {
                    console.error('转换失败:', error);
                    this.showError(`转换失败: ${error.message}`, error);
                } finally {
                    this.isProcessing = false;

                    // 2秒后隐藏进度条
                    setTimeout(() => {
                        progressContainer.style.display = 'none';
                        convertBtn.disabled = false;
                    }, 2000);
                }
            }

            loadImage(file) {
                return new Promise((resolve, reject) => {
                    const img = new Image();
                    const reader = new FileReader();

                    reader.onload = (e) => {
                        img.src = e.target.result;
                        img.onload = () => resolve(img);
                        img.onerror = () => reject(new Error('图片加载失败'));
                    };

                    reader.onerror = () => reject(new Error('文件读取失败'));
                    reader.readAsDataURL(file);
                });
            }

            resizeImageToCanvas(img, width, height) {
                return new Promise((resolve) => {
                    const canvas = document.createElement('canvas');
                    canvas.width = width;
                    canvas.height = height;

                    const ctx = canvas.getContext('2d');

                    // 设置高质量缩放
                    ctx.imageSmoothingEnabled = true;
                    ctx.imageSmoothingQuality = 'high';

                    // 清空画布
                    ctx.clearRect(0, 0, width, height);

                    // 计算缩放比例
                    const scale = Math.min(width / img.width, height / img.height);
                    const scaledWidth = img.width * scale;
                    const scaledHeight = img.height * scale;
                    const x = (width - scaledWidth) / 2;
                    const y = (height - scaledHeight) / 2;

                    // 绘制图片
                    ctx.drawImage(img, x, y, scaledWidth, scaledHeight);

                    resolve(canvas);
                });
            }

            async createICOData(canvases, sizes) {
                const icoParts = [];

                // ICO文件头
                icoParts.push(new Uint8Array([0, 0, 1, 0])); // 保留字段和类型
                icoParts.push(new Uint8Array([canvases.length, 0])); // 图片数量

                let offset = 6 + (canvases.length * 16);

                const pngDatas = [];
                for (let i = 0; i < canvases.length; i++) {
                    const canvas = canvases[i];
                    const pngData = await this.canvasToPNG(canvas);
                    pngDatas.push(pngData);
                }

                // 生成目录项
                for (let i = 0; i < canvases.length; i++) {
                    const size = sizes[i];
                    const pngData = pngDatas[i];
                    const pngSize = pngData.length;

                    const directoryEntry = new Uint8Array(16);

                    // 宽度和高度
                    directoryEntry[0] = size.width >= 256 ? 0 : size.width;
                    directoryEntry[1] = size.height >= 256 ? 0 : size.height;

                    // 颜色数
                    directoryEntry[2] = 0;

                    // 保留字段
                    directoryEntry[3] = 0;

                    // 颜色平面
                    directoryEntry[4] = 0;
                    directoryEntry[5] = 0;

                    // 每像素位数
                    directoryEntry[6] = 32;
                    directoryEntry[7] = 0;

                    // PNG数据大小
                    directoryEntry[8] = pngSize & 0xFF;
                    directoryEntry[9] = (pngSize >> 8) & 0xFF;
                    directoryEntry[10] = (pngSize >> 16) & 0xFF;
                    directoryEntry[11] = (pngSize >> 24) & 0xFF;

                    // 数据偏移
                    directoryEntry[12] = offset & 0xFF;
                    directoryEntry[13] = (offset >> 8) & 0xFF;
                    directoryEntry[14] = (offset >> 16) & 0xFF;
                    directoryEntry[15] = (offset >> 24) & 0xFF;

                    icoParts.push(directoryEntry);
                    offset += pngSize;
                }

                // 添加PNG数据
                for (const pngData of pngDatas) {
                    icoParts.push(pngData);
                }

                // 合并所有部分
                const totalSize = icoParts.reduce((sum, part) => sum + part.length, 0);
                const result = new Uint8Array(totalSize);
                let position = 0;

                for (const part of icoParts) {
                    result.set(part, position);
                    position += part.length;
                }

                return result.buffer;
            }

            canvasToPNG(canvas) {
                return new Promise((resolve) => {
                    canvas.toBlob((blob) => {
                        const reader = new FileReader();
                        reader.onload = () => {
                            resolve(new Uint8Array(reader.result));
                        };
                        reader.readAsArrayBuffer(blob);
                    }, 'image/png');
                });
            }

            downloadICOFile(data, filename) {
                return new Promise((resolve, reject) => {
                    try {
                        const blob = new Blob([data], { type: 'image/vnd.microsoft.icon' });
                        const url = URL.createObjectURL(blob);

                        const a = document.createElement('a');
                        a.href = url;
                        a.download = filename;

                        document.body.appendChild(a);
                        a.click();
                        document.body.removeChild(a);

                        setTimeout(() => URL.revokeObjectURL(url), 100);

                        resolve();
                    } catch (error) {
                        try {
                            const downloadArea = document.getElementById('downloadArea');
                            downloadArea.innerHTML = '';

                            const link = document.createElement('a');
                            link.href = URL.createObjectURL(new Blob([data], { type: 'image/vnd.microsoft.icon' }));
                            link.download = filename;
                            link.textContent = `点击下载 ${filename}`;
                            link.className = 'download-link';

                            downloadArea.appendChild(link);
                            downloadArea.style.display = 'block';

                            this.showStatus('请点击上方的链接下载文件', 'success');
                            resolve();
                        } catch (fallbackError) {
                            reject(fallbackError);
                        }
                    }
                });
            }

            reset() {
                this.currentFile = null;
                this.isProcessing = false;
                this.selectedSizes = new Set(['16x16', '32x32', '48x48', '256x256']);

                document.getElementById('fileInput').value = '';
                document.getElementById('convertBtn').disabled = true;
                document.getElementById('resetBtn').style.display = 'none';
                document.getElementById('progressContainer').style.display = 'none';
                document.getElementById('settingsSection').style.display = 'none';
                document.getElementById('statusArea').innerHTML = '';
                document.getElementById('downloadArea').innerHTML = '';
                document.getElementById('downloadArea').style.display = 'none';

                this.generateSizeOptions();
                this.updateSelectedSizesDisplay();
            }

            showStatus(message, type = 'success') {
                const statusArea = document.getElementById('statusArea');
                statusArea.innerHTML = `
                    <div class="status-message status-${type}">
                        ${message}
                    </div>
                `;
            }

            showError(message, error = null) {
                this.showStatus(message, 'error');

                if (error) {
                    const statusArea = document.getElementById('statusArea');
                    const errorDetails = document.createElement('div');
                    errorDetails.className = 'error-details';
                    errorDetails.textContent = `错误详情: ${error.message}`;
                    statusArea.appendChild(errorDetails);
                }
            }

            updateConvertButton() {
                const convertBtn = document.getElementById('convertBtn');
                convertBtn.disabled = !this.currentFile || this.selectedSizes.size === 0 || this.isProcessing;
            }

            formatFileSize(bytes) {
                if (bytes === 0) return '0 B';
                const k = 1024;
                const sizes = ['B', 'KB', 'MB', 'GB'];
                const i = Math.floor(Math.log(bytes) / Math.log(k));
                return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
            }
        }

        // 初始化转换器
        const icoConverter = new ICOSizeConverter();

        // 全局辅助函数
        function setPresetSize(width, height) {
            document.getElementById('customWidth').value = width;
            document.getElementById('customHeight').value = height;
        }
    </script>
</body>
</html>

演示效果

点击查看

阅读:46
发布时间:
请先 登录 再评论