// ==UserScript== // @name 图片下载 | 页面所有图片打包下载 | 单个图片下载 // @namespace http://tampermonkey.net/ // @description 简单纯洁的网页图片下载小工具、图片打包、可打包页面上所有图片下载、可单选(Ctrl+鼠标右键)下载单个图片、 { 功能: 1.打包所有下载 2.Ctrl+鼠标右键,下载单个 }、A tool that helps you quickly capture web images and package them for download // @description:zh-CN 一个帮你快速捕获网页图片并打包下载、也可单选下载的小工具🔧 // @author // @version v3.0 // @license GPLv3 // @icon https://s21.ax1x.com/2024/05/14/pkmNM0s.png // @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 *://*/* // @downloadURL none // ==/UserScript== var btnStyle = ` background-color: #fff; width: 90px; padding: 8px 0; border-radius: 6px; background: #333; justify-content: center; align-items: center; font-family: 'Damion', cursive; border: none; font-size: 14px; cursor: inherit; transition: 500ms; color: #eeeeee; box-shadow: 0 0 5px #444, 5px 5px 15px #222, inset 5px 5px 10px #444,inset -5px -5px 10px #222; `; var btn_text_style = ` margin: 0; padding: 0; font-size: 14px; ` var load_tip_style = ` position: fixed; width: 210px; padding: 12px; top: 20px; right: -220px; color: #333; background-color: #fff; box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 10px 5px; border-radius: 5px; transition: all 0.5s ease-in-out 0s, transform 0.5s ease-in-out 0s; font-family: 'Damion', cursive; font-weight: 600; z-index: 9999; ` var cssContent = ` #ccc_load_container{ padding: 20px 10px 20px 20px; position: fixed; bottom: 10px; right: -92px; z-index: 99999; transition: 0.5s ease-in-out; cursor: pointer; } #ccc_load_container:hover{ right: 0; } #flashing-div { opacity: 1; transition: all 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; box-shadow: 0px 0px 8px 4px rgba(0, 0, 0, 0.5); } 25% { opacity: 1; box-shadow: none; box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.5); } 50% { opacity: 0.9; box-shadow: 0px 0px 8px 4px rgba(0, 0, 0, 0.5); } 75% { opacity: 1; box-shadow: none; box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.5); } 100% { opacity: 0.9; box-shadow: 0px 0px 8px 4px rgba(0, 0, 0, 0.5); } } /* 添加一个类来停止动画并隐藏div(如果需要的话) */ #flashing-div.stopped { animation: none; visibility: hidden; opacity: 0; transform: scale(0); transition: none; } `; // -------全局------------- var lock = true; // 防止事件重复调用 var allLoadDOM = null; // 按钮容器-打包下载所有 var LoadTipDOM = null; // 下载提示框 // -------------------- // 初始加载样式 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); } /** * 传入配置信息创建元素并返回DOM对象 * @param {* * option { el:元素, text: 元素文本, className: 类名, prop:属性 } * mountE: 挂载元素 * } * @returns 创建元素 */ const myCreateEle = (option, mountE) => { let e = document.createElement(option.el || 'div') option.className && e.classList.add(option.className) for (let p in (option.prop || {})) { e.setAttribute(p, option.prop[p]) } e.innerText = option.text || '' e.style.cssText = option.style || '' mountE && mountE.appendChild(e) return e } // 创建下载提示框 const createLoadTip = () => { LoadTipDOM = myCreateEle({ el: 'div', style: `${load_tip_style}`, text: '稍等片刻,正在打包下载...' }, document.body) } // 打包下载所有图片事件 const handleDownload = () => { let imageUrls = []; document.querySelectorAll("img").forEach((item) => { let src = item?.src if (!src) return; imageUrls.push({ src, imgName: getImageFileNameFromUrl(src) + getImageExtension(src) }); }); console.log('触发点击 ~ imageUrls= ', imageUrls); if (!imageUrls.length) return const zip = new JSZip(); lock = false; !LoadTipDOM && createLoadTip() LoadTipDOM.style.right = '20px' Promise.all( imageUrls.map((item, index) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: item.src, responseType: "blob", onload: function (response) { if (response.status === 200) { let blob = response.response; const filename = item.imgName 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(() => { let domain = window.location.href.replace(/^https?:\/\//i, ''); zip.generateAsync({ type: "blob" }).then((blob) => { saveAs(blob, `【${document.title}】【${domain}】.zip`); unlock(); }); }) .catch((error) => { unlock(); console.error("Error downloading images:", error); }); }; const unlock = (delay = 500) => { setTimeout(() => { lock = true; allLoadDOM.style.cursor = 'pointer' LoadTipDOM.style.right = '-220px' }, delay); }; const createEle = () => { allLoadDOM = document.createElement("div"); allLoadDOM.setAttribute("id", "ccc_load_container"); if(!localStorage.getItem('IS_IMAGE_DOWNLOAD_TIP')){ allLoadDOM.style.right = '0'; setTimeout(() => { allLoadDOM.style = '' }, 1500); } $(allLoadDOM).append(` `); document.body.appendChild(allLoadDOM); $("#ccc_load_container > button").click(() => { lock && handleDownload(); allLoadDOM.style.cursor = 'not-allowed' }); }; // 获取图片名称 function getImageFileNameFromUrl(url) { // 匹配最后一个斜杠('/')之后的任何字符,直到遇到查询参数或文件扩展名的结束 const regex = /([^\/?#]+)(?=\.[\w]+($|[?#]))|([^\/?#]+)$/; const matches = url.match(regex); // 如果找到匹配项,则返回第一个匹配的文件名(可能包括文件扩展名) return matches ? matches[0] : 'default'; } // 获取图片扩展名 function getImageExtension(url) { var extension = url.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|tif)$/i); if (extension) { return extension[0]; } else { return '.jpg'; } } 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); // 创建一个标签用于下载 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); // 清理标签 document.body.removeChild(a); }) .catch((error) => { console.error( "There has been a problem with your fetch operation:", error ); }); } const initBindEvent = () => { document.addEventListener("contextmenu", function (event) { if (event.ctrlKey) { // 取消默认行为(阻止上下文菜单出现) event.preventDefault(); } }); document.addEventListener("mousedown", function (event) { if (event.ctrlKey && event.button === 2) { event.preventDefault(); console.log(" 打印选中 ", event); var targetElement = event.target; if (targetElement) { let url = targetElement.getAttribute("src"); if (url.includes("data:image/")) { downloadImageData(url); console.log("ssssss "); } else { const fileName = getImageFileNameFromUrl(url); downloadImage(url, fileName); } } } }); }; const initTip = () => { let tip = document.createElement("div"); tip.style.cssText = ` position: fixed; top: 3vh; 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.style.top = '-150px' // tip.style.display = "none"; }, 3000); document.body.appendChild(tip); }; const init = () => { window.addEventListener("load", function () { if (window.self !== window.top) return; createEle(); initBindEvent(); loadStyle(); setTimeout(() => { if (!localStorage.getItem('IS_IMAGE_DOWNLOAD_TIP')) { localStorage.setItem('IS_IMAGE_DOWNLOAD_TIP', '1') initTip(); } }, 200); }); }; (function () { init(); })();