logo
GitHub

使用 Vue 和 DaisyUI 构建图片尺寸转换组件

在本教程中,我们将使用 Vue 3 和 DaisyUI 创建一个实用的图片尺寸转换组件。这个组件可以让用户上传图片,并自动转换成多种常用尺寸,非常适合需要准备不同尺寸图片的场景。

在线演示

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

功能特点

  • 支持拖拽上传图片
  • 预览原始图片
  • 转换为多种预设尺寸
  • 支持下载转换后的图片
  • 优雅的用户界面

前置准备

首先确保你的项目已经安装了必要的依赖:

Terminal window
npm install vue@3
npm install daisyui
npm install tailwindcss

组件代码

创建一个新的组件文件 ImageResizer.vue

<template>
<div class="container mx-auto p-4">
<!-- 上传区域 -->
<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>拖拽图片到这里或点击上传</p>
</div>
<img
v-else
:src="selectedImage"
class="max-w-md mx-auto rounded-lg shadow"
/>
</div>
<!-- 预设尺寸选项 -->
<div v-if="selectedImage" class="mt-8">
<h3 class="text-lg font-semibold mb-4">选择目标尺寸:</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>
<!-- 转换后的图片展示 -->
<div v-if="resizedImages.length" class="mt-8">
<h3 class="text-lg font-semibold mb-4">转换结果:</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)"
>
下载
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const fileInput = ref(null)
const selectedImage = ref(null)
const resizedImages = ref([])
// 预设尺寸
const presetSizes = [
{ name: '社交媒体封面', width: 1200, height: 630 },
{ name: '微信头像', width: 132, height: 132 },
{ name: 'Instagram方形', width: 1080, height: 1080 },
{ name: '手机壁纸', width: 1080, height: 1920 },
]
// 触发文件选择
const triggerFileInput = () => {
fileInput.value.click()
}
// 处理文件选择
const handleFileSelect = (event) => {
const file = event.target.files[0]
if (file) {
loadImage(file)
}
}
// 处理拖拽上传
const handleDrop = (event) => {
const file = event.dataTransfer.files[0]
if (file && file.type.startsWith('image/')) {
loadImage(file)
}
}
// 加载图片
const loadImage = (file) => {
const reader = new FileReader()
reader.onload = (e) => {
selectedImage.value = e.target.result
resizedImages.value = [] // 清空之前的结果
}
reader.readAsDataURL(file)
}
// 调整图片尺寸
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')
// 使用白色背景
ctx.fillStyle = '#FFFFFF'
ctx.fillRect(0, 0, canvas.width, canvas.height)
// 计算缩放和位置以保持宽高比
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
})
}
}
// 下载图片
const downloadImage = (dataUrl, width, height) => {
const link = document.createElement('a')
link.download = `resized-${width}x${height}.jpg`
link.href = dataUrl
link.click()
}
</script>

使用说明

  1. 上传图片

    • 点击上传区域选择图片文件
    • 或直接将图片拖拽到上传区域
  2. 选择目标尺寸

    • 上传图片后,可以看到预设的尺寸选项
    • 点击需要的尺寸按钮进行转换
  3. 查看和下载

    • 转换后的图片会显示在下方
    • 每个转换结果都有预览和下载按钮

关键实现细节

1. 图片上传处理

组件支持两种上传方式:点击选择和拖拽上传。使用 FileReader API 读取图片文件:

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

2. 图片尺寸转换

使用 Canvas API 进行图片缩放,保持原始图片的宽高比:

const resizeImage = (targetWidth, targetHeight) => {
const img = new Image()
img.src = selectedImage.value
img.onload = () => {
const canvas = document.createElement('canvas')
// ... 缩放逻辑 ...
}
}

3. 保持宽高比

为了在调整尺寸时保持图片的宽高比,我们计算适当的缩放比例:

const scale = Math.min(
targetWidth / img.width,
targetHeight / img.height
)

样式优化

组件使用 DaisyUI 和 Tailwind CSS 实现了美观的界面:

  • 使用 card 组件展示转换结果
  • 响应式布局适应不同屏幕尺寸
  • 优雅的拖拽上传区域
  • 清晰的按钮和交互效果

进阶优化建议

  1. 添加加载状态

    • 在处理大图片时显示加载提示
    • 使用进度条显示转换进度
  2. 自定义尺寸

    • 添加输入框允许用户指定自定义尺寸
    • 保存常用尺寸配置
  3. 图片优化

    • 添加图片质量控制选项
    • 支持多种输出格式(PNG、WebP等)
  4. 批量处理

    • 支持多图片同时上传和处理
    • 提供批量下载功能

结论

这个图片尺寸转换组件展示了如何使用 Vue 3 和 DaisyUI 创建实用的工具组件。通过组合现代的 Web API 和优雅的 UI 框架,我们可以构建出既实用又美观的功能组件。

你可以根据实际需求进一步扩展这个组件,添加更多功能或优化用户体验。希望这个教程对你有所帮助!