// ==UserScript== // @name 动漫之家漫画页转长图 // @namespace https://unlucky.ninja/ // @version 2024-06-16-2 // @description 打开某一话后点击标题右侧按钮生成长图(仅为用于熟人间分享),需要与网络请求修改类浏览器扩展配合 // @author UnluckyNinja // @license MIT // @match https://manhua.idmzj.com/*/*.shtml* // @match https://manhua.dmzj.com/*/*.shtml* // @require https://code.jquery.com/jquery-3.7.1.slim.min.js // @require https://update.greasyfork.icu/scripts/498113/1395364/waitForKeyElements_mirror.js // @icon https://www.google.com/s2/favicons?sz=64&domain=idmzj.com // @grant none // @downloadURL none // ==/UserScript== (function() { 'use strict'; // consts const CANVAS_WIDTH = 800 const JPG_QUALITY = 0.5 // return tarB in tarA/tarB=srcA/srcB function toRatioValue(srcA, srcB, tarA){ return tarA/srcA * srcB } function getTotalHeight(images, width = 800){ let totalH = 0 for (let image of images){ const w = image.naturalWidth const h = image.naturalHeight totalH += Math.ceil(toRatioValue(w, h, width)) } return totalH } async function genLongImageBlob(){ const images = [...document.querySelectorAll(".comic_wraCon img").values()] const canvas = document.createElement('canvas') canvas.width = CANVAS_WIDTH canvas.height = getTotalHeight(images, CANVAS_WIDTH) const context = canvas.getContext('2d') let curH = 0 const promises = images.map(it=>it.decode()) await Promise.all(promises) for (let image of images){ const w = image.naturalWidth const h = image.naturalHeight const newH = Math.ceil(toRatioValue(w, h, CANVAS_WIDTH)) context.drawImage(image, 0, curH, CANVAS_WIDTH, newH) curH += newH } return new Promise((resolve)=>{ canvas.toBlob((blob)=>{ resolve(blob) }, 'image/jpeg', JPG_QUALITY) }) } let downloadButton let previewButton async function openImage(){ previewButton.innerText = '生成中...' previewButton.disabled = true const blob = await genLongImageBlob() const url = URL.createObjectURL(blob) window.open(url, '_blank') setTimeout(()=>{ URL.revokeObjectURL(url) }, 10000) previewButton.innerText = '预览长图' previewButton.disabled = false } async function downloadImage(){ downloadButton.innerText = '生成中...' downloadButton.disabled = true const blob = await genLongImageBlob() const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url const name = document.querySelector('.comic_wraCon h1').textContent const chapter = document.querySelector('.comic_wraCon h1 ~ span').textContent a.download = `${name}_${chapter}.jpg` a.click() setTimeout(()=>{ URL.revokeObjectURL(url) }, 0) downloadButton.innerText = '下载长图' downloadButton.disabled = false } function addButton(node){ previewButton = document.createElement('button') previewButton.innerText = '预览长图' previewButton.style.margin = '0.5rem' previewButton.addEventListener('click', openImage) node[0].parentElement.append(previewButton) downloadButton = document.createElement('button') downloadButton.innerText = '下载长图' downloadButton.style.margin = '0.5rem' downloadButton.addEventListener('click', downloadImage) node[0].parentElement.append(downloadButton) } waitForKeyElements('.comic_wraCon img', (images)=>{ images[0].crossOrigin = 'anonymous' }) waitForKeyElements('.comic_wraCon h1', addButton, true) })();