Greasy Fork

网页自定义截图工具

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

// ==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.org/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();
  }
})();