Greasy Fork

来自缓存

Younge Ace UP Comic Viewer

ヤングエースUPの漫画を見開きで表示する

目前为 2018-01-03 提交的版本。查看 最新版本

// ==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.2
// @grant       none
// ==/UserScript==

(function (){
	//親コンテナの幅制限を解除
	$(".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("<style type='text/css'> div[id^=img] {display:none} </style>");
	
	// ページ組み換えボタン
	var $reconst = $("<div id='constraction' />").css(
		{
			'position': "fixed",
			'left': 0,
			'top': 0,
			'width': "100%",
			'height': "20px",
			'background-color': "darkgray",
			'opacity': 0,
			'text-align': "center",
			'line-height': "20px",
		}
	);
	$reconst.text("Construction");
	var _preblank = true;
	$reconst.on(
		{
			'click': function()
			{
				if( pages==null )
				{
					// なにかの不具合でページが構築されていないときのため
					InitImage();
				}
				else
				{
					// クリックするたびにページ組みを切り替える
					Centering(!_preblank);
				}
			},

			// ボタンバーを隠しておく
			'mouseenter': function()
			{
				$(this).stop()
				$(this).animate(
					{
						'opacity': 0.8
					},"fast"
				);
			},
			'mouseleave': function()
			{
				$(this).stop()
				$(this).animate(
					{
						'opacity': 0
					},"fast"
				);
			},
		}
	);
	$("body").append($reconst);

	// ページのテンプレート
	var $page = $("<div class='page'/>").css(
		{
			'margin': 0,
			'margin-bottom': "10px",
			'width': "50%",
		}
	);
	var $preblank = $page.clone().attr('class',"page pre_blank");
	var $aftblank = $page.clone().attr('class',"page aft_blank");
	$preblank.css( 'float', "right" );
	$aftblank.css( 'float', "left");
	
	// ページを入れるコンテナ
	var $IMAGE_CONTAINER = $(".lazy-container").css( 'width', "auto" );

	// 各ページを管理する配列
	var pages;
	// ロード済みの画像をカウント
	var mihiraki = false;
	var loaded = 0;
	// ページを作成
	var InitImage = function()
	{
		// 画像一覧を取得
		pages = [];
		$.getJSON(
			$IMAGE_CONTAINER.data("url"), function(data)
			{
				$.each(
					data, function(i, val)
					{
						var $i = $("<img>").attr(
							{
								'src': val,
								'num': i
							}
						);
						
						// ロードした画像が見開きっぽければ、属性とスタイルを追加
						// (見開き関連の処理はヤングエースUPでは必要ないけど……)
						$i.load(
							function()
							{
								var img = new Image();
								img.src = $(this).attr('src');

								if( img.width > img.height )
								{
									mihiraki = true;
									
									$(this).parent().attr( 'mihiraki', true);
									$(this).parent().css(
										{
											'width': "100%",
											'float': "none",
										}
									);
									$(this).css(
										{
											'margin': "0 auto",
											'float': "none",
										}
									);
									
									// 見開きが一枚目だった場合、前見返しを非表示に
									if( $(this).attr('num')==0 )
									{
										$preblank.hide();
										_preblank = null;
									}
								}

								loaded++;
								// 見開きが存在し、すべてロード完了したときに中央寄せ
								if( mihiraki &&
									loaded==pages.length )
								{
									Centering();
								}
							}
						);

						// 管理配列にページ情報を追加
						pages.push(
							{
								'index': i,
								'src': val,
								'$page': $page.clone().append($i),
								'$image': $i,
							}
						);
					}
				);
				
				// 一応ページ順をソートしておく
				pages.sort(
					function(v1, v2)
					{
						return v1.index<v2.index? -1: 1;
					}
				);
				
				// ページを追加していく
				// 前見返し
				$IMAGE_CONTAINER.append( $preblank );
				// ページ画像
				$.each( pages,
					function(i, val)
					{
						$IMAGE_CONTAINER.append( val.$page );
					}
				);
				// 後ろ見返し
				$IMAGE_CONTAINER.append( $aftblank );

				// clearfix
				$IMAGE_CONTAINER.append(
					$("<div class='clearfix'>").css(
						{
							'height': 0,
							'clear': "both",
						}
					)
				);

				// クリックスクロール用領域
				var $scrL = $("<div/>").css(
					{
						'position': "absolute",
						'width': "50%",
						'height': "100%",
						'top': 0
					}
				);
				var $scrR = $scrL.clone();
				$scrL.css( 'left', 0);
				$scrR.css( 'right', 0);
				$IMAGE_CONTAINER.prepend($scrL);
				$IMAGE_CONTAINER.prepend($scrR);

				// 次か前のページにスクロールする
				var ScrollToPage = function(e, delta)
				{
					var st = $(window).scrollTop();
					var i;
					for( i=pagepos.length-1; i>=0; i-- )
					{
						// 次のページ
						if( delta<0 && st >= pagepos[i] )
						{
							i++;
							break;
						}
						// 前のページ
						else if( delta>0 && !(st <= pagepos[i]) )
						{
							break;
						}
					}

					$('html,body').stop();
					$('html,body').animate({
						scrollTop: pagepos.round(i)
					},300);
				}

				// エピソード移動
				var MoveEpisode = function($nav, homepos)
				{
					if( $nav.length>0 &&
						$(window).scrollTop() == homepos )
					{
						location.href = $nav.attr('href');
					}
				};

				$scrL.on(
					{
						// 左側クリックで次のページへ
						'click': function(e)
						{
							e.stopPropagation();
							ScrollToPage(e, -1);
						},

						// 最後の左ページをダブルクリックで次の話
						'dblclick': function()
						{
							MoveEpisode( $(".viewerbtn a"), pagepos.lastv() );
						}
					}
				);
				$scrR.on(
					{
						// 右側クリックで前のページへ
						'click': function(e)
						{
							e.stopPropagation();
							ScrollToPage(e, 1);
						},
					}
				);

				// ロード完了まで暫定的にセンタリングする
				//  画像がキャッシュされていないサイズが取得できないので、
				//  すべての画像がロードされた時もう一度中央寄せする必要がある
				Centering(true);
				// サイズ調整
				Resize();
			}
		);
	};
	
	// スクロール位置を記録しておく配列
	var pagepos = [];
	var PosUpdate = function()
	{
		pagepos = [];
		$.each( pages,
			function(i, val)
			{
				var target = Math.ceil(val.$page.offset().top);
				if( pagepos.lastIndexOf(target)<0 )
				{
					pagepos.push( target );
				}
			}
		);
	};
	
	// 各ページの画像を真ん中に寄せる
	var Centering = function(blankin)
	{
		if( _preblank != null &&
			blankin != null ) _preblank = blankin;

		var count = 0;
		// フラグが立っていれば前見返しを表示
		if( _preblank )
		{
			$preblank.show();
			count++;
		}
		else
		{
			$preblank.hide();
		}

		$.each( pages,
			function(i, val)
			{
				var $p = val.$page;
				var $i = val.$image;
				var img = new Image();
				img.src = $i.attr('src');

				// 画像サイズで見開きを判定
				// (キャッシュがあれば直接取得できる)
				// (ないときのためロードを待ってもう一度Centering関数を実行すること)
				if( img.width > img.height ||
					$p.attr('mihiraki') )
				{
					// カウントをリセット(次のページは強制的に右)
					count = 0;
				}
				else
				{
					// 偶数カウントであれば右ページ(画像は左寄せ)
					$p.css(
						{
							'width': "50%",
							'float': count%2!=0? "left": "right",
						}
					);
					$i.css( 'float', count%2==0? "left": "right" );
					
					count++;
				}
			}
		);

		// 最後が右ページであれば後ろ見返しを表示
		if( count%2!=0 )
		{
			$aftblank.show();
		}
		else
		{
			$aftblank.hide();
		}
		
		PosUpdate();
	};

	const sqt = Math.sqrt(2);
	var Resize = function()
	{
		var wh = $(window).height();
		var ww = $(window).width();
		$IMAGE_CONTAINER.css( 'width', ww );

		$preblank.css('height', wh);
		$aftblank.css('height', wh);
		$.each( pages,
			function(i, val)
			{
				val.$page.css( 'height', wh);
			}
		);

		// 画像をアジャスト
		var prm = wh*sqt<ww? {
			//横長
			'height': "100%",
			'width': "auto",
			'margin': 0
		}:
		{
			//縦長
			'height': "auto",
			'width': "100%",
			'margin-top': ((wh-ww/2*sqt) / 2)
		};
		$.each(
			pages, function(i, val)
			{
				val.$image.css(prm);
			}
		);

		PosUpdate();
	};
	

	$(document).on(
		{
			'ready': function()
			{
				InitImage();
			},
		}
	);
	$(window).on(
		{
			// リサイズ時に画像サイズをアジャスト
			'resize': function()
			{
				Resize();
			}
		}
	);

})();