修复移动端目录悬浮球,修复文章页布局,优化画廊
This commit is contained in:
1 parent
788d0cc488
commit
67dc37c308
355 files changed
+1407
-270
No files matched your search
@@ -0,0 +1,56 @@
|
||||
---
|
||||
---
|
||||
|
||||
<div class="wi-cursor-glow" id="wi-cursor-glow"></div>
|
||||
|
||||
<script is:inline>
|
||||
(function(){
|
||||
var glowEl = document.getElementById("wi-cursor-glow");
|
||||
if (!glowEl) return;
|
||||
var rafId = 0;
|
||||
document.addEventListener("mousemove", function(e) {
|
||||
if (rafId) return;
|
||||
rafId = requestAnimationFrame(function() {
|
||||
glowEl.style.transform = "translate(calc(" + e.clientX + "px - 50%), calc(" + e.clientY + "px - 50%))";
|
||||
glowEl.classList.add("wi-cursor-glow--visible");
|
||||
rafId = 0;
|
||||
});
|
||||
}, { passive: true });
|
||||
document.addEventListener("mouseleave", function() {
|
||||
glowEl.classList.remove("wi-cursor-glow--visible");
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.wi-cursor-glow {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(212, 118, 78, 0.06) 0%,
|
||||
transparent 70%
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.wi-cursor-glow--visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
html.dark .wi-cursor-glow {
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(232, 149, 95, 0.04) 0%,
|
||||
transparent 70%
|
||||
);
|
||||
}
|
||||
</style>
|
||||
@@ -1,74 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
|
||||
const glowEl = ref<HTMLElement | null>(null);
|
||||
const visible = ref(false);
|
||||
var rafId = 0;
|
||||
|
||||
function handleMouseMove(e: MouseEvent) {
|
||||
if (rafId) return;
|
||||
rafId = requestAnimationFrame(() => {
|
||||
if (glowEl.value) {
|
||||
glowEl.value.style.transform = `translate(calc(${e.clientX}px - 50%), calc(${e.clientY}px - 50%))`;
|
||||
}
|
||||
rafId = 0;
|
||||
});
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
function handleMouseLeave() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener("mousemove", handleMouseMove, { passive: true });
|
||||
document.addEventListener("mouseleave", handleMouseLeave);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener("mousemove", handleMouseMove);
|
||||
document.removeEventListener("mouseleave", handleMouseLeave);
|
||||
if (rafId) cancelAnimationFrame(rafId);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="glowEl"
|
||||
class="wi-cursor-glow"
|
||||
:class="{ 'wi-cursor-glow--visible': visible }"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.wi-cursor-glow {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(212, 118, 78, 0.06) 0%,
|
||||
transparent 70%
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.wi-cursor-glow--visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
html.dark .wi-cursor-glow {
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(232, 149, 95, 0.04) 0%,
|
||||
transparent 70%
|
||||
);
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
const THEME_VERSION = "0.1.0";
|
||||
const THEME_VERSION = "1.0.0";
|
||||
const today = new Date();
|
||||
---
|
||||
|
||||
|
||||
@@ -6,14 +6,10 @@
|
||||
import 'lightgallery/css/lg-zoom.css';
|
||||
import 'lightgallery/css/lg-thumbnail.css';
|
||||
import 'lightgallery/css/lg-fullscreen.css';
|
||||
import 'lightgallery/css/lg-rotate.css';
|
||||
import 'lightgallery/css/lg-autoplay.css';
|
||||
import lightGallery from 'lightgallery';
|
||||
import lgZoom from 'lightgallery/plugins/zoom';
|
||||
import lgThumbnail from 'lightgallery/plugins/thumbnail';
|
||||
import lgFullscreen from 'lightgallery/plugins/fullscreen';
|
||||
import lgRotate from 'lightgallery/plugins/rotate';
|
||||
import lgAutoplay from 'lightgallery/plugins/autoplay';
|
||||
|
||||
var _initialized = new WeakSet();
|
||||
|
||||
@@ -74,7 +70,7 @@
|
||||
function createLgConfig() {
|
||||
return {
|
||||
selector: '.wi-lightgallery-item',
|
||||
plugins: [lgZoom, lgThumbnail, lgFullscreen, lgRotate, lgAutoplay],
|
||||
plugins: [lgZoom, lgThumbnail, lgFullscreen],
|
||||
speed: 280,
|
||||
mode: 'lg-fade',
|
||||
licenseKey: '0000-0000-0000-0000',
|
||||
@@ -89,15 +85,6 @@
|
||||
showZoomInOutIcons: true,
|
||||
toggleThumb: true,
|
||||
allowMediaOverlap: true,
|
||||
autoplay: true,
|
||||
slideShowAutoplay: false,
|
||||
slideShowInterval: 5000,
|
||||
progressBar: true,
|
||||
autoplayControls: true,
|
||||
forceSlideShowAutoplay: false,
|
||||
rotate: true,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
mobileSettings: {
|
||||
controls: true,
|
||||
showCloseIcon: true,
|
||||
@@ -272,8 +259,18 @@
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initLightGallery);
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if ('requestIdleCallback' in window) {
|
||||
requestIdleCallback(initLightGallery, { timeout: 2000 });
|
||||
} else {
|
||||
setTimeout(initLightGallery, 200);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
initLightGallery();
|
||||
if ('requestIdleCallback' in window) {
|
||||
requestIdleCallback(initLightGallery, { timeout: 2000 });
|
||||
} else {
|
||||
setTimeout(initLightGallery, 200);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
import ThemeSwitcher from "./ThemeSwitcher.astro";
|
||||
---
|
||||
|
||||
<header class="wi-navbar-wrapper" id="wi-navbar" th:classappend="${theme.config?.navbar?.navbar_style == 'minimal'} ? 'wi-navbar--minimal' : (${theme.config?.navbar?.navbar_style == 'float'} ? 'wi-navbar--float' : 'wi-navbar--glass')">
|
||||
@@ -10,6 +10,8 @@ import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
th:src="${theme.config?.basic?.logo}"
|
||||
alt=""
|
||||
class="wi-navbar__logo"
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
/>
|
||||
<span
|
||||
th:if="${#strings.isEmpty(theme.config?.basic?.logo)}"
|
||||
@@ -42,7 +44,7 @@ import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
<div class="wi-navbar__actions">
|
||||
<button
|
||||
th:if="${pluginFinder.available('PluginSearchWidget') and theme.config?.navbar?.navbar_show_search != false}"
|
||||
class="wi-navbar__action-btn"
|
||||
class="wi-navbar__action-btn wi-navbar__search-btn"
|
||||
type="button"
|
||||
th:aria-label="${theme.config?.basic?.label_search ?: #messages.msg('common.search')}"
|
||||
onclick="SearchWidget.open()"
|
||||
@@ -52,7 +54,7 @@ import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
|
||||
<th:block th:if="${theme.config?.navbar?.navbar_show_theme_switch != false}">
|
||||
<span th:attr="data-label=${theme.config?.basic?.label_theme_switch ?: #messages.msg('common.themeSwitch')}" style="display:inline-flex">
|
||||
<ThemeSwitcher client:idle />
|
||||
<ThemeSwitcher />
|
||||
</span>
|
||||
</th:block>
|
||||
|
||||
@@ -315,8 +317,9 @@ import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wi-navbar__action-btn[aria-label="Search"] {
|
||||
display: none;
|
||||
.wi-navbar__action-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.wi-navbar__menu-btn {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
---
|
||||
|
||||
<script is:inline>
|
||||
(function(){
|
||||
var enabled = !document.documentElement.classList.contains("wi-no-animations");
|
||||
if (!enabled) {
|
||||
document.querySelectorAll(".wi-reveal").forEach(function(el) {
|
||||
el.classList.add("wi-revealed");
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!("IntersectionObserver" in window)) {
|
||||
document.querySelectorAll(".wi-reveal").forEach(function(el) {
|
||||
el.classList.add("wi-revealed");
|
||||
});
|
||||
return;
|
||||
}
|
||||
var observer = new IntersectionObserver(function(entries) {
|
||||
entries.forEach(function(entry) {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("wi-revealed");
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.1, rootMargin: "0px 0px -40px 0px" });
|
||||
document.querySelectorAll(".wi-reveal").forEach(function(el) {
|
||||
observer.observe(el);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -1,36 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
|
||||
const observer = ref<IntersectionObserver | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
const animationEnabled = !document.documentElement.classList.contains(
|
||||
"wi-no-animations"
|
||||
);
|
||||
if (!animationEnabled) return;
|
||||
|
||||
observer.value = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("wi-revealed");
|
||||
observer.value?.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.1, rootMargin: "0px 0px -40px 0px" }
|
||||
);
|
||||
|
||||
document.querySelectorAll(".wi-reveal").forEach((el) => {
|
||||
observer.value?.observe(el);
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
observer.value?.disconnect();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot />
|
||||
</template>
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
---
|
||||
|
||||
<button
|
||||
class="theme-toggle"
|
||||
type="button"
|
||||
id="wi-theme-toggle"
|
||||
aria-label="切换主题"
|
||||
title="切换主题"
|
||||
>
|
||||
<svg class="theme-toggle__icon theme-toggle__icon--sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="5"></circle>
|
||||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||||
</svg>
|
||||
<svg class="theme-toggle__icon theme-toggle__icon--moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<script is:inline>
|
||||
(function(){
|
||||
var btn = document.getElementById("wi-theme-toggle");
|
||||
if (!btn) return;
|
||||
var sunIcon = btn.querySelector(".theme-toggle__icon--sun");
|
||||
var moonIcon = btn.querySelector(".theme-toggle__icon--moon");
|
||||
var isDark = document.documentElement.classList.contains("dark");
|
||||
|
||||
function updateIcons() {
|
||||
if (isDark) {
|
||||
sunIcon.style.display = "";
|
||||
moonIcon.style.display = "none";
|
||||
} else {
|
||||
sunIcon.style.display = "none";
|
||||
moonIcon.style.display = "";
|
||||
}
|
||||
}
|
||||
|
||||
var labelEl = document.querySelector("[data-label]");
|
||||
if (labelEl) {
|
||||
var label = labelEl.getAttribute("data-label") || "切换主题";
|
||||
btn.setAttribute("aria-label", label);
|
||||
btn.setAttribute("title", label);
|
||||
}
|
||||
|
||||
updateIcons();
|
||||
|
||||
btn.addEventListener("click", function() {
|
||||
document.documentElement.classList.add("wi-theme-transition");
|
||||
isDark = !isDark;
|
||||
document.documentElement.classList.toggle("dark", isDark);
|
||||
document.documentElement.setAttribute("data-color-scheme", isDark ? "dark" : "light");
|
||||
localStorage.setItem("wi-theme", isDark ? "dark" : "light");
|
||||
var tc = document.querySelector('meta[name="theme-color"]');
|
||||
if (tc) tc.setAttribute("content", isDark ? "#1a1614" : "#faf7f2");
|
||||
updateIcons();
|
||||
setTimeout(function() {
|
||||
document.documentElement.classList.remove("wi-theme-transition");
|
||||
}, 300);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.theme-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--ink-2);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.15s ease,
|
||||
color 0.15s ease;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
background: var(--bg-raised);
|
||||
color: var(--ink);
|
||||
}
|
||||
</style>
|
||||
@@ -1,64 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import MingcuteMoonLine from "~icons/mingcute/moon-line";
|
||||
import MingcuteSunLine from "~icons/mingcute/sun-line";
|
||||
|
||||
const isDark = ref(false);
|
||||
const label = ref("切换主题");
|
||||
|
||||
onMounted(() => {
|
||||
isDark.value = document.documentElement.classList.contains("dark");
|
||||
const parent = document.querySelector("[data-label]");
|
||||
if (parent) {
|
||||
label.value = parent.getAttribute("data-label") || "切换主题";
|
||||
}
|
||||
});
|
||||
|
||||
function toggle() {
|
||||
document.documentElement.classList.add("wi-theme-transition");
|
||||
isDark.value = !isDark.value;
|
||||
document.documentElement.classList.toggle("dark", isDark.value);
|
||||
localStorage.setItem("wi-theme", isDark.value ? "dark" : "light");
|
||||
setTimeout(() => {
|
||||
document.documentElement.classList.remove("wi-theme-transition");
|
||||
}, 300);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
class="theme-toggle"
|
||||
type="button"
|
||||
:aria-label="label"
|
||||
:title="label"
|
||||
@click="toggle"
|
||||
>
|
||||
<MingcuteSunLine v-if="isDark" />
|
||||
<MingcuteMoonLine v-else />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.theme-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--ink-2);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.15s ease,
|
||||
color 0.15s ease;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
background: var(--bg-raised);
|
||||
color: var(--ink);
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user