blog / src /components /features /OverlayWallpaper.astro
cacode's picture
Upload 434 files
96dd062 verified
---
import { Picture } from "astro:assets";
import * as path from "node:path";
import type { ImageMetadata } from "astro";
import {
getFallbackFormat,
getImageFormats,
getImageQuality,
} from "@/utils/image-utils";
import { url } from "@/utils/url-utils";
interface Props {
config: {
src: {
desktop?: string;
mobile?: string;
};
position?: string;
zIndex?: number;
opacity?: number;
blur?: number;
};
className?: string;
}
const { config, className } = Astro.props;
// 获取图片源
const desktopSrc = config.src.desktop || config.src.mobile || "";
const mobileSrc = config.src.mobile || config.src.desktop || "";
// 如果没有任何图片源,不渲染
if (!desktopSrc && !mobileSrc) {
return null;
}
// 判断是否为本地图片
const isLocalImage = (src: string) => {
return (
src &&
!src.startsWith("/") &&
!src.startsWith("http") &&
!src.startsWith("https") &&
!src.startsWith("data:")
);
};
const isPublicImage = (src: string) => src.startsWith("/");
// 动态导入本地图片
let desktopImg: ImageMetadata | null = null;
let mobileImg: ImageMetadata | null = null;
if (isLocalImage(desktopSrc)) {
const files = import.meta.glob<ImageMetadata>("../../**", {
import: "default",
});
const normalizedPath = path
.normalize(path.join("../../", desktopSrc))
.replace(/\\/g, "/");
const file = files[normalizedPath];
if (file) {
desktopImg = await file();
}
}
if (isLocalImage(mobileSrc)) {
const files = import.meta.glob<ImageMetadata>("../../**", {
import: "default",
});
const normalizedPath = path
.normalize(path.join("../../", mobileSrc))
.replace(/\\/g, "/");
const file = files[normalizedPath];
if (file) {
mobileImg = await file();
}
}
// 样式相关
const position = config.position || "center";
const zIndex = config.zIndex || -1;
const opacity = config.opacity || 0.8;
const blur = config.blur || 0;
// 图片格式配置
const imageFormats = getImageFormats();
const fallbackFormat = getFallbackFormat();
const desktopQuality = getImageQuality();
const mobileQuality = Math.round(getImageQuality() * 0.9);
const imageStyle = `object-position: ${position};${blur > 0 ? ` filter: blur(${blur}px);` : ""}`;
---
<div
class:list={[
"fixed inset-0 w-full h-full overflow-hidden pointer-events-none",
className
].filter(Boolean)}
style={`z-index: ${zIndex}; opacity: ${opacity};`}
data-overlay-wallpaper
>
<!-- 桌面端壁纸 -->
{desktopSrc && (
<div class="hidden lg:block w-full h-full relative">
{desktopImg ? (
<Picture
src={desktopImg}
alt="Desktop wallpaper"
class="absolute inset-0 w-full h-full object-cover"
style={imageStyle}
formats={imageFormats}
fallbackFormat={fallbackFormat}
widths={[1280, 1920, 2560]}
sizes="100vw"
loading="eager"
fetchpriority="high"
quality={desktopQuality}
/>
) : (
<img
src={isPublicImage(desktopSrc) ? url(desktopSrc) : desktopSrc}
alt="Desktop wallpaper"
class="absolute inset-0 w-full h-full object-cover"
style={imageStyle}
loading="eager"
fetchpriority="high"
/>
)}
</div>
)}
<!-- 移动端壁纸 -->
{mobileSrc && (
<div class="block lg:hidden w-full h-full relative">
{mobileImg ? (
<Picture
src={mobileImg}
alt="Mobile wallpaper"
class="absolute inset-0 w-full h-full object-cover"
style={imageStyle}
formats={imageFormats}
fallbackFormat={fallbackFormat}
widths={[640, 750, 1080]}
sizes="100vw"
loading="eager"
fetchpriority="high"
quality={mobileQuality}
/>
) : (
<img
src={isPublicImage(mobileSrc) ? url(mobileSrc) : mobileSrc}
alt="Mobile wallpaper"
class="absolute inset-0 w-full h-full object-cover"
style={imageStyle}
loading="eager"
fetchpriority="high"
/>
)}
</div>
)}
</div>