mirror of
https://github.com/fankes/komari-theme-purcarte.git
synced 2025-10-19 03:49:22 +08:00
refactor(background): 简化背景功能为静态图片
动态背景切换功能因效果不佳暂时移除。本次重构将背景实现简化为仅支持单张静态图片
This commit is contained in:
10
README.md
10
README.md
@@ -31,7 +31,15 @@
|
|||||||
|
|
||||||
### 配置背景图片
|
### 配置背景图片
|
||||||
|
|
||||||
为获得最佳视觉效果,建议搭配背景图片使用。请在 `Komari 后台 > 设置 > 站点 > 自定义 Body` 处添加以下代码并保存:
|
> 为获得最佳视觉效果,建议搭配背景图片使用。
|
||||||
|
|
||||||
|
#### Komari v1.0.5 及以上版本
|
||||||
|
|
||||||
|
如果 Komari 版本为 v1.0.5 或更高版本,可直接在 `Komari 后台 > PurCarte设置` 中配置背景图片等主题选项,无需手动添加自定义代码
|
||||||
|
|
||||||
|
#### 旧版本配置方法
|
||||||
|
|
||||||
|
对于旧版本,请在 `Komari 后台 > 设置 > 站点 > 自定义 Body` 处添加以下代码并保存:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<style>
|
<style>
|
||||||
|
@@ -18,24 +18,8 @@
|
|||||||
"name": "背景图片链接",
|
"name": "背景图片链接",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "https://i.yon.li/w/682f73d97eade.png",
|
"default": "/assets/Moonlit-Scenery.webp",
|
||||||
"help": "多张图片请以英文逗号分隔(eg:https://img.com/1.png,https://test.com/2.jpg)"
|
"help": "目前仅支持单张背景图片(eg: https://test.com/1.png)"
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "switchTime",
|
|
||||||
"name": "切换时间(秒)",
|
|
||||||
"type": "number",
|
|
||||||
"required": false,
|
|
||||||
"default": 10,
|
|
||||||
"help": "背景图片切换的时间间隔,单位为秒(仅设置多张图片时生效)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "transition",
|
|
||||||
"name": "背景切换过渡效果",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "background-image 0.8s ease-in-out",
|
|
||||||
"help": "CSS 过渡效果,用于背景图片切换时的动画效果(仅设置多张图片时生效)"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
BIN
public/assets/Moonlit-Scenery.webp
Normal file
BIN
public/assets/Moonlit-Scenery.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
@@ -1,99 +1,39 @@
|
|||||||
import { useEffect, useState, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import { BACKGROUND } from "@/config/default";
|
import { BACKGROUND } from "@/config/default";
|
||||||
import type { PublicInfo } from "@/types/node.d";
|
import type { PublicInfo } from "@/types/node.d";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态背景组件
|
* 动态效果不佳,暂时仅使用静态背景
|
||||||
* 根据设定的时间间隔自动切换背景图片
|
|
||||||
* 并预加载所有图片以提高用户体验
|
|
||||||
* 支持自定义过渡效果和切换时间
|
|
||||||
*/
|
*/
|
||||||
interface ThemeSettings {
|
interface ThemeSettings {
|
||||||
backgroundImage?: string; // 逗号分隔的背景图片URL列表
|
backgroundImage?: string; // 背景图片URL
|
||||||
switchTime?: number; // 背景切换时间间隔(秒)
|
|
||||||
transition?: string; // CSS过渡效果
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BackgroundProps {
|
interface BackgroundProps {
|
||||||
publicSettings: PublicInfo;
|
publicSettings: PublicInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DynamicPseudoBackground({ publicSettings }: BackgroundProps) {
|
function Background({ publicSettings }: BackgroundProps) {
|
||||||
const theme = (publicSettings?.theme_settings as ThemeSettings) || {};
|
const theme = (publicSettings?.theme_settings as ThemeSettings) || {};
|
||||||
|
|
||||||
// 使用 useMemo 缓存背景图片列表,避免每次渲染时重新计算
|
// 使用 useMemo 缓存背景图片列表,避免每次渲染时重新计算
|
||||||
const imageList = useMemo(() => {
|
const imageUrl = useMemo(() => {
|
||||||
return theme.backgroundImage
|
return theme.backgroundImage
|
||||||
? theme.backgroundImage.split(",").map((url) => url.trim())
|
? theme.backgroundImage
|
||||||
: [BACKGROUND.backgroundImage];
|
: BACKGROUND.backgroundImage;
|
||||||
}, [theme.backgroundImage]);
|
}, [theme.backgroundImage]);
|
||||||
|
|
||||||
// 将切换时间从秒转换为毫秒
|
|
||||||
const switchTime = useMemo(() => {
|
|
||||||
return (theme.switchTime || BACKGROUND.switchTime) * 1000;
|
|
||||||
}, [theme.switchTime]);
|
|
||||||
|
|
||||||
const transition = useMemo(() => {
|
|
||||||
return theme.transition || BACKGROUND.transition;
|
|
||||||
}, [theme.transition]);
|
|
||||||
|
|
||||||
const [currentImageIndex, setCurrentImageIndex] = useState(0);
|
|
||||||
const currentImageUrl = imageList[currentImageIndex];
|
|
||||||
|
|
||||||
// 预加载指定的图片
|
|
||||||
const preloadImage = (url: string) => {
|
|
||||||
if (!url) return;
|
|
||||||
const img = new Image();
|
|
||||||
img.src = url;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 预加载所有图片,只在组件初始化或图片列表变化时执行一次
|
|
||||||
useEffect(() => {
|
|
||||||
// 只有当有多张图片时才设置过渡效果
|
|
||||||
if (imageList.length > 1) {
|
|
||||||
document.body.style.setProperty(
|
|
||||||
"--body-background-transition",
|
|
||||||
transition
|
|
||||||
);
|
|
||||||
|
|
||||||
// 预加载所有图片以提高用户体验
|
|
||||||
imageList.forEach((url) => {
|
|
||||||
preloadImage(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 组件卸载时清理
|
|
||||||
return () => {
|
|
||||||
document.body.style.removeProperty("--body-background-transition");
|
|
||||||
};
|
|
||||||
}, [imageList, transition]);
|
|
||||||
|
|
||||||
// 背景切换逻辑
|
// 背景切换逻辑
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 当当前图片URL变化时,更新CSS变量
|
// 当当前图片URL变化时,更新CSS变量
|
||||||
document.body.style.setProperty(
|
document.body.style.setProperty(
|
||||||
"--body-background-url",
|
"--body-background-url",
|
||||||
`url(${currentImageUrl})`
|
`url(${imageUrl})`
|
||||||
);
|
);
|
||||||
|
}, [imageUrl]);
|
||||||
// 只有当有多张图片时才设置定时器进行轮换
|
|
||||||
let intervalId: number | undefined;
|
|
||||||
if (imageList.length > 1) {
|
|
||||||
intervalId = window.setInterval(() => {
|
|
||||||
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % imageList.length);
|
|
||||||
}, switchTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清理函数,组件卸载或依赖项变化时执行
|
|
||||||
return () => {
|
|
||||||
if (intervalId) {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [currentImageUrl, imageList, switchTime]);
|
|
||||||
|
|
||||||
// 此组件不渲染任何可见内容
|
// 此组件不渲染任何可见内容
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DynamicPseudoBackground;
|
export default Background;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
export const BACKGROUND = {
|
export const BACKGROUND = {
|
||||||
backgroundImage: "https://i.yon.li/w/682f73d97eade.png",
|
backgroundImage: "",
|
||||||
switchTime: 10, // 10 seconds
|
// switchTime: 10, // 10 seconds
|
||||||
transition: "background-image 0.8s ease-in-out", // CSS transition for background change
|
// transition: "background-image 0.8s ease-in-out", // CSS transition for background change
|
||||||
};
|
};
|
||||||
|
@@ -81,7 +81,7 @@
|
|||||||
--frosted-border-light: rgba(255, 255, 255, 0.2);
|
--frosted-border-light: rgba(255, 255, 255, 0.2);
|
||||||
|
|
||||||
--body-background-url: url("");
|
--body-background-url: url("");
|
||||||
--body-background-transition: background-image 0.8s ease-in-out;
|
/* --body-background-transition: background-image 0.8s ease-in-out; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
@@ -145,7 +145,7 @@ body::before {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
background: var(--body-background-url) center/cover no-repeat;
|
background: var(--body-background-url) center/cover no-repeat;
|
||||||
transition: var(--body-background-transition);
|
/* transition: var(--body-background-transition); */
|
||||||
}
|
}
|
||||||
|
|
||||||
.striped-bg-red-translucent-diagonal {
|
.striped-bg-red-translucent-diagonal {
|
||||||
|
@@ -5,7 +5,7 @@ import "./index.css";
|
|||||||
import "@radix-ui/themes/styles.css";
|
import "@radix-ui/themes/styles.css";
|
||||||
import { Theme } from "@radix-ui/themes";
|
import { Theme } from "@radix-ui/themes";
|
||||||
import { Header } from "@/components/sections/Header";
|
import { Header } from "@/components/sections/Header";
|
||||||
import DynamicPseudoBackground from "@/components/sections/Background";
|
import Background from "@/components/sections/Background";
|
||||||
import { useTheme } from "@/hooks/useTheme";
|
import { useTheme } from "@/hooks/useTheme";
|
||||||
import { NodeDataProvider } from "@/contexts/NodeDataContext";
|
import { NodeDataProvider } from "@/contexts/NodeDataContext";
|
||||||
import { LiveDataProvider } from "@/contexts/LiveDataContext";
|
import { LiveDataProvider } from "@/contexts/LiveDataContext";
|
||||||
@@ -46,10 +46,8 @@ const App = () => {
|
|||||||
appearance="inherit"
|
appearance="inherit"
|
||||||
scaling="110%"
|
scaling="110%"
|
||||||
style={{ backgroundColor: "transparent" }}>
|
style={{ backgroundColor: "transparent" }}>
|
||||||
{/* 使用动态背景组件 */}
|
{/* 使用背景组件 */}
|
||||||
{publicSettings && (
|
{publicSettings && <Background publicSettings={publicSettings} />}
|
||||||
<DynamicPseudoBackground publicSettings={publicSettings} />
|
|
||||||
)}
|
|
||||||
<div className="min-h-screen flex flex-col text-sm">
|
<div className="min-h-screen flex flex-col text-sm">
|
||||||
<Header
|
<Header
|
||||||
viewMode={viewMode}
|
viewMode={viewMode}
|
||||||
|
Reference in New Issue
Block a user