您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Download resized version of single-image pages
// ==UserScript== // @name Resize Image Downloader // @version 2.0 // @author SleepingGiant // @description Download resized version of single-image pages // @namespace https://greasyfork.org/users/1395131 // @match *://*/*.jpg // @match *://*/*.jpeg // @match *://*/*.png // @match *://*/*.webp // @grant none // ==/UserScript== (function () { 'use strict'; let cropLines = {}; let cropOverlay = null; let infoBox = null; const createUI = () => { const container = document.createElement('div'); container.style.position = 'fixed'; container.style.top = '20px'; container.style.right = '20px'; container.style.backgroundColor = '#222'; container.style.color = 'white'; container.style.padding = '10px'; container.style.borderRadius = '10px'; container.style.zIndex = '9999'; container.style.display = 'flex'; container.style.flexDirection = 'column'; container.style.gap = '6px'; container.style.fontSize = '13px'; const createLabeledInput = (labelText, defaultValue) => { const wrapper = document.createElement('div'); wrapper.style.display = 'flex'; wrapper.style.alignItems = 'center'; wrapper.style.gap = '4px'; const label = document.createElement('label'); label.textContent = labelText; const input = document.createElement('input'); input.type = 'number'; input.value = defaultValue; input.style.width = '60px'; input.style.padding = '4px'; input.style.borderRadius = '4px'; input.style.border = 'none'; wrapper.appendChild(label); wrapper.appendChild(input); container.appendChild(wrapper); return input; }; const widthInput = createLabeledInput('Width:', 1200); const heightInput = createLabeledInput('Height:', 1200); // Crop toggle checkbox const cropToggle = document.createElement('label'); cropToggle.style.display = 'flex'; cropToggle.style.alignItems = 'center'; cropToggle.style.gap = '6px'; const cropCheckbox = document.createElement('input'); cropCheckbox.type = 'checkbox'; cropCheckbox.checked = false; cropCheckbox.onchange = () => { if (cropCheckbox.checked) { const img = document.querySelector('img'); if (img) createCropOverlay(img); } else { removeCropOverlay(); } }; cropToggle.appendChild(cropCheckbox); cropToggle.appendChild(document.createTextNode('Enable Crop')); container.appendChild(cropToggle); // Scaling toggle checkbox const scaleToggle = document.createElement('label'); scaleToggle.style.display = 'flex'; scaleToggle.style.alignItems = 'center'; scaleToggle.style.gap = '6px'; const scaleCheckbox = document.createElement('input'); scaleCheckbox.type = 'checkbox'; scaleCheckbox.checked = true; scaleToggle.appendChild(scaleCheckbox); scaleToggle.appendChild(document.createTextNode('Enable Scaling')); container.appendChild(scaleToggle); // Download button const downloadBtn = document.createElement('button'); downloadBtn.textContent = '⬇️ Download'; styleButton(downloadBtn); downloadBtn.onclick = () => downloadCroppedAndResized( widthInput.value, heightInput.value, cropCheckbox.checked, scaleCheckbox.checked ); container.appendChild(downloadBtn); document.body.appendChild(container); }; const styleButton = (btn) => { btn.style.backgroundColor = '#007acc'; btn.style.color = 'white'; btn.style.border = 'none'; btn.style.padding = '6px 10px'; btn.style.borderRadius = '6px'; btn.style.cursor = 'pointer'; btn.style.fontSize = '13px'; }; const createCropOverlay = (img) => { const rect = img.getBoundingClientRect(); cropOverlay = document.createElement('div'); cropOverlay.style.position = 'absolute'; cropOverlay.style.left = `${rect.left + window.scrollX}px`; cropOverlay.style.top = `${rect.top + window.scrollY}px`; cropOverlay.style.width = `${rect.width}px`; cropOverlay.style.height = `${rect.height}px`; cropOverlay.style.zIndex = '9998'; cropOverlay.style.pointerEvents = 'none'; document.body.appendChild(cropOverlay); const directions = ['left', 'right', 'top', 'bottom']; directions.forEach(dir => { const line = document.createElement('div'); line.className = `crop-line ${dir}`; Object.assign(line.style, { position: 'absolute', backgroundColor: 'red', pointerEvents: 'auto', zIndex: '10000', cursor: dir === 'left' || dir === 'right' ? 'ew-resize' : 'ns-resize', }); if (dir === 'left' || dir === 'right') { line.style.top = '0'; line.style.width = '2px'; line.style.height = '100%'; line.style.left = dir === 'left' ? '10px' : `${rect.width - 10}px`; } else { line.style.left = '0'; line.style.height = '2px'; line.style.width = '100%'; line.style.top = dir === 'top' ? '10px' : `${rect.height - 10}px`; } makeDraggable(line, dir, img, rect); cropOverlay.appendChild(line); cropLines[dir] = line; }); // Info box infoBox = document.createElement('div'); infoBox.style.position = 'fixed'; infoBox.style.bottom = '20px'; infoBox.style.left = '20px'; infoBox.style.background = '#000a'; infoBox.style.color = 'white'; infoBox.style.padding = '6px 10px'; infoBox.style.borderRadius = '8px'; infoBox.style.fontSize = '13px'; infoBox.style.zIndex = '9999'; document.body.appendChild(infoBox); updateInfoBox(img, rect); }; const removeCropOverlay = () => { if (cropOverlay) cropOverlay.remove(); if (infoBox) infoBox.remove(); cropOverlay = null; infoBox = null; cropLines = {}; }; const makeDraggable = (element, direction, img, imgRect) => { let isDragging = false; element.addEventListener('mousedown', (e) => { e.preventDefault(); isDragging = true; const onMouseMove = (moveEvent) => { if (!isDragging) return; const delta = direction === 'left' || direction === 'right' ? moveEvent.clientX - imgRect.left : moveEvent.clientY - imgRect.top; if (direction === 'left' || direction === 'right') { const clamped = Math.max(0, Math.min(delta, imgRect.width)); element.style.left = `${clamped}px`; } else { const clamped = Math.max(0, Math.min(delta, imgRect.height)); element.style.top = `${clamped}px`; } updateInfoBox(img, imgRect); }; const onMouseUp = () => { isDragging = false; document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); }; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); }; const getCropValues = (imgRect) => { const left = parseInt(cropLines.left?.style.left || '0'); const right = parseInt(cropLines.right?.style.left || `${imgRect.width}`); const top = parseInt(cropLines.top?.style.top || '0'); const bottom = parseInt(cropLines.bottom?.style.top || `${imgRect.height}`); const cropX = Math.min(left, right); const cropY = Math.min(top, bottom); const cropW = Math.abs(right - left); const cropH = Math.abs(bottom - top); return { cropX, cropY, cropW, cropH }; }; const updateInfoBox = (img, imgRect) => { const { cropX, cropY, cropW, cropH } = getCropValues(imgRect); const removedLeft = cropX; const removedTop = cropY; const removedRight = img.naturalWidth - (cropX + cropW); const removedBottom = img.naturalHeight - (cropY + cropH); infoBox.innerHTML = ` <b>Crop</b><br/> Removed: Left ${removedLeft}px, Right ${removedRight}px<br/> Removed: Top ${removedTop}px, Bottom ${removedBottom}px<br/> Final: ${cropW} x ${cropH}px `; }; const downloadCroppedAndResized = (newWidth, newHeight, cropEnabled, scaleEnabled) => { const img = document.querySelector('img'); const rect = img.getBoundingClientRect(); let cropX = 0, cropY = 0, cropW = img.naturalWidth, cropH = img.naturalHeight; if (cropEnabled && cropOverlay) { const values = getCropValues(rect); cropX = values.cropX * img.naturalWidth / rect.width; cropY = values.cropY * img.naturalHeight / rect.height; cropW = values.cropW * img.naturalWidth / rect.width; cropH = values.cropH * img.naturalHeight / rect.height; } const finalW = scaleEnabled ? parseInt(newWidth) : cropW; const finalH = scaleEnabled ? parseInt(newHeight) : cropH; const canvas = document.createElement('canvas'); canvas.width = finalW; canvas.height = finalH; const ctx = canvas.getContext('2d'); ctx.drawImage(img, cropX, cropY, cropW, cropH, 0, 0, finalW, finalH); canvas.toBlob(blob => { const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `cropped_scaled_${canvas.width}x${canvas.height}.jpg`; link.click(); }, 'image/jpeg', 0.9); }; const interval = setInterval(() => { const img = document.querySelector('img'); if (img && document.body) { createUI(); clearInterval(interval); } }, 200); })();