fixed: 修复友圈掉帧bug
This commit is contained in:
1 parent
904f9f40c4
commit
f09d6a7f71
1 file changed
+159
-16
@@ -49,11 +49,9 @@
|
|||||||
background-color 0.3s ease,
|
background-color 0.3s ease,
|
||||||
border-color 0.3s ease;
|
border-color 0.3s ease;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
overflow: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
animation: ukFadeInUp 0.6s cubic-bezier(0.165, 0.84, 0.44, 1) forwards;
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transform: translateZ(0); /* Enable GPU acceleration */
|
transform: translateZ(0); /* Enable GPU acceleration */
|
||||||
|
overflow: hidden; /* 防止背景图溢出 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.friend-circle-list a {
|
.friend-circle-list a {
|
||||||
@@ -110,17 +108,6 @@
|
|||||||
transition: all 0.15s ease;
|
transition: all 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes ukFadeInUp {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(40px) scale(0.95);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0) scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Top: Title */
|
/* Top: Title */
|
||||||
.fc-title {
|
.fc-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
@@ -305,8 +292,74 @@
|
|||||||
[data-theme="dark"] .artalk .atk-main-editor {
|
[data-theme="dark"] .artalk .atk-main-editor {
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Friend Circle Tooltip Card */
|
||||||
|
.fc-tooltip {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999;
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
width: 300px;
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95) translateY(10px);
|
||||||
|
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
display: none; /* Hidden by default */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-tooltip.is-visible {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1) translateY(0);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-tooltip-title {
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #000;
|
||||||
|
border-bottom: 1px solid rgba(0,0,0,0.05);
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-tooltip-content {
|
||||||
|
color: #555;
|
||||||
|
text-align: justify;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 6; /* Limit lines */
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .fc-tooltip {
|
||||||
|
background: rgba(35, 35, 35, 0.95);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .fc-tooltip-title {
|
||||||
|
color: #fff;
|
||||||
|
border-bottom-color: rgba(255,255,255,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .fc-tooltip-content {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<div id="fc-tooltip" class="fc-tooltip">
|
||||||
|
<div class="fc-tooltip-title"></div>
|
||||||
|
<div class="fc-tooltip-content"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// 使用全局对象管理友圈逻辑
|
// 使用全局对象管理友圈逻辑
|
||||||
window.FriendCircle = {
|
window.FriendCircle = {
|
||||||
@@ -334,10 +387,13 @@
|
|||||||
const dateStr = this.timeAgo(post.date);
|
const dateStr = this.timeAgo(post.date);
|
||||||
// 减少延迟时间,避免动画积压
|
// 减少延迟时间,避免动画积压
|
||||||
const delay = index * 0.05;
|
const delay = index * 0.05;
|
||||||
const bgImageSrc = post.image || post.avatar;
|
// 背景图固定使用头像,以获得一致的装饰效果
|
||||||
|
const bgImageSrc = post.avatar;
|
||||||
|
// Escape quotes for data attribute
|
||||||
|
const description = post.description ? post.description.replace(/"/g, '"') : '';
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<a href="${post.link}" target="_blank" class="fc-item" style="animation-delay: ${delay}s">
|
<a href="${post.link}" target="_blank" class="fc-item uk-animation-slide-bottom-small" style="animation-delay: ${delay}s" data-desc="${description}" data-title="${post.title}">
|
||||||
<div class="fc-title" title="${post.title}">${post.title}</div>
|
<div class="fc-title" title="${post.title}">${post.title}</div>
|
||||||
<img src="${bgImageSrc}" class="fc-bg-image" loading="lazy" onerror="this.style.opacity=0">
|
<img src="${bgImageSrc}" class="fc-bg-image" loading="lazy" onerror="this.style.opacity=0">
|
||||||
<div class="fc-bottom">
|
<div class="fc-bottom">
|
||||||
@@ -385,10 +441,97 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initTooltip: function() {
|
||||||
|
if (this.tooltipInitialized) return;
|
||||||
|
this.tooltipInitialized = true;
|
||||||
|
|
||||||
|
const tooltip = document.getElementById('fc-tooltip');
|
||||||
|
const titleEl = tooltip.querySelector('.fc-tooltip-title');
|
||||||
|
const contentEl = tooltip.querySelector('.fc-tooltip-content');
|
||||||
|
const container = document.getElementById('friend-circle-container');
|
||||||
|
|
||||||
|
if (!tooltip || !container) return;
|
||||||
|
|
||||||
|
// Move tooltip to body to prevent clipping by overflow:hidden or transforms
|
||||||
|
if (tooltip.parentNode !== document.body) {
|
||||||
|
document.body.appendChild(tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup tooltip when navigating away (PJAX)
|
||||||
|
const cleanup = () => {
|
||||||
|
if (tooltip && tooltip.parentNode === document.body) {
|
||||||
|
tooltip.remove();
|
||||||
|
}
|
||||||
|
document.removeEventListener('pjax:send', cleanup);
|
||||||
|
};
|
||||||
|
document.addEventListener('pjax:send', cleanup);
|
||||||
|
|
||||||
|
const updateTooltip = (e) => {
|
||||||
|
const item = e.target.closest('.fc-item');
|
||||||
|
if (item) {
|
||||||
|
const desc = item.getAttribute('data-desc');
|
||||||
|
const title = item.getAttribute('data-title');
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
titleEl.innerText = title;
|
||||||
|
contentEl.innerText = desc;
|
||||||
|
tooltip.classList.add('is-visible');
|
||||||
|
|
||||||
|
const tooltipWidth = tooltip.offsetWidth;
|
||||||
|
const tooltipHeight = tooltip.offsetHeight;
|
||||||
|
const winWidth = window.innerWidth;
|
||||||
|
const winHeight = window.innerHeight;
|
||||||
|
const gap = 15; // Gap between cursor and tooltip
|
||||||
|
|
||||||
|
let left = e.clientX + gap;
|
||||||
|
let top = e.clientY + gap;
|
||||||
|
|
||||||
|
// Horizontal Logic
|
||||||
|
if (left + tooltipWidth > winWidth - gap) {
|
||||||
|
// Flip to left
|
||||||
|
left = e.clientX - tooltipWidth - gap;
|
||||||
|
|
||||||
|
// If flipping makes it go off-screen to the left (e.g. wide tooltip, cursor near left)
|
||||||
|
if (left < gap) {
|
||||||
|
// Clamp to left edge
|
||||||
|
left = gap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical Logic
|
||||||
|
if (top + tooltipHeight > winHeight - gap) {
|
||||||
|
// Flip to top
|
||||||
|
top = e.clientY - tooltipHeight - gap;
|
||||||
|
|
||||||
|
// If flipping makes it go off-screen to the top
|
||||||
|
if (top < gap) {
|
||||||
|
// Clamp to top edge
|
||||||
|
top = gap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip.style.left = `${left}px`;
|
||||||
|
tooltip.style.top = `${top}px`;
|
||||||
|
} else {
|
||||||
|
tooltip.classList.remove('is-visible');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tooltip.classList.remove('is-visible');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
container.addEventListener('mousemove', updateTooltip);
|
||||||
|
container.addEventListener('mouseleave', () => {
|
||||||
|
tooltip.classList.remove('is-visible');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
const container = document.getElementById("friend-circle-container");
|
const container = document.getElementById("friend-circle-container");
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
|
this.initTooltip();
|
||||||
|
|
||||||
// 防止重复初始化导致掉帧
|
// 防止重复初始化导致掉帧
|
||||||
if (this.isFetching) return;
|
if (this.isFetching) return;
|
||||||
this.isFetching = true;
|
this.isFetching = true;
|
||||||
|
|||||||
Reference in new issue
Block a user