您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
实现灰机汉化组漫画网站(yoedge.com)的横屏阅读模式
// ==UserScript== // @name yoedge-horizontal-screen // @namespace https://github.com/Lockvictor // @author Lockvictor // @description 实现灰机汉化组漫画网站(yoedge.com)的横屏阅读模式 // @homepage https://github.com/Lockvictor/yoedge-horizontal-screen // @match http://*.yoedge.com/smp-app/* // @version 2.1.3 // @grant none // ==/UserScript== //漫画宽高比 var MANGA_ASPECT_RATIO = 1.5; //默认屏幕占比 var DEFAULT_SCALE_RATIO = 0.6; //最大占比,漫画与屏幕等宽 var MAX_SCALE_RATIO = 1; //最小占比,漫画与屏幕等高,即原来的竖屏模式 var MIN_SCALE_RATIO = window.screen.height / MANGA_ASPECT_RATIO / window.screen.width; //屏幕占比缩放步长 var SCALE_STEP = 0.05; //j和k快捷键滚动屏幕的比例 var SCROLLBY_RATIO = 0.2; //漫画当前屏幕占比 var gMangaAreaRatio = DEFAULT_SCALE_RATIO; (function () { 'use strict'; document.body.innerHTML = ''; document.addEventListener('contextmenu', function (event) { event.preventDefault(); }); //获取本话的配置信息,主要包括页数和图片的url var configString = get("smp_cfg.json"); loadAllPage(JSON.parse(configString)); })(); function get(url) { var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET", url, false); xmlHttp.send(null); return xmlHttp.responseText; } function loadAllPage(config) { //获取图片url和序号 var orderList = config.pages.order; var imageUrlList = config.pages.page; //创建漫画原图的img元素 for (var i = 0; i < orderList.length; i++) { var order = orderList[i]; var img = document.createElement('img'); img.id = 'img' + order; img.style.display = 'none'; img.src = imageUrlList[order]; document.body.appendChild(img); } var imgElementList = document.getElementsByTagName('img'); //图片传输需要时间,直接获取会出错,采用分次加载,每次加载5张图 var loadStartIndex = 0; var loadEndIndex = 0; var LOAD_STEP = 5; var INDEX_LIMIT = imgElementList.length; // console.log(`INDEX_LIMIT: ${INDEX_LIMIT}`); var imgSizeCheckFlag = setInterval(function () { loadEndIndex = ((loadStartIndex + LOAD_STEP) > INDEX_LIMIT) ? INDEX_LIMIT : (loadStartIndex + LOAD_STEP); if (isImageOk(imgElementList, loadStartIndex, loadEndIndex)) { //用canvas绘制原图,实现反色块的处理 drawImageByCanvas(orderList, imageUrlList, loadStartIndex, loadEndIndex); loadStartIndex = loadEndIndex; } if (loadStartIndex === INDEX_LIMIT) { clearInterval(imgSizeCheckFlag); for (var i = 0; i < orderList.length; i++) { var img = document.getElementById('img' + orderList[i]); document.body.removeChild(img); } imgElementList = null; addNextEpisodeButton(); } // console.log('loadStartIndex: ' + loadStartIndex); }, 2000); // 自定义缩放、滚动等快捷键 customizeShortcut(); } function isImageOk(imgElementList, startIndex, endIndex) { var isLoaded = true; for (var i = startIndex; i < endIndex; i++) { var img = imgElementList[i]; if (!img.complete || img.naturalWidth === 0) { isLoaded = false; break; } } return isLoaded; } function drawImageByCanvas(orderList, imageUrlList, startIndex, endIndex) { for (var i = startIndex; i < endIndex; i++) { var order = orderList[i]; var img = document.getElementById('img' + order); var width = img.naturalWidth; var height = img.naturalHeight; // console.log(img); // console.log(`order: ${order}, width: ${width}, height: ${height}`); var mgcanv = document.createElement('canvas'); mgcanv.id = 'canvas' + order; mgcanv.width = width; mgcanv.height = height; mgcanv.style.display = 'block'; mgcanv.style.margin = '0 auto'; mgcanv.style.width = numberToPercentage(gMangaAreaRatio); // console.log(mgcanv); var context = mgcanv.getContext('2d'); context.drawImage(img, 0, 0); //前5张图没有反色块 if (i > 4) { cleanClutter(imageUrlList[order], context, width, height); } document.body.appendChild(mgcanv); // console.log(mgcanv); } } function cleanClutter(imageUrl, context, width, height) { if (imageUrl && window.clutter && imageUrl.indexOf("pages") != -1 && width > 200 && height > 300 && ( (imageUrl.indexOf('.png') != -1 && window.clutter == '1') || (imageUrl.indexOf('.png') != -1 && window.clutter == '2' && smp.controller.type == '0' && imageUrl.match(/\/0{0,3}[1aA]\.png$/) !== null) || (imageUrl.indexOf('.png') != -1 && window.clutter == '2' && smp.controller.type == '1' && imageUrl.match(/\/0?00[012345]\.png$/) === null) || (imageUrl.indexOf('.jpg') != -1 && window.clutter == '2' && smp.controller.type == '1' && imageUrl.match(/\/0?00[012345]\.jpg$/) === null))) { var imageData = context.getImageData(0, 0, width, height); var data = imageData.data; var j1 = 0, j2 = 0; var r = width * 4, r1 = r * 110, r2 = r; var y1 = Math.floor(height >> 1) & 0xFFFFFFE; if (window.clutter == '2' && imageUrl.indexOf('.png') !== -1) { y1 = 100; } var x1 = Math.floor(width / 3); var x2 = x1 << 1; var y2 = y1 + 20; if (height > 550) { y2 = y1 + 60; } if (window.clutter == '2') { var lastOf = imageUrl.lastIndexOf('/'); var fileName = decodeURI(imageUrl.substring(lastOf)); if (fileName.indexOf("3") != -1) { y1 -= 8; y2 -= 11; } else if (fileName.indexOf("4") != -1) { y1 -= 6; y2 -= 13; } else if (fileName.indexOf("5") != -1) { y2 -= 14; } else if (fileName.indexOf("7") != -1) { y1 -= 2; y2 -= 3; } else if (fileName.indexOf("9") != -1) { y2 -= 13; } else if (fileName.indexOf("01") != -1) { y2 -= 11; } else if (fileName.indexOf("02") != -1) { y1 -= 12; y2 -= 17; } if (fileName.indexOf("4") != -1) { x1 -= 7; x2 -= 19; } else if (fileName.indexOf("5") != -1) { x1 -= 15; x2 -= 13; } else if (fileName.indexOf("6") != -1) { x1 -= 31; x2 = x1 + 76; } else if (fileName.indexOf("7") != -1) { x1 += 21; } else if (fileName.indexOf("8") != -1) { x2 -= 13; } else if (fileName.indexOf("01") != -1) { x2 = x1 + 99; } else if (fileName.indexOf("02") != -1) { x1 -= 13; x2 = x1 + 97; } else if (fileName.indexOf("03") != -1) { x2 = x1 + 91; } } var is = y1 * r + x1 * 4, i = 0; if (window.clutter == '2') { for (j1 = y1; j1 < y2; j1 += 1) { i = is; for (j2 = x1; j2 < x2; j2++) { data[i + 2] = data[i + 2] ^ 0xFF; data[i + 1] = data[i + 1] ^ 0xFF; data[i] = data[i] ^ 0xFF; i += 4; } x2--; is += r2; } } else { for (j1 = y1; j1 < y2; j1 += 1) { i = is; for (j2 = x1; j2 < x2; j2++) { if (data[i + 3 - r1] !== 0) { data[i + 2] = data[i + 2] ^ data[i + 2 - r1]; data[i + 1] = data[i + 1] ^ data[i + 1 - r1]; data[i] = data[i] ^ data[i - r1]; } i += 4; } is += r2; } } context.putImageData(imageData, 0, 0); } } function addNextEpisodeButton() { var style = document.createElement('style'); style.innerHTML = "#next-episode { display: block; margin: 0 auto; height: 70px; background: rgba(211, 211, 211, 0.3) url('res/common/pre.png') no-repeat 50% 14px;}"; style.innerHTML += "#next-episode:hover { background-color: rgba(211, 211, 211, 0.5); }"; document.head.appendChild(style); var nextEpisodeButton = document.createElement('div'); nextEpisodeButton.id = 'next-episode'; nextEpisodeButton.style.width = numberToPercentage(gMangaAreaRatio); nextEpisodeButton.addEventListener('click', function (event) { smp.toolbar.nextApp(); }); document.body.appendChild(nextEpisodeButton); } function customizeShortcut() { // 漫画缩放、滚动、翻页 // 缩放和滚动都可以持续响应,注册到keydown document.addEventListener('keydown', function (event) { switch (event.key) { case '=': scale(SCALE_STEP); break; case '-': scale(-SCALE_STEP); break; case '0': gMangaAreaRatio = DEFAULT_SCALE_RATIO; scale(0); break; case 'j': smoothyScrollBy(0, screen.width * gMangaAreaRatio * MANGA_ASPECT_RATIO * SCROLLBY_RATIO); break; case 'k': smoothyScrollBy(0, -screen.width * gMangaAreaRatio * MANGA_ASPECT_RATIO * SCROLLBY_RATIO); break; case 'h': smoothyScrollTo(0, 0); break; case 'l': smoothyScrollTo(0, document.body.scrollHeight); break; default: break; } }); // 跳转下一话是单次响应,注册到keyup document.addEventListener('keyup', function (event) { switch (event.key) { case 'n': smp.toolbar.nextApp(); break; default: break; } }); } function scale(increment) { var expectedScaleRatio = gMangaAreaRatio + increment; if (increment > 0) { gMangaAreaRatio = (expectedScaleRatio >= MAX_SCALE_RATIO) ? MAX_SCALE_RATIO : expectedScaleRatio; } else if (increment < 0) { gMangaAreaRatio = (expectedScaleRatio <= MIN_SCALE_RATIO) ? MIN_SCALE_RATIO : expectedScaleRatio; } var newWidth = numberToPercentage(gMangaAreaRatio); canvasList = document.getElementsByTagName('canvas'); for (var i = 0; i < canvasList.length; i++) { canvasList[i].style.width = newWidth; } document.getElementById('next-episode').style.width = newWidth; } //=====================基础功能相关函数===================== function smoothyScrollBy(offsetX, offsetY) { try { window.scrollBy({ top: offsetY, left: offsetX, behavior: 'smooth' }); } catch (error) { window.scrollBy(offsetX, offsetY); } } function smoothyScrollTo(x, y) { try { window.scrollTo({ top: y, left: x, behavior: 'smooth' }); } catch (error) { window.scrollTo(x, y); } } function numberToPercentage(value) { return Math.floor(100 * value) + '%'; }