导航菜单

Building an Image Resizer Component with Vue and DaisyUI

In this tutorial, we’ll create a practical image resizer component using Vue 3 and DaisyUI. This component allows users to upload images and automatically convert them into various common sizes, perfect for scenarios where different image dimensions are needed.

Live Demo

拖拽图片到这里或点击上传

Features

  • Drag and drop image upload
  • Original image preview
  • Convert to multiple preset sizes
  • Download converted images
  • Elegant user interface

Prerequisites

First, ensure your project has the necessary dependencies installed:

npm install vue@3
npm install daisyui
npm install tailwindcss

Component Code

Create a new component file ImageResizer.vue:

<template>
    <div class="container mx-auto p-4">
        <!-- Upload Area -->
        <div
            class="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center"
            @drop.prevent="handleDrop"
            @dragover.prevent
            @click="triggerFileInput"
        >
            <input
                type="file"
                ref="fileInput"
                class="hidden"
                accept="image/*"
                @change="handleFileSelect"
            />
            <div v-if="!selectedImage" class="text-gray-500">
                <i class="fas fa-cloud-upload-alt text-3xl mb-2"></i>
                <p>Drag and drop an image here or click to upload</p>
            </div>
            <img v-else :src="selectedImage" class="max-w-md mx-auto rounded-lg shadow" />
        </div>

        <!-- Preset Size Options -->
        <div v-if="selectedImage" class="mt-8">
            <h3 class="text-lg font-semibold mb-4">Select Target Size:</h3>
            <div class="grid grid-cols-2 md:grid-cols-3 gap-4">
                <button
                    v-for="size in presetSizes"
                    :key="size.name"
                    class="btn btn-primary"
                    @click="resizeImage(size.width, size.height)"
                >
                    {{ size.name }} ({{ size.width }}x{{ size.height }})
                </button>
            </div>
        </div>

        <!-- Converted Images Display -->
        <div v-if="resizedImages.length" class="mt-8">
            <h3 class="text-lg font-semibold mb-4">Conversion Results:</h3>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                <div
                    v-for="(image, index) in resizedImages"
                    :key="index"
                    class="card bg-base-100 shadow-xl"
                >
                    <figure class="px-4 pt-4">
                        <img :src="image.url" class="rounded-xl" />
                    </figure>
                    <div class="card-body">
                        <h2 class="card-title">{{ image.width }}x{{ image.height }}</h2>
                        <div class="card-actions justify-end">
                            <button
                                class="btn btn-primary"
                                @click="downloadImage(image.url, image.width, image.height)"
                            >
                                Download
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue';

import ReferenceAnswer from '@/components/common/ReferenceAnswer.vue';

const fileInput = ref(null);
const selectedImage = ref(null);
const resizedImages = ref([]);

// Preset sizes
const presetSizes = [
    { name: 'Social Media Cover', width: 1200, height: 630 },
    { name: 'WeChat Avatar', width: 132, height: 132 },
    { name: 'Instagram Square', width: 1080, height: 1080 },
    { name: 'Mobile Wallpaper', width: 1080, height: 1920 },
];

// Trigger file selection
const triggerFileInput = () => {
    fileInput.value.click();
};

// Handle file selection
const handleFileSelect = event => {
    const file = event.target.files[0];
    if (file) {
        loadImage(file);
    }
};

// Handle drag and drop
const handleDrop = event => {
    const file = event.dataTransfer.files[0];
    if (file && file.type.startsWith('image/')) {
        loadImage(file);
    }
};

// Load image
const loadImage = file => {
    const reader = new FileReader();
    reader.onload = e => {
        selectedImage.value = e.target.result;
        resizedImages.value = []; // Clear previous results
    };
    reader.readAsDataURL(file);
};

// Resize image
const resizeImage = (targetWidth, targetHeight) => {
    const img = new Image();
    img.src = selectedImage.value;
    img.onload = () => {
        const canvas = document.createElement('canvas');
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        const ctx = canvas.getContext('2d');

        // Use white background
        ctx.fillStyle = '#FFFFFF';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Calculate scale and position to maintain aspect ratio
        const scale = Math.min(targetWidth / img.width, targetHeight / img.height);
        const x = (targetWidth - img.width * scale) / 2;
        const y = (targetHeight - img.height * scale) / 2;

        ctx.drawImage(img, x, y, img.width * scale, img.height * scale);

        const resizedUrl = canvas.toDataURL('image/jpeg', 0.9);
        resizedImages.value.push({
            url: resizedUrl,
            width: targetWidth,
            height: targetHeight,
        });
    };
};

// Download image
const downloadImage = (dataUrl, width, height) => {
    const link = document.createElement('a');
    link.download = `resized-${width}x${height}.jpg`;
    link.href = dataUrl;
    link.click();
};
</script>

Usage Instructions

  1. Upload Image:

    • Click the upload area to select an image file
    • Or drag and drop an image directly into the upload area
  2. Select Target Size:

    • After uploading an image, you’ll see preset size options
    • Click the desired size button to convert
  3. View and Download:

    • Converted images will appear below
    • Each conversion result has preview and download buttons

Key Implementation Details

1. Image Upload Handling

The component supports two upload methods: click-to-select and drag-and-drop. It uses the FileReader API to read image files:

const loadImage = (file) => {
  const reader = new FileReader()
  reader.onload = (e) => {
    selectedImage.value = e.target.result
    resizedImages.value = []
  }
  reader.readAsDataURL(file)

搜索