Generate Skeleton
// ==UserScript==
// @name SkeletonScript
// @namespace https://github.com/popring/vite-skeleton
// @version 2024-09-23
// @description Generate Skeleton
// @author popring
// @match *://*/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @license MIT
// ==/UserScript==
// 递归生成骨架图
function processElement(el, skeletonOverlay, bodyRect) {
const children = el.children;
if (children.length > 0) {
for (let i = 0; i < children.length; i++) {
processElement(children[i], skeletonOverlay, bodyRect);
}
} else {
const rect = el.getBoundingClientRect();
if (rect.width > 0 && rect.height > 0) {
const skeletonElement = document.createElement('div');
skeletonElement.className = 'skeleton-box';
skeletonElement.style.position = 'absolute';
skeletonElement.style.top = rect.top - bodyRect.top + 'px';
skeletonElement.style.left = rect.left - bodyRect.left + 'px';
skeletonElement.style.width = rect.width + 'px';
skeletonElement.style.height = rect.height + 'px';
skeletonOverlay.appendChild(skeletonElement);
}
}
}
// 覆盖页面并生成骨架图
function generateSkeleton() {
if (document.getElementById('skeleton-overlay')) return;
const skeletonOverlay = document.createElement('div');
skeletonOverlay.id = 'skeleton-overlay';
skeletonOverlay.style.position = 'fixed';
skeletonOverlay.style.top = 0;
skeletonOverlay.style.left = 0;
skeletonOverlay.style.width = '100%';
skeletonOverlay.style.height = '100%';
skeletonOverlay.style.zIndex = 9999;
skeletonOverlay.style.backgroundColor = 'rgba(255, 255, 255, 1)';
const bodyRect = document.body.getBoundingClientRect();
// 排除 <br> 标签
document
.querySelectorAll('div, p, h1, h2, h3, h4, h5, h6, a, img, span, em')
.forEach((el) => {
processElement(el, skeletonOverlay, bodyRect);
});
insertSkeletonStyles(skeletonOverlay);
document.body.appendChild(skeletonOverlay);
}
// 骨架图样式函数
function insertSkeletonStyles(skeletonOverlay) {
const skeletonStyles = `
.skeleton-box {
background-color: #f0f0f0;
animation: skeleton-loading 1.5s infinite;
border-radius: 4px;
}
@keyframes skeleton-loading {
0% {
background-color: #f0f0f0;
}
50% {
background-color: #e0e0e0;
}
100% {
background-color: #f0f0f0;
}
}
`;
const styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
styleSheet.innerHTML = skeletonStyles;
skeletonOverlay.appendChild(styleSheet);
}
// 切换骨架图的显示和隐藏
function toggleSkeleton() {
const skeletonOverlay = document.getElementById('skeleton-overlay');
if (skeletonOverlay) {
skeletonOverlay.style.display =
skeletonOverlay.style.display === 'none' ? 'block' : 'none';
} else {
generateSkeleton();
}
}
// 添加控制按钮
function addToggleButton() {
const button = document.createElement('button');
button.innerText = '切换骨架图显示';
button.style.position = 'fixed';
button.style.top = '10px';
button.style.right = '10px';
button.style.zIndex = 10000;
button.onclick = toggleSkeleton;
document.body.appendChild(button);
}
// 初始化函数,添加按钮
function init() {
addToggleButton();
}
// 将核心函数绑定到 window 对象上
window.generateSkeleton = generateSkeleton;
window.toggleSkeleton = toggleSkeleton;
// 初始化
init();