Greasy Fork

Greasy Fork is available in English.

网页自定义截图工具

根据页面中的id或者class使用html2canvas-pro实现网页长截图,支持多元素拼接

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         网页自定义截图工具
// @namespace    https://github.com/2019-02-18
// @version      0.1
// @description  根据页面中的id或者class使用html2canvas-pro实现网页长截图,支持多元素拼接
// @author       2019-02-18
// @match        *://*/*
// @grant        none
// @license MIT
// @require https://update.greasyfork.icu/scripts/457525/1134363/html2canvas%20141.js
// ==/UserScript==

(function() {
  'use strict';

  // 创建控制面板
  const panel = document.createElement('div');
  panel.style.cssText = 'position:fixed;top:10px;right:10px;z-index:9999;background:#fff;padding:10px;border:1px solid #ccc;';
  
  // 创建输入框
  const input = document.createElement('textarea');
  input.placeholder = '输入目标元素的id或class,多个元素用逗号分隔';
  input.style.marginRight = '10px';
  input.style.width = '200px';
  input.style.height = '60px';
  
  // 创建截图按钮
  const button = document.createElement('button');
  button.textContent = '截图';
  button.style.display = 'block';
  button.style.marginTop = '5px';
  
  // 创建单元素截图按钮
  const singleButton = document.createElement('button');
  singleButton.textContent = '单元素截图';
  singleButton.style.display = 'block';
  singleButton.style.marginTop = '5px';
  
  // 添加元素到面板
  panel.appendChild(input);
  panel.appendChild(singleButton);
  panel.appendChild(button);
  document.body.appendChild(panel);

  // 单元素截图功能
  singleButton.addEventListener('click', async () => {
      const selector = input.value.trim();
      if (!selector) {
          alert('请输入选择器');
          return;
      }
      
      let target;
      
      // 查找目标元素
      if (selector.startsWith('#')) {
          target = document.getElementById(selector.slice(1));
      } else if (selector.startsWith('.')) {
          target = document.querySelector(selector);
      } else {
          alert('请输入正确的id或class选择器(以#或.开头)');
          return;
      }

      if (!target) {
          alert('未找到目标元素');
          return;
      }

      try {
          await captureAndDownload([target]);
      } catch (error) {
          console.error('截图失败:', error);
          alert('截图失败,请检查控制台获取详细信息');
      }
  });

  // 多元素拼接截图功能
  button.addEventListener('click', async () => {
      const selectors = input.value.split(',').map(s => s.trim()).filter(s => s);
      
      if (selectors.length === 0) {
          alert('请输入至少一个选择器');
          return;
      }
      
      const targets = [];
      
      // 查找所有目标元素
      for (const selector of selectors) {
          let target;
          
          if (selector.startsWith('#')) {
              target = document.getElementById(selector.slice(1));
          } else if (selector.startsWith('.')) {
              target = document.querySelector(selector);
          } else {
              alert(`请输入正确的id或class选择器(以#或.开头): ${selector}`);
              return;
          }
          
          if (!target) {
              alert(`未找到目标元素: ${selector}`);
              return;
          }
          
          targets.push(target);
      }

      try {
          await captureAndDownload(targets);
      } catch (error) {
          console.error('截图失败:', error);
          alert('截图失败,请检查控制台获取详细信息');
      }
  });
  
  // 截图并下载函数
  async function captureAndDownload(elements) {
      if (!elements || elements.length === 0) return;
      
      // 如果只有一个元素,直接截图并下载
      if (elements.length === 1) {
          const canvas = await html2canvas(elements[0], {
              useCORS: true,
              scrollX: 0,
              scrollY: 0,
              windowWidth: document.documentElement.offsetWidth,
              windowHeight: document.documentElement.offsetHeight,
              scale: window.devicePixelRatio
          });
          
          downloadImage(canvas);
          return;
      }
      
      // 多个元素,需要拼接
      const canvases = [];
      let totalHeight = 0;
      let maxWidth = 0;
      
      // 先截取所有元素
      for (const element of elements) {
          const canvas = await html2canvas(element, {
              useCORS: true,
              scrollX: 0,
              scrollY: 0,
              windowWidth: document.documentElement.offsetWidth,
              windowHeight: document.documentElement.offsetHeight,
              scale: window.devicePixelRatio
          });
          
          canvases.push(canvas);
          totalHeight += canvas.height;
          maxWidth = Math.max(maxWidth, canvas.width);
      }
      
      // 创建新画布并拼接
      const finalCanvas = document.createElement('canvas');
      finalCanvas.width = maxWidth;
      finalCanvas.height = totalHeight;
      
      const ctx = finalCanvas.getContext('2d');
      let currentY = 0;
      
      // 将每个画布绘制到最终画布上
      for (const canvas of canvases) {
          // 居中绘制
          const x = (maxWidth - canvas.width) / 2;
          ctx.drawImage(canvas, x, currentY);
          currentY += canvas.height;
      }
      
      // 下载拼接后的图片
      downloadImage(finalCanvas);
  }
  
  // 下载图片函数
  function downloadImage(canvas) {
      const image = canvas.toDataURL('image/png');
      const link = document.createElement('a');
      //文件名称使用当前日期加页面标题
      let date = new Date();
      let year = date.getFullYear();
      let month = (date.getMonth() + 1).toString().padStart(2, '0');
      let day = date.getDate().toString().padStart(2, '0');
      let filename = year + '-' + month + '-' + day + '-' + document.title + '.png';
      link.download = filename;
      link.href = image;
      link.click();
  }
})();