mirror of
https://github.com/BewlyBewly/BewlyBewly.git
synced 2025-04-14 13:15:29 +00:00
feat: add image compression and resizing for wallpaper upload
This commit is contained in:
@@ -5,6 +5,7 @@ import Slider from '~/components/Slider.vue'
|
||||
import Tooltip from '~/components/Tooltip.vue'
|
||||
import { WALLPAPERS } from '~/constants/imgs'
|
||||
import { settings } from '~/logic'
|
||||
import { compressAndResizeImage } from '~/utils/main'
|
||||
|
||||
import SettingsItem from './SettingsItem.vue'
|
||||
import SettingsItemGroup from './SettingsItemGroup.vue'
|
||||
@@ -28,6 +29,14 @@ function changeWallpaperType(type: 'buildIn' | 'byUrl') {
|
||||
else {
|
||||
settings.value.searchPageWallpaperMode = type
|
||||
}
|
||||
|
||||
// Set the wallpaper to empty if it's a locally uploaded wallpaper to prevent the `QUOTA_BYTES quota exceeded` error
|
||||
if (type === 'byUrl') {
|
||||
if (settings.value.wallpaper.startsWith('data:image/'))
|
||||
settings.value.wallpaper = ''
|
||||
else if (settings.value.searchPageWallpaper.startsWith('data:image/'))
|
||||
settings.value.searchPageWallpaper = ''
|
||||
}
|
||||
}
|
||||
|
||||
function changeWallpaper(url: string) {
|
||||
@@ -59,16 +68,19 @@ function handleUploadWallpaper(e: Event) {
|
||||
const file = (e.target as HTMLInputElement)?.files?.[0]
|
||||
if (!file)
|
||||
return
|
||||
// img to base64 on browser
|
||||
fileToBase64(file).then((base64) => {
|
||||
// 使用base64字符串
|
||||
changeWallpaper(base64 as string)
|
||||
settings.value.customizeWallpaper = {
|
||||
name: file.name,
|
||||
url: base64 as string,
|
||||
}
|
||||
}).catch(() => {
|
||||
// 处理错误
|
||||
|
||||
compressAndResizeImage(file, 2560, 1440, 0.9, (compressedFile: File) => {
|
||||
// img to base64 on browser
|
||||
fileToBase64(compressedFile).then((base64) => {
|
||||
// 使用base64字符串
|
||||
changeWallpaper(base64 as string)
|
||||
settings.value.customizeWallpaper = {
|
||||
name: file.name,
|
||||
url: base64 as string,
|
||||
}
|
||||
}).catch(() => {
|
||||
// 处理错误
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -149,6 +161,7 @@ function handleRemoveCustomWallpaper() {
|
||||
pos="absolute top-4px right-4px" z-1 text="14px" flex="~ gap-1"
|
||||
>
|
||||
<button
|
||||
style="backdrop-filter: var(--bew-filter-glass-1);"
|
||||
bg="$bew-content-1" rounded-full w-28px h-28px
|
||||
grid place-items-center
|
||||
@click="handleUploadWallpaper"
|
||||
@@ -156,6 +169,7 @@ function handleRemoveCustomWallpaper() {
|
||||
<i i-mingcute:edit-2-line />
|
||||
</button>
|
||||
<button
|
||||
style="backdrop-filter: var(--bew-filter-glass-1);"
|
||||
bg="$bew-content-1" rounded-full w-28px h-28px
|
||||
grid place-items-center
|
||||
@click="handleRemoveCustomWallpaper"
|
||||
|
||||
@@ -113,3 +113,73 @@ export function isHomePage(): boolean {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses and resizes an image file.
|
||||
*
|
||||
* @param file - The image file to compress and resize.
|
||||
* @param maxWidth - The maximum width of the resized image.
|
||||
* @param maxHeight - The maximum height of the resized image.
|
||||
* @param quality - The quality of the compressed image (0-1).
|
||||
* @param callback - The callback function to execute with the compressed file.
|
||||
*/
|
||||
export function compressAndResizeImage(file: File, maxWidth: number, maxHeight: number, quality: number, callback: any) {
|
||||
// Create an Image object
|
||||
const img = new Image()
|
||||
|
||||
// Create a FileReader to read the file
|
||||
const reader = new FileReader()
|
||||
reader.onload = function (e) {
|
||||
img.src = e.target?.result as string
|
||||
|
||||
img.onload = function () {
|
||||
// Create a canvas
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
// Calculate new size
|
||||
let width = img.width
|
||||
let height = img.height
|
||||
|
||||
if (width > height) {
|
||||
if (width > maxWidth) {
|
||||
height = Math.round(height * maxWidth / width)
|
||||
width = maxWidth
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (height > maxHeight) {
|
||||
width = Math.round(width * maxHeight / height)
|
||||
height = maxHeight
|
||||
}
|
||||
}
|
||||
|
||||
// Set canvas dimensions
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
|
||||
if (!ctx) {
|
||||
console.error('compressAndResizeImage => ctx is null')
|
||||
return
|
||||
}
|
||||
|
||||
// Draw the image on the canvas
|
||||
ctx.drawImage(img, 0, 0, width, height)
|
||||
|
||||
// Compress the image
|
||||
canvas.toBlob((blob) => {
|
||||
// Create a new blob file
|
||||
const compressedFile = new File([blob as Blob], file.name, {
|
||||
type: 'image/jpeg',
|
||||
lastModified: Date.now(),
|
||||
})
|
||||
|
||||
// Execute the callback with the new compressed file
|
||||
callback(compressedFile)
|
||||
}, 'image/jpeg', quality)
|
||||
}
|
||||
}
|
||||
|
||||
// Read the file as a Data URL (base64)
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user