diff --git a/themes/Ying/assets/css/main.css b/themes/Ying/assets/css/main.css
index 0db1f704..3d72bd6f 100644
--- a/themes/Ying/assets/css/main.css
+++ b/themes/Ying/assets/css/main.css
@@ -45,32 +45,6 @@ html {
scroll-behavior: smooth;
}
-/* ── Theme switch transition ── */
-::view-transition-old(root),
-::view-transition-new(root) {
- animation-duration: 0.45s;
- animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-}
-
-::view-transition-old(root) {
- animation-name: theme-fade-out;
-}
-
-::view-transition-new(root) {
- animation-name: theme-fade-in;
- animation-delay: 0.04s;
-}
-
-@keyframes theme-fade-out {
- from { opacity: 1; }
- to { opacity: 0; }
-}
-
-@keyframes theme-fade-in {
- from { opacity: 0; }
- to { opacity: 1; }
-}
-
[data-theme="dark"] body {
color: var(--text-content-dark-color);
background-color: var(--background-dark-color);
@@ -4533,6 +4507,8 @@ img[atk-emoticon] {
/* --- Global Theme Transition --- */
body,
.main,
+body,
+.main,
.header,
.footer,
.post-content,
diff --git a/themes/Ying/assets/js/modules/floating-tools.js b/themes/Ying/assets/js/modules/floating-tools.js
index e6604022..06a10c81 100644
--- a/themes/Ying/assets/js/modules/floating-tools.js
+++ b/themes/Ying/assets/js/modules/floating-tools.js
@@ -123,20 +123,33 @@ window.initFloatingTools = function() {
};
updateIcon();
- themeToggle.addEventListener('click', function() {
+ themeToggle.addEventListener('click', function(e) {
var currentTheme = document.documentElement.getAttribute('data-theme');
var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
- document.documentElement.setAttribute('data-theme', newTheme);
- localStorage.setItem('theme', newTheme);
- updateIcon();
-
- // Trigger Artalk theme update
- if (window.artalk && typeof window.artalk.setDarkMode === 'function') {
- window.artalk.setDarkMode(newTheme === 'dark');
- }
- if (window.showToast) {
- window.showToast('已切换至 ' + (newTheme === 'dark' ? '深色' : '浅色') + '模式', 'success');
+ if (typeof themeSweep === 'function') {
+ var apply = function() {
+ document.documentElement.setAttribute('data-theme', newTheme);
+ localStorage.setItem('theme', newTheme);
+ updateIcon();
+ if (window.artalk && typeof window.artalk.setDarkMode === 'function') {
+ window.artalk.setDarkMode(newTheme === 'dark');
+ }
+ if (window.showToast) {
+ window.showToast('已切换至 ' + (newTheme === 'dark' ? '深色' : '浅色') + '模式', 'success');
+ }
+ };
+ themeSweep(newTheme, apply);
+ } else {
+ document.documentElement.setAttribute('data-theme', newTheme);
+ localStorage.setItem('theme', newTheme);
+ updateIcon();
+ if (window.artalk && typeof window.artalk.setDarkMode === 'function') {
+ window.artalk.setDarkMode(newTheme === 'dark');
+ }
+ if (window.showToast) {
+ window.showToast('已切换至 ' + (newTheme === 'dark' ? '深色' : '浅色') + '模式', 'success');
+ }
}
});
}
diff --git a/themes/Ying/assets/js/modules/utils.js b/themes/Ying/assets/js/modules/utils.js
index 17b96803..be88bb60 100644
--- a/themes/Ying/assets/js/modules/utils.js
+++ b/themes/Ying/assets/js/modules/utils.js
@@ -1,11 +1,50 @@
-// 判断是否为移动端
-window.isMobile = function() {
- if (window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
- return true; // 移动端
- } else {
- return false; // PC端
- }
-};
+// Scanner — page is blanked, beam paints the new theme back line by line
+function themeSweep(newTheme, callback) {
+ var isH = Math.random() < 0.5;
+ var w = window.innerWidth, h = window.innerHeight;
+
+ // Blank overlay: covers entire page with new-theme's dominant color
+ var blank = newTheme === 'dark' ? '#111827' : '#fcfaf5';
+ var sheet = document.createElement('div');
+ sheet.style.cssText =
+ 'position:fixed;inset:0;z-index:9999;' +
+ 'background:' + blank + ';' +
+ (isH
+ ? 'clip-path:inset(0 0 0 0);transition:clip-path 1.2s cubic-bezier(0.4,0,0.2,1);will-change:clip-path;'
+ : 'clip-path:inset(0 0 0 0);transition:clip-path 1.2s cubic-bezier(0.4,0,0.2,1);will-change:clip-path;');
+ document.body.appendChild(sheet);
+
+ // Thin scan beam at the leading edge
+ var beam = document.createElement('div');
+ beam.style.cssText =
+ 'position:fixed;z-index:10000;pointer-events:none;' +
+ 'background:rgba(255,255,255,0.7);' +
+ 'box-shadow:0 0 4px 1px rgba(255,255,255,0.35),0 0 12px 2px rgba(255,255,255,0.12);' +
+ 'transition:transform 1.2s cubic-bezier(0.4,0,0.2,1);will-change:transform;' +
+ (isH
+ ? 'top:0;right:0;width:1px;height:100%;transform:translateX(0);'
+ : 'bottom:0;left:0;height:1px;width:100%;transform:translateY(0);');
+
+ document.body.appendChild(beam);
+ sheet.offsetWidth;
+
+ // Switch theme immediately — sheet covers it, beam reveals
+ callback();
+
+ if (isH) {
+ sheet.style.clipPath = 'inset(0 0 0 100%)';
+ beam.style.transform = 'translateX(' + (-w) + 'px)';
+ } else {
+ sheet.style.clipPath = 'inset(100% 0 0 0)';
+ beam.style.transform = 'translateY(' + (-h) + 'px)';
+ }
+
+ beam.addEventListener('transitionend', function(e) {
+ if (e.propertyName !== 'transform') return;
+ if (sheet.parentNode) sheet.parentNode.removeChild(sheet);
+ if (beam.parentNode) beam.parentNode.removeChild(beam);
+ });
+}
// Toast Message Helper
window.showToast = function(text, type) {
@@ -21,13 +60,12 @@ window.showToast = function(text, type) {
// Theme Toggle Logic
window.initThemeToggle = function() {
- const avatar = document.getElementById('theme-toggle-avatar');
+ var avatar = document.getElementById('theme-toggle-avatar');
if (!avatar) return;
-
- // Remove existing listeners to avoid duplicates (if any)
- const newAvatar = avatar.cloneNode(true);
+
+ var newAvatar = avatar.cloneNode(true);
avatar.parentNode.replaceChild(newAvatar, avatar);
-
+
newAvatar.addEventListener('click', function(e) {
e.preventDefault();
@@ -38,49 +76,34 @@ window.initThemeToggle = function() {
var apply = function() {
html.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
-
window.showToast('已切换至 ' + (newTheme === 'dark' ? '深色' : '浅色') + '模式', 'success');
-
if (window.artalk && typeof window.artalk.setDarkMode === 'function') {
window.artalk.setDarkMode(newTheme === 'dark');
}
-
window.dispatchEvent(new Event('resize'));
};
- var isMobile = window.isMobile && window.isMobile();
-
- if (document.startViewTransition && !isMobile) {
- document.startViewTransition(function() { apply(); });
- } else {
- apply();
- }
+ themeSweep(newTheme, apply);
});
};
// Code Folding Logic
window.initCodeFold = function() {
- const codeBlocks = document.querySelectorAll('.highlight');
- codeBlocks.forEach(block => {
- // Check height (approx 300px)
+ var codeBlocks = document.querySelectorAll('.highlight');
+ codeBlocks.forEach(function(block) {
if (block.offsetHeight > 360) {
- // Check if already processed
if (block.parentNode.classList.contains('code-fold-container')) return;
-
- // Wrap
- const wrapper = document.createElement('div');
+
+ var wrapper = document.createElement('div');
wrapper.className = 'code-fold-container collapsed';
block.parentNode.insertBefore(wrapper, block);
wrapper.appendChild(block);
-
- // Add Button
- const btn = document.createElement('button');
+
+ var btn = document.createElement('button');
btn.className = 'code-expand-btn';
btn.innerHTML = ' 展开代码 ';
btn.onclick = function() {
wrapper.classList.remove('collapsed');
- // Hide button after expand, or change to collapse?
- // Usually just expand is enough.
btn.style.display = 'none';
};
wrapper.appendChild(btn);
@@ -90,62 +113,40 @@ window.initCodeFold = function() {
// Code Copy Logic
window.initCodeCopy = function() {
- // Target pre tags that contain code, or .highlight containers
- const codeBlocks = document.querySelectorAll('pre');
-
- codeBlocks.forEach(pre => {
- // Avoid double init
+ var codeBlocks = document.querySelectorAll('pre');
+
+ codeBlocks.forEach(function(pre) {
if (pre.parentNode.querySelector('.copy-code-btn')) return;
if (pre.querySelector('.copy-code-btn')) return;
-
- // Check if it's inside a highlight block (Hugo usually does .highlight > pre)
- // We attach button to the pre or the highlight container?
- // Attaching to pre is safer for positioning.
-
- const btn = document.createElement('button');
+
+ var btn = document.createElement('button');
btn.className = 'copy-code-btn';
btn.innerHTML = '';
btn.title = "复制代码";
- btn.style.cssText = `
- position: absolute;
- top: -6px;
- right: 5px;
- background: transparent;
- border: none;
- color: #888;
- cursor: pointer;
- padding: 5px;
- border-radius: 4px;
- transition: all 0.2s;
- opacity: 0;
- z-index: 10;
- `;
-
- // Show on hover
- pre.addEventListener('mouseenter', () => btn.style.opacity = '1');
- pre.addEventListener('mouseleave', () => btn.style.opacity = '0');
-
- // Handle touch devices
- if (window.isMobile()) {
- btn.style.opacity = '1';
- }
+ btn.style.cssText =
+ 'position:absolute;top:-6px;right:5px;background:transparent;border:none;' +
+ 'color:#888;cursor:pointer;padding:5px;border-radius:4px;' +
+ 'transition:all 0.2s;opacity:0;z-index:10;';
- btn.addEventListener('click', (e) => {
+ pre.addEventListener('mouseenter', function() { btn.style.opacity = '1'; });
+ pre.addEventListener('mouseleave', function() { btn.style.opacity = '0'; });
+
+ if (window.isMobile()) { btn.style.opacity = '1'; }
+
+ btn.addEventListener('click', function(e) {
e.stopPropagation();
- const code = pre.querySelector('code') ? pre.querySelector('code').innerText : pre.innerText;
-
+ var code = pre.querySelector('code') ? pre.querySelector('code').innerText : pre.innerText;
+
if (navigator.clipboard) {
- navigator.clipboard.writeText(code).then(() => {
+ navigator.clipboard.writeText(code).then(function() {
window.showToast('代码已复制 / Copied!', 'success');
btn.innerHTML = '';
- setTimeout(() => btn.innerHTML = '', 2000);
- }).catch(err => {
- console.error('Copy failed', err);
+ setTimeout(function() { btn.innerHTML = ''; }, 2000);
+ }).catch(function() {
window.showToast('复制失败 / Failed', 'error');
});
} else {
- // Fallback
- const textarea = document.createElement('textarea');
+ var textarea = document.createElement('textarea');
textarea.value = code;
document.body.appendChild(textarea);
textarea.select();
@@ -154,12 +155,11 @@ window.initCodeCopy = function() {
window.showToast('代码已复制 / Copied!', 'success');
}
});
-
- // Ensure relative positioning
+
if (getComputedStyle(pre).position === 'static') {
pre.style.position = 'relative';
}
-
+
pre.appendChild(btn);
});
};