改为CSS实现
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Chaturbate 缩略图放大 2 倍
|
// @name Chaturbate 缩略图放大 2 倍
|
||||||
// @namespace https://chaturbate.com/
|
// @namespace https://chaturbate.com/
|
||||||
// @version 0.1.1
|
// @version 0.2.6
|
||||||
// @description 将房间列表缩略图按宽高 2 倍放大
|
// @description 通过放大 grid 最小列宽来放大房间列表缩略图,保留原站填满行为
|
||||||
// @match https://chaturbate.com/*
|
// @match https://chaturbate.com/*
|
||||||
// @match https://*.chaturbate.com/*
|
// @match https://*.chaturbate.com/*
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
@@ -13,173 +13,53 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// ========== 配置项 ==========
|
// ========== 配置项 ==========
|
||||||
// 放大倍数(宽度和高度都会按此倍数放大)
|
// 最小列宽倍数(原站约 174px / 180px,乘以该倍数后作为新的 minmax 最小值,1fr 仍填满整行)
|
||||||
const SCALE = 1.5;
|
const SCALE = 1.3;
|
||||||
|
|
||||||
// 调试开关(true: 输出调试信息,false: 静默运行)
|
|
||||||
const DEBUG = false;
|
|
||||||
// ===========================
|
// ===========================
|
||||||
|
|
||||||
// ========== 内部常量 ==========
|
const MIN_COL_MAIN = 174; // #main 下的 min
|
||||||
const SCALED_ATTR = "data-tm-scaled";
|
const MIN_COL_ROOT = 180; // #roomlist_root、频道页下方(180×101) 的 min
|
||||||
const BASE_W_ATTR = "data-tm-base-w";
|
const minMain = Math.round(MIN_COL_MAIN * SCALE);
|
||||||
const BASE_H_ATTR = "data-tm-base-h";
|
const minRoot = Math.round(MIN_COL_ROOT * SCALE);
|
||||||
// ===========================
|
|
||||||
|
|
||||||
// 提前注入 CSS,避免闪烁
|
|
||||||
const injectCSS = () => {
|
|
||||||
const style = document.createElement("style");
|
const style = document.createElement("style");
|
||||||
style.id = "tm-thumb-scale-style";
|
style.id = "tm-thumb-scale-style";
|
||||||
const css = `
|
style.textContent = `
|
||||||
img.room_thumbnail:not([${SCALED_ATTR}="1"]) {
|
#main #roomlist_root .roomlist_container ul.list,
|
||||||
opacity: 0;
|
#main #roomlist_root .placeholder_roomlist_container ul.list {
|
||||||
transition: opacity 0.1s;
|
grid-template-columns: repeat(auto-fill, minmax(${minMain}px, 1fr)) !important;
|
||||||
}
|
}
|
||||||
img.room_thumbnail[${SCALED_ATTR}="1"] {
|
#roomlist_root .roomlist_container ul.list,
|
||||||
opacity: 1;
|
#roomlist_root .placeholder_roomlist_container ul.list {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(${minRoot}px, 1fr)) !important;
|
||||||
}
|
}
|
||||||
ul.list,
|
/* 频道页下方:列表在 .BaseRoomContents 内,统一用该祖先即可 */
|
||||||
ul.list.endless_page_template {
|
.BaseRoomContents ul.list {
|
||||||
display: flex !important;
|
display: grid !important;
|
||||||
flex-wrap: wrap !important;
|
grid-gap: 0.6em 0.75em !important;
|
||||||
gap: 0 !important;
|
grid-template-columns: repeat(auto-fill, minmax(${minRoot}px, 1fr)) !important;
|
||||||
|
}
|
||||||
|
.BaseRoomContents ul.list li {
|
||||||
|
width: auto !important;
|
||||||
|
max-width: none !important;
|
||||||
|
max-height: none !important;
|
||||||
|
}
|
||||||
|
.BaseRoomContents ul.list .room_thumbnail_container {
|
||||||
|
display: block !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.BaseRoomContents ul.list .room_thumbnail_container img {
|
||||||
|
width: 100% !important;
|
||||||
|
height: auto !important;
|
||||||
|
display: block !important;
|
||||||
|
max-width: none !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
style.textContent = css;
|
|
||||||
const inject = () => {
|
const inject = () => {
|
||||||
if (!document.getElementById("tm-thumb-scale-style")) {
|
if (!document.getElementById("tm-thumb-scale-style"))
|
||||||
(document.head || document.documentElement).appendChild(style);
|
(document.head || document.documentElement).appendChild(style);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if (document.head) {
|
if (document.head) inject();
|
||||||
inject();
|
else document.addEventListener("DOMContentLoaded", inject);
|
||||||
} else {
|
|
||||||
document.addEventListener("DOMContentLoaded", inject);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
injectCSS();
|
|
||||||
|
|
||||||
const relaxKnownOuter = () => {
|
|
||||||
// 确保列表容器能容纳更大的卡片
|
|
||||||
document.querySelectorAll("ul.list, ul.list.endless_page_template").forEach((el) => {
|
|
||||||
el.style.width = "100%";
|
|
||||||
el.style.maxWidth = "none";
|
|
||||||
el.style.boxSizing = "border-box";
|
|
||||||
el.style.overflow = "visible";
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const scale = () => {
|
|
||||||
if (DEBUG) console.log("[tm] running on", location.href);
|
|
||||||
relaxKnownOuter();
|
|
||||||
const items = document.querySelectorAll("a.room_thumbnail_container");
|
|
||||||
if (DEBUG) console.log("[tm] containers:", items.length);
|
|
||||||
items.forEach((container) => {
|
|
||||||
const img = container.querySelector("img.room_thumbnail");
|
|
||||||
if (DEBUG && !img) console.log("[tm] no img in container", container);
|
|
||||||
if (!img) return;
|
|
||||||
|
|
||||||
const attrW = parseFloat(img.getAttribute("width"));
|
|
||||||
const attrH = parseFloat(img.getAttribute("height"));
|
|
||||||
const baseW = parseFloat(img.getAttribute(BASE_W_ATTR)) || attrW;
|
|
||||||
const baseH = parseFloat(img.getAttribute(BASE_H_ATTR)) || attrH;
|
|
||||||
if (!baseW || !baseH) return;
|
|
||||||
|
|
||||||
if (!img.getAttribute(BASE_W_ATTR) || !img.getAttribute(BASE_H_ATTR)) {
|
|
||||||
img.setAttribute(BASE_W_ATTR, String(baseW));
|
|
||||||
img.setAttribute(BASE_H_ATTR, String(baseH));
|
|
||||||
}
|
|
||||||
|
|
||||||
const scaledW = baseW * SCALE;
|
|
||||||
const scaledH = baseH * SCALE;
|
|
||||||
if (DEBUG) console.log("[tm] img size:", baseW, baseH, img);
|
|
||||||
|
|
||||||
img.setAttribute("width", String(scaledW));
|
|
||||||
img.setAttribute("height", String(scaledH));
|
|
||||||
img.setAttribute(SCALED_ATTR, "1");
|
|
||||||
img.style.width = `${scaledW}px`;
|
|
||||||
img.style.height = `${scaledH}px`;
|
|
||||||
img.style.maxWidth = "none";
|
|
||||||
img.style.maxHeight = "none";
|
|
||||||
img.style.display = "block";
|
|
||||||
img.style.opacity = "1";
|
|
||||||
|
|
||||||
container.style.width = `${scaledW}px`;
|
|
||||||
container.style.height = `${scaledH}px`;
|
|
||||||
container.style.minWidth = `${scaledW}px`;
|
|
||||||
container.style.maxWidth = `${scaledW}px`;
|
|
||||||
container.style.minHeight = `${scaledH}px`;
|
|
||||||
container.style.overflow = "visible";
|
|
||||||
container.style.display = "block";
|
|
||||||
container.style.boxSizing = "border-box";
|
|
||||||
container.style.flexShrink = "0";
|
|
||||||
|
|
||||||
const card = container.closest("li.roomCard");
|
|
||||||
if (card) {
|
|
||||||
card.style.width = `${scaledW}px`;
|
|
||||||
card.style.minWidth = `${scaledW}px`;
|
|
||||||
card.style.maxWidth = `${scaledW}px`;
|
|
||||||
card.style.minHeight = `${scaledH}px`;
|
|
||||||
card.style.height = "auto";
|
|
||||||
card.style.overflow = "visible";
|
|
||||||
card.style.flexShrink = "0";
|
|
||||||
card.style.flexGrow = "0";
|
|
||||||
card.style.flexBasis = `${scaledW}px`;
|
|
||||||
card.style.boxSizing = "border-box";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const init = () => {
|
|
||||||
if (DEBUG) {
|
|
||||||
const thumbs = document.querySelectorAll("img.room_thumbnail");
|
|
||||||
console.log("[tm] thumbnails:", thumbs.length, Array.from(thumbs));
|
|
||||||
}
|
|
||||||
scale();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 立即执行(如果 DOM 已就绪)
|
|
||||||
if (document.readyState === "loading") {
|
|
||||||
document.addEventListener("DOMContentLoaded", init);
|
|
||||||
} else {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 延迟重试,处理动态加载
|
|
||||||
window.setTimeout(scale, 100);
|
|
||||||
window.setTimeout(scale, 300);
|
|
||||||
window.setTimeout(scale, 600);
|
|
||||||
window.setTimeout(scale, 1000);
|
|
||||||
window.setTimeout(scale, 2000);
|
|
||||||
|
|
||||||
// MutationObserver 监听动态添加的内容
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
|
||||||
for (const mutation of mutations) {
|
|
||||||
for (const node of mutation.addedNodes) {
|
|
||||||
if (node.nodeType === 1 && (
|
|
||||||
node.matches?.("a.room_thumbnail_container, li.roomCard") ||
|
|
||||||
node.querySelector?.("a.room_thumbnail_container")
|
|
||||||
)) {
|
|
||||||
if (DEBUG) console.log("[tm] new content detected, scaling...");
|
|
||||||
scale();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 开始观察
|
|
||||||
const startObserving = () => {
|
|
||||||
const target = document.body || document.documentElement;
|
|
||||||
if (target) {
|
|
||||||
observer.observe(target, { childList: true, subtree: true });
|
|
||||||
if (DEBUG) console.log("[tm] MutationObserver started");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (document.body) {
|
|
||||||
startObserving();
|
|
||||||
} else {
|
|
||||||
document.addEventListener("DOMContentLoaded", startObserving);
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user