Created
July 17, 2024 07:23
-
-
Save ricky9w/bcae71989c79d11d08dad691d0a2db36 to your computer and use it in GitHub Desktop.
Create a long screenshot of all elements in a scrollable container
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Long Screenshot Creator for Scrollable Container | |
// @namespace https://rikko.top | |
// @version 0.1 | |
// @description Create a long screenshot of all elements in a scrollable container | |
// @author ricky9w | |
// @email [email protected] | |
// @match https://*/* | |
// @grant none | |
// @require https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
// 创建一个按钮来触发截图 | |
const button = document.createElement('button'); | |
button.textContent = '创建长截图'; | |
button.style.position = 'fixed'; | |
button.style.top = '10px'; | |
button.style.right = '10px'; | |
button.style.zIndex = '9999'; | |
document.body.appendChild(button); | |
button.addEventListener('click', createLongScreenshot); | |
async function createLongScreenshot() { | |
// 假设可滚动容器的选择器是 '.scrollable-container' | |
const scrollableContainer = document.querySelector('div.scroller---esn7'); | |
if (!scrollableContainer) { | |
alert('找不到可滚动容器'); | |
return; | |
} | |
const targetElements = []; | |
let lastScrollHeight = -1; | |
while (scrollableContainer.scrollTop < scrollableContainer.scrollHeight) { | |
// 检查是否到达底部 | |
if (lastScrollHeight === scrollableContainer.scrollHeight) { | |
break; | |
} | |
lastScrollHeight = scrollableContainer.scrollHeight; | |
// 获取当前可见的目标元素 | |
const visibleElements = Array.from(scrollableContainer.querySelectorAll('div.drag-wrapper---smTQ')) | |
.filter(el => isElementVisible(el, scrollableContainer)); | |
targetElements.push(...visibleElements); | |
// 滚动容器 | |
scrollableContainer.scrollTop += scrollableContainer.clientHeight; | |
// 等待一段时间,以便新内容加载(如果有的话) | |
await new Promise(resolve => setTimeout(resolve, 1000)); | |
} | |
// 重置滚动位置 | |
scrollableContainer.scrollTop = 0; | |
// 创建一个新的容器来存放所有元素 | |
const container = document.createElement('div'); | |
container.style.position = 'absolute'; | |
container.style.left = '-9999px'; | |
container.style.width = scrollableContainer.clientWidth + 'px'; | |
// 复制所有相关的样式表 | |
document.querySelectorAll('style, link[rel="stylesheet"]').forEach(styleSheet => { | |
container.appendChild(styleSheet.cloneNode(true)); | |
}); | |
// 将所有元素的克隆添加到新容器中 | |
targetElements.forEach(element => { | |
const clone = element.cloneNode(true); | |
preserveComputedStyles(element, clone); | |
container.appendChild(clone); | |
}); | |
// 将容器添加到文档中 | |
document.body.appendChild(container); | |
// 使用 html2canvas 创建截图 | |
html2canvas(container, { | |
allowTaint: true, | |
useCORS: true, | |
scale: 2 // 提高分辨率 | |
}).then(canvas => { | |
// 将 canvas 转换为图片 URL | |
const imgData = canvas.toDataURL('image/png'); | |
// 创建下载链接 | |
const link = document.createElement('a'); | |
link.href = imgData; | |
link.download = 'long_screenshot.png'; | |
link.click(); | |
// 清理:移除临时容器 | |
document.body.removeChild(container); | |
}); | |
} | |
function isElementVisible(el, container) { | |
const { top, bottom } = el.getBoundingClientRect(); | |
const containerRect = container.getBoundingClientRect(); | |
return top < containerRect.bottom && bottom > containerRect.top; | |
} | |
function preserveComputedStyles(sourceElement, targetElement) { | |
const computedStyle = window.getComputedStyle(sourceElement); | |
for (const property of computedStyle) { | |
targetElement.style[property] = computedStyle.getPropertyValue(property); | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment