Greasy Fork

Greasy Fork is available in English.

图片打包下载工具

简单纯洁的网页图片打包下载小工具、图片打包、A tool that helps you quickly capture web images and package them for download

当前为 2024-05-11 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         图片打包下载工具
// @namespace    http://tampermonkey.net/
// @description  简单纯洁的网页图片打包下载小工具、图片打包、A tool that helps you quickly capture web images and package them for download
// @description:zh-CN  一个帮你快速捕获网页图片并打包下载的工具
// @author       <[email protected]>
// @version      v2.2.0
// @license      GPLv3
// @icon         https://s21.ax1x.com/2024/04/16/pFxNgjH.jpg
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// @grant        GM_xmlhttpRequest
// @match        *://*/*

// ==/UserScript==

let btnStyle = `
    border: 1px solid #ccc;
    border-radius: 5px;
    background-color: #fff;
    cursor: pointer;
    height: 40px;
    width: 90px;
    border-radius: 6px;
    background: #333;
    justify-content: center;
    align-items: center;
    font-family: 'Damion', cursive;
    cursor: pointer;
    border: none;
    font-size: 14px;
    transition: 500ms;
    color: rgb(161, 161, 161);
    box-shadow: 0 0 5px #444, 5px 5px 15px #222, inset 5px 5px 10px #444,inset -5px -5px 10px #222;
`;
let divStyle = `
    padding: 20px 10px 20px 20px;
    position: fixed;
    right: 0;
    bottom: 10px;
    z-index: 99999;
    transition: 500ms;
`;
var lock = true;
const handleDownload = () => {
  let imageUrls = [];
  document.querySelectorAll("img").forEach((item) => {
    if (!item.src) return;
    imageUrls.push(item.src);
  });
  const zip = new JSZip();
  lock = false;
  Promise.all(
    imageUrls.map((url, index) => {
      return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
          method: "GET",
          url: url,
          responseType: "blob",
          onload: function (response) {
            if (response.status === 200) {
              let blob = response.response;
              const filename = `image${index + 1}.jpg`;
              zip.file(filename, blob, { binary: true });
            } else {
              console.error("Request failed with status " + response.status);
            }
            resolve();
          },
          onerror: function (e) {
            console.error("Request failed: " + e.message);
            resolve();
          },
        });
      });
    })
  )
    .then(() => {
      zip.generateAsync({ type: "blob" }).then((blob) => {
        saveAs(blob, "images.zip");
      });
      unlock();
    })
    .catch((error) => {
      unlock();
      console.error("Error downloading images:", error);
    });
};
const unlock = (delay = 3000) => {
  setTimeout(() => {
    lock = true;
  }, delay);
};
const createEle = () => {
  let div = document.createElement("div");
  div.style.cssText = divStyle;
  div.setAttribute("id", "ccc_load_container");
  function hoverOn() {
    div.style.cssText = `
            ${divStyle}
            right: 0;
        `;
  }
  function hoverOff() {
    div.style.cssText = `
        ${divStyle}
                right: -92px;
            `;
  }
  setTimeout(() => {
    hoverOff();
  }, 1000);
  div.addEventListener("mouseover", hoverOn);
  div.addEventListener("mouseout", hoverOff);
  $(div).append(`
        <button style="${btnStyle}">下载图片</button>
    `);
  document.body.appendChild(div);
  $("#ccc_load_container > button").click(() => {
    lock && handleDownload();
  });
};

function getImageFileNameFromUrl(url) {
  // 匹配最后一个斜杠('/')之后的任何字符,直到遇到查询参数或文件扩展名的结束
  const regex = /([^\/?#]+)(?=\.[\w]+($|[?#]))|([^\/?#]+)$/;
  const matches = url.match(regex);

  // 如果找到匹配项,则返回第一个匹配的文件名(可能包括文件扩展名)
  return matches ? matches[0] : null;
}

function downloadImageData(imgSrc, imgAlt = "default") {
  let a = document.createElement("a");
  a.href = imgSrc;
  a.download = imgAlt || "image.png"; // 设置下载的图片名
  a.style.display = "none";
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

function downloadImage(imageUrl, imageName = "image.png") {
  fetch(imageUrl)
    .then((response) => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.blob(); // 或者 response.arrayBuffer()
    })
    .then((blob) => {
      // 创建一个Blob URL
      const url = window.URL.createObjectURL(blob);

      // 创建一个<a>标签用于下载
      const a = document.createElement("a");
      a.href = url;
      a.download = imageName; // 设置下载的文件名
      a.style.display = "none";

      // 触发点击事件
      document.body.appendChild(a);
      a.click();

      // 释放URL对象
      window.URL.revokeObjectURL(url);

      // 清理<a>标签
      document.body.removeChild(a);
    })
    .catch((error) => {
      console.error(
        "There has been a problem with your fetch operation:",
        error
      );
    });
}

const initBindEvent = () => {
  document.addEventListener("mousedown", function (event) {
    // 检查是否同时按下了Ctrl键和鼠标右键
    if (event.ctrlKey && event.button === 2) {
      // 阻止右键点击的默认事件(打开上下文菜单)
      event.preventDefault();

      console.log(" 打印选中 ", event);

      // 假设我们有一个ID为'targetElement'的元素要选中
      var targetElement = event.target;
      if (targetElement) {
        // 选中元素,例如改变其背景色
        // targetElement.style.boxShadow = '0 0 10px rgba(255, 0, 0, 0.7)';

        let url = targetElement.getAttribute("src");

        if (url.includes("data:image/")) {
          downloadImageData(url);
          console.log("ssssss ");
        } else {
          const fileName = getImageFileNameFromUrl(url);
          downloadImage(url, fileName);
        }
      }
    }
  });
};

// 初始加载样式
const loadStyle = () => {
  // 创建一个新的style元素
  var style = document.createElement("style");

  // 将CSS样式内容设置为style元素的文本内容
  if (style.styleSheet) {
    // 对于老版本的IE浏览器
    style.styleSheet.cssText = cssContent;
  } else {
    // 对于其他浏览器
    style.appendChild(document.createTextNode(cssContent));
  }
  // 将style元素添加到head中
  var head = document.head || document.getElementsByTagName("head")[0];
  head.appendChild(style);
};
var cssContent = `

#flashing-div {
    opacity: 1;
    transition: opacity 0.8s ease-in-out, transform 0.8s ease-in-out;
    animation: flashAndScale 2.5s infinite; /* 初始状态设置为无限循环,稍后通过JavaScript控制 */
    visibility: visible; /* 初始状态为可见 */
  }
  @keyframes flashAndScale {
    0% {
      opacity: 0.9;
      transform: scale(0.9);
    }
    25% {
      opacity: 1;
      transform: scale(1);
    }
    50% {
      opacity: 0.9;
      transform: scale(0.9);
    }
    75% {
      opacity: 1;
      transform: scale(1);
    }
    100% {
      opacity: 0.9;
      transform: scale(0.9);
      visibility: hidden; /* 在动画结束时隐藏div */
    }
  }
  /* 添加一个类来停止动画并隐藏div(如果需要的话) */
  #flashing-div.stopped {
    animation: none;
    visibility: hidden;
    opacity: 0;
    transform: scale(0);
    transition: none;
  }


`;
const initTip = () => {
  loadStyle();

  let tip = document.createElement("div");
  tip.style.cssText = `
        position: fixed;
        top: 5vh;
        left: 50%;
        transform: translate(-50%, 0);
        background-color: rgba(0, 0, 0, 0.8);
        display: flex;
        justify-content: center;
       align-items: center;
       color: #ffffff;
       z-index: 999999;
       padding: 10px 20px;
       border-radius: 10px;
       text-align: center;
       letter-spacing: 1.5px;
    `;

  tip.innerText = "Ctrl + 🖱️鼠标右键 \n (下载选中图片~)";
  tip.setAttribute("id", "flashing-div");
  setTimeout(() => {
    tip.classList.add("stopped");
  }, 3500);

  document.body.appendChild(tip);
};

const init = () => {
  window.addEventListener("load", function () {
    if (window.self !== window.top) return;
    createEle();
    initBindEvent();
    setTimeout(() => {
      initTip();
    }, 1000);
  });
};
(function () {
  init();
})();