diff --git a/config.json b/config.json
index 19eef0e..9b270ab 100644
--- a/config.json
+++ b/config.json
@@ -17,7 +17,7 @@
"urlMode":"issue",
"showPostSource":0,
"needComment":0,
- "indexScript":"",
"bottomText":"❤️ 转载文章请注明出处,谢谢!❤️",
- "script":"",
- "allHead":"",
+ "script":"",
+ "allHead":""
+}
diff --git a/static/assets/articletoc.js b/static/assets/articletoc.js
deleted file mode 100644
index 1037e45..0000000
--- a/static/assets/articletoc.js
+++ /dev/null
@@ -1,158 +0,0 @@
-function loadResource(type, attributes) {
- if (type === 'style') {
- const style = document.createElement('style');
- style.textContent = attributes.css;
- document.head.appendChild(style);
- }
-}
-
-function createTOC() {
- const tocElement = document.createElement('div');
- tocElement.className = 'toc';
- const contentContainer = document.querySelector('.markdown-body');
- contentContainer.appendChild(tocElement);
-
- const headings = contentContainer.querySelectorAll('h1, h2, h3, h4, h5, h6');
- headings.forEach(heading => {
- if (!heading.id) {
- heading.id = heading.textContent.trim().replace(/\s+/g, '-').toLowerCase();
- }
- const link = document.createElement('a');
- link.href = '#' + heading.id;
- link.textContent = heading.textContent;
- link.className = 'toc-link';
- link.style.paddingLeft = `${(parseInt(heading.tagName.charAt(1)) - 1) * 10}px`;
- tocElement.appendChild(link);
- });
-}
-
-function toggleTOC() {
- const tocElement = document.querySelector('.toc');
- const tocIcon = document.querySelector('.toc-icon');
- if (tocElement) {
- tocElement.classList.toggle('show');
- tocIcon.classList.toggle('active');
- tocIcon.textContent = tocElement.classList.contains('show') ? '✖' : '☰';
- }
-}
-
-document.addEventListener("DOMContentLoaded", function() {
- createTOC();
- const css = `
- :root {
- --toc-bg: #fff;
- --toc-border: #e1e4e8;
- --toc-text: #24292e;
- --toc-hover: #f6f8fa;
- --toc-icon-bg: #fff;
- --toc-icon-color: #ad6598;
- --toc-icon-active-bg: #813c85;
- --toc-icon-active-color: #fff;
- }
-
- @media (prefers-color-scheme: dark) {
- :root {
- --toc-bg: #2d333b;
- --toc-border: #444c56;
- --toc-text: #adbac7;
- --toc-hover: #373e47;
- --toc-icon-bg: #22272e;
- --toc-icon-color: #ad6598;
- --toc-icon-active-bg: #813c85;
- --toc-icon-active-color: #adbac7;
- }
- }
-
- .toc {
- position: fixed;
- bottom: 60px;
- right: 20px;
- width: 250px;
- max-height: 70vh;
- background-color: var(--toc-bg);
- border: 1px solid var(--toc-border);
- border-radius: 6px;
- padding: 10px;
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
- overflow-y: auto;
- z-index: 1000;
- opacity: 0;
- visibility: hidden;
- transform: translateY(20px) scale(0.9);
- transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
- }
- .toc.show {
- opacity: 1;
- visibility: visible;
- transform: translateY(0) scale(1);
- }
- .toc a {
- display: block;
- color: var(--toc-text);
- text-decoration: none;
- padding: 5px 0;
- font-size: 14px;
- line-height: 1.5;
- border-bottom: 1px solid var(--toc-border);
- transition: background-color 0.2s ease, padding-left 0.2s ease;
- }
- .toc a:last-child {
- border-bottom: none;
- }
- .toc a:hover {
- background-color: var(--toc-hover);
- padding-left: 5px;
- }
- .toc-icon {
- position: fixed;
- bottom: 20px;
- right: 20px;
- cursor: pointer;
- font-size: 24px;
- background-color: var(--toc-icon-bg);
- color: var(--toc-icon-color);
- border: 2px solid var(--toc-icon-color);
- border-radius: 50%;
- width: 40px;
- height: 40px;
- display: flex;
- align-items: center;
- justify-content: center;
- box-shadow: 0 1px 3px rgba(0,0,0,0.12);
- z-index: 1001;
- transition: all 0.3s ease;
- user-select: none;
- -webkit-tap-highlight-color: transparent;
- outline: none;
- }
- .toc-icon:hover {
- transform: scale(1.1);
- }
- .toc-icon:active {
- transform: scale(0.9);
- }
- .toc-icon.active {
- background-color: var(--toc-icon-active-bg);
- color: var(--toc-icon-active-color);
- border-color: var(--toc-icon-active-bg);
- transform: rotate(90deg);
- }
- `;
- loadResource('style', {css: css});
-
- const tocIcon = document.createElement('div');
- tocIcon.className = 'toc-icon';
- tocIcon.textContent = '☰';
- tocIcon.onclick = (e) => {
- e.stopPropagation();
- toggleTOC();
- };
- document.body.appendChild(tocIcon);
-
- document.addEventListener('click', (e) => {
- const tocElement = document.querySelector('.toc');
- if (tocElement && tocElement.classList.contains('show') && !tocElement.contains(e.target) && !e.target.classList.contains('toc-icon')) {
- toggleTOC();
- }
- });
-});
diff --git a/static/assets/lazyload.js b/static/assets/lazyload.js
deleted file mode 100644
index 724416d..0000000
--- a/static/assets/lazyload.js
+++ /dev/null
@@ -1,25 +0,0 @@
- // lazyload.js
- document.addEventListener('DOMContentLoaded', () => {
- const images = document.querySelectorAll('img[data-src]');
-
- const lazyLoad = target => {
- const io = new IntersectionObserver((entries, observer) => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
- const img = entry.target;
- img.src = img.dataset.src;
- img.onload = () => {
- img.classList.add('loaded');
- };
- observer.disconnect();
- }
- });
- });
-
- io.observe(target);
- };
-
- images.forEach(img => {
- lazyLoad(img);
- });
- });
diff --git a/static/background.webp b/static/background.webp
index 2c5b5ba..477c578 100644
Binary files a/static/background.webp and b/static/background.webp differ
diff --git a/static/plugins/ArticleTOC.js b/static/plugins/ArticleTOC.js
new file mode 100644
index 0000000..b877c48
--- /dev/null
+++ b/static/plugins/ArticleTOC.js
@@ -0,0 +1,217 @@
+function loadResource(type, attributes) {
+ if (type === 'style') {
+ const style = document.createElement('style');
+ style.textContent = attributes.css;
+ document.head.appendChild(style);
+ }
+}
+
+function createTOC() {
+ const tocElement = document.createElement('div');
+ tocElement.className = 'toc';
+ tocElement.classList.add('show');
+
+ const contentContainer = document.querySelector('.markdown-body');
+ contentContainer.appendChild(tocElement);
+
+ const headings = contentContainer.querySelectorAll('h1, h2, h3, h4, h5, h6');
+ headings.forEach(heading => {
+ if (!heading.id) {
+ heading.id = heading.textContent.trim().replace(/\s+/g, '-').toLowerCase();
+ }
+ const link = document.createElement('a');
+ link.href = '#' + heading.id;
+ link.textContent = heading.textContent;
+
+ link.setAttribute('data-id', heading.id);
+
+ link.className = 'toc-link';
+ link.style.paddingLeft = `${(parseInt(heading.tagName.charAt(1)) - 1) * 10}px`;
+ tocElement.appendChild(link);
+ });
+
+
+ tocElement.insertAdjacentHTML('beforeend', '返回顶部');
+ contentContainer.prepend(tocElement);
+}
+
+function highlightTOC() {
+ const tocLinks = document.querySelectorAll('.toc-link');
+ const fromTop = window.scrollY + 10;
+
+ let currentHeading = null;
+
+ tocLinks.forEach(link => {
+ const section = document.getElementById(link.getAttribute('data-id'));
+ if (section && section.offsetTop <= fromTop) {
+ currentHeading = link;
+ }
+ });
+
+ tocLinks.forEach(link => {
+ link.classList.remove('active-toc');
+ });
+
+ if (currentHeading) {
+ currentHeading.classList.add('active-toc');
+
+ // 确保当前高亮的目录项在可视区域的中间
+ currentHeading.scrollIntoView({
+ block: 'center', // 确保当前高亮项滚动到视图中间位置
+ inline: 'nearest' // 可选,保持水平滚动条不动
+ });
+ }
+}
+
+function toggleTOC() {
+ const tocElement = document.querySelector('.toc');
+ const tocIcon = document.querySelector('.toc-icon');
+ if (tocElement) {
+ tocElement.classList.toggle('show');
+ tocIcon.classList.toggle('active');
+ tocIcon.textContent = tocElement.classList.contains('show') ? '✖' : '☰';
+ }
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ createTOC();
+ const css = `
+ :root {
+ --toc-bg: rgba(237, 239, 233, 0.84);
+ --toc-border: #e1e4e8;
+ --toc-text: #24292e;
+ --toc-hover: #8ae9c4;
+ --toc-icon-bg: #fff;
+ --toc-icon-color: #ad6598;
+ --toc-icon-active-bg: #813c85;
+ --toc-icon-active-color: #fff;
+ }
+
+ .toc {
+ position: fixed;
+ bottom: 60px;
+ right: 20px;
+ width: 250px;
+ max-height: 70vh;
+ background-color: var(--toc-bg);
+ border: 1px solid var(--toc-border);
+ border-radius: 8px;
+ padding: 10px;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ overflow-y: auto;
+ z-index: 1000;
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(20px) scale(0.9);
+ transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
+ }
+ .toc.show {
+ opacity: 1;
+ visibility: visible;
+ transform: translateY(0) scale(1);
+ }
+ .toc a {
+ display: block;
+ border-radius: 8px;
+ color: var(--toc-text);
+ text-decoration: none;
+ padding: 5px 0;
+ font-size: 14px;
+ line-height: 1.5;
+ border-bottom: 1px solid var(--toc-border);
+ transition: background-color 0.2s ease, padding-left 0.2s ease;
+ }
+ .toc a:last-child {
+ border-bottom: none;
+ }
+ .toc a:hover {
+ background-color: var(--toc-hover);
+ padding-left: 5px;
+ border-radius: 8px;
+ }
+ .toc-icon {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ cursor: pointer;
+ font-size: 24px;
+ background-color: var(--toc-icon-bg);
+ color: var(--toc-icon-color);
+ border: 2px solid var(--toc-icon-color);
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12);
+ z-index: 1001;
+ transition: all 0.3s ease;
+ user-select: none;
+ -webkit-tap-highlight-color: transparent;
+ outline: none;
+ }
+ .toc-icon:hover {
+ transform: scale(0.9);
+ }
+ .toc-icon:active {
+ transform: scale(0.9);
+ }
+ .toc-icon.active {
+ background-color: var(--toc-icon-active-bg);
+ color: var(--toc-icon-active-color);
+ border-color: var(--toc-icon-active-bg);
+ transform: rotate(90deg);
+ }
+
+ .toc-end {
+ font-weight: bold;
+ text-align: center;
+ cursor: pointer;
+ visibility: hidden;
+ background-color: white;
+ padding: 10px; /* 可选:增加一些内边距,使按钮更易点击 */
+ border-radius: 8px; /* 可选:使按钮有圆角 */
+ border: 1px solid var(--toc-border); /* 可选:增加边框,使其更明显 */
+ }
+
+ .active-toc {
+ font-weight: bold;
+ border-radius: 8px;
+ background-color: var(--toc-hover); /* 根据你的设计,可以定制高亮颜色 */
+ padding-left: 5px; /* 可选:增加左边距以突出当前项目 */
+ }
+ `;
+ loadResource('style', {css: css});
+
+ const tocIcon = document.createElement('div');
+ tocIcon.className = 'toc-icon';
+
+ tocIcon.classList.add('active');
+
+ tocIcon.textContent = '✖';
+ tocIcon.onclick = (e) => {
+ e.stopPropagation();
+ toggleTOC();
+ };
+ document.body.appendChild(tocIcon);
+
+ window.onscroll = function() {
+ const backToTopButton = document.querySelector('.toc-end');
+ if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
+ backToTopButton.style="visibility: visible;background-color: white;"
+ } else {
+ backToTopButton.style="visibility: hidden;background-color: white;"
+ }
+ };
+
+ document.addEventListener('scroll', highlightTOC);
+
+ document.addEventListener('click', (e) => {
+ const tocElement = document.querySelector('.toc');
+ if (tocElement && tocElement.classList.contains('show') && !tocElement.contains(e.target) && e.target.classList.contains('toc-icon')) {
+ toggleTOC();
+
+ }
+ });
+});
diff --git a/static/assets/yifantheme_index.js b/static/plugins/RonanTheme.js
similarity index 94%
rename from static/assets/yifantheme_index.js
rename to static/plugins/RonanTheme.js
index a093299..8a1196a 100644
--- a/static/assets/yifantheme_index.js
+++ b/static/plugins/RonanTheme.js
@@ -29,7 +29,7 @@ style.innerHTML = `
}
html {
- background: url('https://bing.img.run/1920x1080.php') no-repeat center center fixed;
+ background: url('https://blog.freeblock.cn/background.webp') no-repeat center center fixed;
background-size: cover;
}
@@ -76,7 +76,7 @@ document.head.appendChild(style);
style.innerHTML = `
html {
- background: url('https://wowpb.pages.dev/file/2a84a86f2bb288032e3a1.jpg') no-repeat center center fixed;
+ background: url('https://blog.freeblock.cn/background.webp') no-repeat center center fixed;
background-size: cover;
}
@@ -148,7 +148,7 @@ document.head.appendChild(style);
style.innerHTML = `
html {
- background: url('https://wowpb.pages.dev/file/2a84a86f2bb288032e3a1.jpg') no-repeat center center fixed;
+ background: url('https://blog.freeblock.cn/background.webp') no-repeat center center fixed;
background-size: cover;
}
diff --git a/static/plugins/lightbox.js b/static/plugins/lightbox.js
new file mode 100644
index 0000000..b7389ef
--- /dev/null
+++ b/static/plugins/lightbox.js
@@ -0,0 +1,369 @@
+(function() {
+ // 灯箱插件
+ class Lightbox {
+ constructor(options = {}) {
+ this.options = Object.assign({
+ animationDuration: 300,
+ closeOnOverlayClick: true,
+ onOpen: null,
+ onClose: null,
+ onNavigate: null
+ }, options);
+
+ this.images = [];
+ this.currentIndex = 0;
+ this.isOpen = false;
+ this.isZoomed = false;
+ this.zoomLevel = 1;
+ this.touchStartX = 0;
+ this.touchEndX = 0;
+ this.wheelTimer = null;
+
+ this.init();
+ }
+
+ init() {
+ this.createStyles();
+ this.createLightbox();
+ this.bindEvents();
+ }
+
+ createStyles() {
+ const style = document.createElement('style');
+ style.textContent = `
+ .lb-lightbox-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(255, 255, 255, 0.9);
+ backdrop-filter: blur(5px);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0;
+ transition: opacity ${this.options.animationDuration}ms ease;
+ pointer-events: none;
+ }
+ .lb-lightbox-overlay.active {
+ pointer-events: auto;
+ }
+ .lb-lightbox-content-wrapper {
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 100%;
+ }
+ .lb-lightbox-container {
+ max-width: 90%;
+ max-height: 90%;
+ position: relative;
+ transition: transform ${this.options.animationDuration}ms cubic-bezier(0.25, 0.1, 0.25, 1);
+ }
+ .lb-lightbox-image {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+ border-radius: 8px;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+ transition: transform ${this.options.animationDuration}ms cubic-bezier(0.25, 0.1, 0.25, 1), opacity ${this.options.animationDuration}ms ease;
+ }
+ .lb-lightbox-nav {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ background-color: rgba(255, 255, 255, 0.8);
+ color: #333;
+ border: none;
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ font-size: 24px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ }
+ .lb-lightbox-nav:hover {
+ background-color: rgba(255, 255, 255, 1);
+ transform: translateY(-50%) scale(1.1);
+ }
+ .lb-lightbox-nav:active {
+ transform: translateY(-50%) scale(0.9);
+ }
+ .lb-lightbox-prev {
+ left: 20px;
+ }
+ .lb-lightbox-next {
+ right: 20px;
+ }
+ .lb-lightbox-close {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ background-color: rgba(255, 255, 255, 0.8);
+ color: #333;
+ border: none;
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ font-size: 24px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ }
+ .lb-lightbox-close:hover {
+ background-color: rgba(255, 255, 255, 1);
+ transform: scale(1.1);
+ }
+ .lb-lightbox-close:active {
+ transform: scale(0.9);
+ }
+ @media (max-width: 768px) {
+ .lb-lightbox-nav {
+ width: 40px;
+ height: 40px;
+ font-size: 20px;
+ }
+ .lb-lightbox-close {
+ width: 35px;
+ height: 35px;
+ font-size: 20px;
+ }
+ }
+ @media (prefers-color-scheme: dark) {
+ .lb-lightbox-overlay {
+ background-color: rgba(0, 0, 0, 0.9);
+ }
+ .lb-lightbox-nav,
+ .lb-lightbox-close {
+ background-color: rgba(50, 50, 50, 0.8);
+ color: #fff;
+ }
+ .lb-lightbox-nav:hover,
+ .lb-lightbox-close:hover {
+ background-color: rgba(70, 70, 70, 1);
+ }
+ .lb-lightbox-image {
+ box-shadow: 0 10px 30px rgba(255, 255, 255, 0.1);
+ }
+ }
+ `;
+ document.head.appendChild(style);
+ }
+
+ createLightbox() {
+ this.overlay = document.createElement('div');
+ this.overlay.className = 'lb-lightbox-overlay';
+ this.overlay.style.zIndex = '-1';
+
+ this.contentWrapper = document.createElement('div');
+ this.contentWrapper.className = 'lb-lightbox-content-wrapper';
+
+ this.container = document.createElement('div');
+ this.container.className = 'lb-lightbox-container';
+
+ this.image = document.createElement('img');
+ this.image.className = 'lb-lightbox-image';
+
+ this.prevButton = document.createElement('button');
+ this.prevButton.className = 'lb-lightbox-nav lb-lightbox-prev';
+ this.prevButton.innerHTML = '❮';
+
+ this.nextButton = document.createElement('button');
+ this.nextButton.className = 'lb-lightbox-nav lb-lightbox-next';
+ this.nextButton.innerHTML = '❯';
+
+ this.closeButton = document.createElement('button');
+ this.closeButton.className = 'lb-lightbox-close';
+ this.closeButton.innerHTML = '×';
+
+ this.container.appendChild(this.image);
+ this.contentWrapper.appendChild(this.container);
+ this.contentWrapper.appendChild(this.prevButton);
+ this.contentWrapper.appendChild(this.nextButton);
+ this.contentWrapper.appendChild(this.closeButton);
+
+ this.overlay.appendChild(this.contentWrapper);
+
+ document.body.appendChild(this.overlay);
+ }
+
+ bindEvents() {
+ document.addEventListener('click', this.handleImageClick.bind(this), true);
+ this.overlay.addEventListener('click', this.handleOverlayClick.bind(this));
+ this.prevButton.addEventListener('click', this.showPreviousImage.bind(this));
+ this.nextButton.addEventListener('click', this.showNextImage.bind(this));
+ this.closeButton.addEventListener('click', this.close.bind(this));
+ document.addEventListener('keydown', this.handleKeyDown.bind(this));
+ this.overlay.addEventListener('wheel', this.handleWheel.bind(this));
+ this.overlay.addEventListener('touchstart', this.handleTouchStart.bind(this));
+ this.overlay.addEventListener('touchmove', this.handleTouchMove.bind(this));
+ this.overlay.addEventListener('touchend', this.handleTouchEnd.bind(this));
+ }
+
+ handleImageClick(event) {
+ const clickedImage = event.target.closest('img');
+ if (clickedImage && !this.isOpen) {
+ event.preventDefault();
+ event.stopPropagation();
+ this.images = Array.from(document.querySelectorAll('.markdown-body img'));
+ this.currentIndex = this.images.indexOf(clickedImage);
+ this.open();
+ }
+ }
+
+ handleOverlayClick(event) {
+ if (event.target === this.overlay && this.options.closeOnOverlayClick) {
+ this.close();
+ } else if (!event.target.closest('.lb-lightbox-container')) {
+ const elementBelow = document.elementFromPoint(event.clientX, event.clientY);
+ if (elementBelow) {
+ elementBelow.click();
+ }
+ }
+ }
+
+ handleKeyDown(event) {
+ if (!this.isOpen) return;
+
+ switch (event.key) {
+ case 'ArrowLeft':
+ this.showPreviousImage();
+ break;
+ case 'ArrowRight':
+ this.showNextImage();
+ break;
+ case 'Escape':
+ this.close();
+ break;
+ }
+ }
+
+ handleWheel(event) {
+ event.preventDefault();
+ clearTimeout(this.wheelTimer);
+
+ this.wheelTimer = setTimeout(() => {
+ const delta = Math.sign(event.deltaY);
+ if (delta > 0) {
+ this.showNextImage();
+ } else {
+ this.showPreviousImage();
+ }
+ }, 50);
+ }
+
+ handleTouchStart(event) {
+ this.touchStartX = event.touches[0].clientX;
+ }
+
+ handleTouchMove(event) {
+ this.touchEndX = event.touches[0].clientX;
+ }
+
+ handleTouchEnd() {
+ const difference = this.touchStartX - this.touchEndX;
+ if (Math.abs(difference) > 50) {
+ if (difference > 0) {
+ this.showNextImage();
+ } else {
+ this.showPreviousImage();
+ }
+ }
+ }
+
+ open() {
+ this.isOpen = true;
+ this.overlay.style.zIndex = '10000';
+ this.overlay.classList.add('active');
+ this.showImage();
+ this.overlay.style.opacity = '1';
+ document.body.style.overflow = 'hidden';
+ if (typeof this.options.onOpen === 'function') {
+ this.options.onOpen();
+ }
+ }
+
+ close() {
+ this.isOpen = false;
+ this.overlay.style.opacity = '0';
+ this.overlay.classList.remove('active');
+ document.body.style.overflow = '';
+ setTimeout(() => {
+ this.image.style.transform = '';
+ this.zoomLevel = 1;
+ this.isZoomed = false;
+ this.overlay.style.zIndex = '-1';
+ }, this.options.animationDuration);
+ if (typeof this.options.onClose === 'function') {
+ this.options.onClose();
+ }
+ }
+
+ showPreviousImage() {
+ if (this.currentIndex > 0) {
+ this.currentIndex--;
+ this.showImage();
+ }
+ }
+
+ showNextImage() {
+ if (this.currentIndex < this.images.length - 1) {
+ this.currentIndex++;
+ this.showImage();
+ }
+ }
+
+ showImage() {
+ const imgSrc = this.images[this.currentIndex].src;
+ this.image.style.opacity = '0';
+
+ const newImage = new Image();
+ newImage.src = imgSrc;
+ newImage.onload = () => {
+ this.image.src = imgSrc;
+ this.image.style.opacity = '1';
+ };
+
+ this.prevButton.style.display = this.currentIndex > 0 ? '' : 'none';
+ this.nextButton.style.display = this.currentIndex < this.images.length - 1 ? '' : 'none';
+
+ if (typeof this.options.onNavigate === 'function') {
+ this.options.onNavigate(this.currentIndex);
+ }
+
+ this.preloadImages();
+ }
+
+ zoom(factor) {
+ this.zoomLevel += factor;
+ this.zoomLevel = Math.max(1, Math.min(this.zoomLevel, 3));
+ this.image.style.transform = `scale(${this.zoomLevel})`;
+ this.isZoomed = this.zoomLevel !== 1;
+ }
+
+ preloadImages() {
+ const preloadNext = (this.currentIndex + 1) % this.images.length;
+ const preloadPrev = (this.currentIndex - 1 + this.images.length) % this.images.length;
+ new Image().src = this.images[preloadNext].src;
+ new Image().src = this.images[preloadPrev].src;
+ }
+ }
+
+ // 将 Lightbox 类添加到全局对象
+ window.Lightbox = Lightbox;
+
+ // 自动初始化
+ document.addEventListener('DOMContentLoaded', () => {
+ new Lightbox();
+ });
+})();
diff --git a/static/assets/rain.js b/static/plugins/rain.js
similarity index 100%
rename from static/assets/rain.js
rename to static/plugins/rain.js