// ==UserScript== // @name Younge Ace UP Comic Viewer // @namespace phodra // @description ヤングエースUPの漫画を見開きで表示する // @include https://web-ace.jp/youngaceup/contents/* // @require https://greasyfork.org/scripts/36978-arrayex/code/ArrayEx.js?version=240772 // @version 0.3 // @grant none // @downloadURL none // ==/UserScript== (()=>{ //親コンテナの幅制限を解除 $(".col-viewer").width("auto"); $(".inner-delivery-contents").css( 'padding', "10px 0 0 0"); $(".top-brand-logo, .global-navigation, .sub-navigation, .containerMain, .footer").css( { 'max-width': "initial", 'min-width': "initial", } ); $(".displayFlex").css( 'flex-flow', "row wrap"); $(".nav-youngaceup").hide(); // 元の画像を非表示 $("head").append(""); let _preblank = true; // ページ組み換えボタン let $reconst = $("
").text("Construction"); $reconst.css( { 'background-color': "darkgray", 'flex-grow': 1, } ); $reconst.click( // なにかの不具合でページが構築されていないときのため初期化もできるようにしておく // クリックするたびにページ組みを切り替える () => pages==null? InitImage(): Centering(!_preblank) ); // ロード不全の画像を読み込む let $suppley = $("
").text("Suppley"); $suppley.css( { 'background-color': "gray", 'flex-basis': "70px", 'padding': "0 10px", } ); $suppley.click( () => { pages.forEach( val => { if( val.error ) { loaded--; val.$image.attr( 'src', val.src + "?" + String(Math.random()).slice(2) ); console.log(val.index, val.$image ); } } ); } ); let $control = $("
").css( { 'position': "fixed", 'display': "flex", 'left': 0, 'top': 0, 'width': "100%", 'opacity': 0, 'height': "20px", 'text-align': "center", 'line-height': "20px", } ); // コントロールバーを隠しておく let AutoHide = (_this, mark) => { $(_this).stop(); $(_this).animate( { 'opacity': mark }, "fast" ); } $control.hover( function(){ AutoHide(this, 0.8); }, function(){ AutoHide(this, 0); } ); $control.append($reconst); $control.append($suppley); $("body").append($control); // ページのテンプレート const $sheet = $("
").css( { 'position': "relative", 'pointer-events': "none", 'margin': 0, 'margin-bottom': "10px", 'width': "50%", 'display': "flex", 'align-items': "center", } ); // ページを入れるコンテナ let $IMAGE_CONTAINER = $(".lazy-container").css( 'width', "auto" ); // 各ページを管理する配列 let pages; // ロード済みの画像をカウント let loaded = 0; // ページを作成 let InitImage = () => { // 画像一覧を取得 pages = []; $.getJSON( $IMAGE_CONTAINER.data("url"), idata => { idata.forEach( (val, i) => { let $i = $("").attr( { 'src': val, 'num': i } ); // ロードした画像が見開きっぽければ、属性とスタイルを追加 // (見開き関連の処理はヤングエースUPでは必要ないけど……) $i.on( { 'load': () => { if( loaded==0 ) Centering(); }, // 画像が読み込み不全になった場合 'error': function(){ let index = $(this).attr('index'); if( index ) { pages[index].error = true; } console.log("error", index, pages[index]); }, } ); let $s = $sheet.clone(); $s.append($i); // 管理配列にページ情報を追加 pages.push( { 'index': i, 'src': val, '$sheet': $s, '$image': $i, 'error': null, 'side': null, 'pos': 0, } ); } ); // 一応ページ順をソートしておく pages.sort( (v1, v2) => v1.index $IMAGE_CONTAINER.append( val.$sheet ) ); // clearfix $IMAGE_CONTAINER.append( $("
").css( { 'height': 0, 'clear': "both", } ) ); // クリックスクロール用領域 let $scrL = $("
").css( { 'position': "absolute", 'width': "50%", 'height': "100%", 'top': 0 } ); let $scrR = $scrL.clone(); $scrL.css( 'left', 0); $scrR.css( 'right', 0); $IMAGE_CONTAINER.prepend($scrL); $IMAGE_CONTAINER.prepend($scrR); // 次か前のページにスクロールする let ScrollToPage = delta => { let st = $(window).scrollTop(); let i; for( i=pages.length-1; i>=0; i-- ) { // 次のページ if( delta>0 && st >= pages[i].pos ) { i++; break; } // 前のページ else if( delta<0 && !(st <= pages[i].pos) ) { break; } } $('html,body').stop(); $('html,body').animate({ scrollTop: pages.round(i).pos },300); }; // エピソード移動 let MoveEpisode = ($nav, homepos) => { if( $nav.length>0 && $(window).scrollTop() == homepos ) { location.href = $nav.attr('href'); } }; $scrL.on( { // 左側クリックで次のページへ 'click': (e) => { e.stopPropagation(); ScrollToPage(1); }, // 最後の左ページをダブルクリックで次の話 'dblclick': () => { MoveEpisode( $(".viewerbtn a"), pages.lastv().pos ); } } ); $scrR.on( { // 右側クリックで前のページへ 'click': (e) => { e.stopPropagation(); ScrollToPage(-1); }, } ); // ロード完了まで暫定的にセンタリングする //  画像がキャッシュされていないサイズが取得できないので、 //  すべての画像がロードされた時もう一度中央寄せする必要がある Centering(); // サイズ調整 Resize(); } ); }; // スクロール位置を記録しておく配列 let PosUpdate = () =>{ pages.forEach( val => val.pos = Math.ceil(val.$sheet.offset().top) ); }; // 各ページの画像を真ん中に寄せる let Centering = blankin => { if( _preblank != null && blankin != null ) _preblank = blankin; let count = 0; // フラグが立っていれば前見返しを表示 if( _preblank ) count++; pages.forEach( val => { let $s = val.$sheet; // 偶数カウントであれば右ページ(画像は左寄せ) if( count%2==0 ) { val.side = "right"; $s.attr( 'side', "right"); $s.css( { 'float': "right", 'justify-content': "flex-start", } ); } else { val.side = "left"; $s.attr( 'side', "left"); $s.css( { 'float': "none", 'justify-content': "flex-end", } ); } count++; } ); PosUpdate(); }; const sqt = Math.sqrt(2); let Resize = () => { let wh = $(window).height(); let ww = $(window).width(); $IMAGE_CONTAINER.css( 'width', ww ); pages.forEach( val => { val.$sheet.css( 'height', wh); if( wh*sqt { InitImage(); }, } ); $(window).on( { // readyで初期化できていなかった場合 'load': () => { if( pages==null ) InitImage(); }, // リサイズ時に画像サイズをアジャスト 'resize': () => { Resize(); } } ); })();