pixivにメニューバーを追加するUserScript(Chrome)

pixivにメニューを追加するUserScript

最近pixivのUI改悪で「作品管理」や「ブックマーク」のメニューが格納されて右上のアイコンをクリックしないと表示されなくなってアクセスが悪くなりました。

pixiv右上部のアイコンをクリックしないとよく使うメニューが表示されない
よく使うメニューが格納された…

という事でヘッダーにメニューを追加するためのUserScriptを作成しました。

自分が使う分にはこれで十分かな…という簡易的な物ですが、ご自由にお使いください。

メニュー追加
pixivに簡易メニューを追加
こんな感じに追加されます
新UIでも追加されます
pixiv新UIでのメニュー
新UIでの表示

スポンサーリンク

pixivにメニューを追加するUserScript

シェア用: notepad

// ==UserScript==
// @name        pixivにメニューを追加
// @namespace   http://web.monogusa-note.com/add-menu-to-pixiv
// @version     1
// @description pixivに簡易的なメニューを追加します。
// @author      草村
// @match       https://www.pixiv.net/*
// @grant       none
// ==/UserScript==

window.addEventListener( 'load', () => {
	const user_id = '';
	const menu = {
//		"ホーム":["/"],
		"作品投稿":["/upload.php", {
			"イラスト":["/upload.php"],
//			"うごイラ":["/ugoira_upload.php"],
			"マンガ":["/upload.php?type=manga"],
//			"小説":["/novel/upload.php"],
		}],
		"作品管理":["/manage/illusts"],
//		"フォロー":["/users/[id]/following"],
//		"フォロワー":["/users/[id]/followers"],
		"フォロー中":["/bookmark.php?type=user"],
		"ブックマーク":["/bookmark.php"],
//		"閲覧履歴":["/history.php"],
//		"しおり":["/novel/marker_all.php"],
//		"設定":["/setting_user.php"],
//		"イラスト・漫画":["/"],
//		"小説":["/novel"],
//		"フォロー新着":["/bookmark_new_illust.php"],
//		"ディスカバリー":["/discovery"],
//		"フィード":["/stacc?mode=unify"],
//		"ランキング":["/ranking.php"],
//		"みんなの新着":["/new_illust.php"],
//		"コンテスト":["/contest"],
	};
	const css = `
		#add-menubar {
			background: #fff;
			font-size: 14px;
			padding: 5px 0;
			animation: add-menu-feedin .5s backwards;
		}
		#add-menubar>ul {
			width: 970px;
			margin: 0 auto;
			padding: 0;
		}
		#add-menubar li {
			position: relative;
			list-style: none;
		}
		#add-menubar>ul>li {
			display: inline-block;
		}
		#add-menubar>ul>li+li {
			border-left: 1px solid #ccc;
		}
		#add-menubar li ul {
			min-width: 100px;
			background: #fff;
			position: absolute;
			z-index: 10;
			padding: 10px;
			opacity: 0;
			box-shadow: 2px 5px 5px rgba(0,0,0,.2);
			transition: .3s;
			transform: translateY(-10px);
			pointer-events: none;
		}
		#add-menubar li:hover ul {
			opacity: 1;
			transform: translateY(0);
			pointer-events: auto;
		}
		#add-menubar li.none a {
			pointer-events: none;
		}
		#add-menubar li.none:before,
		#add-menubar li.none:after {
			position: absolute;
			bottom: 100%;
			left: 50%;
			transform: translate(-50%, 5px);
			opacity: 0;
			transition: .3s;
			pointer-events: none;
		}
		#add-menubar li.none:before {
			content:"ユーザーIDを設定してください";
			color: #fff;
			background: #333;
			border-radius: 3px;
			padding: 5px 10px;
			white-space: nowrap;
		}
		#add-menubar li.none:after {
			content: "";
			margin: 0 0 -10px;
			border-width: 10px 6px 0;
			border-style: solid;
			border-color: #333 transparent;
		}

		#add-menubar li.none:hover:before,
		#add-menubar li.none:hover:after {
			transform: translate(-50%, -5px);
			opacity: 1;
		}
		#add-menubar a {
			display: block;
			padding: 5px 10px;
		}
		#add-menubar a:hover {
			text-decoration: underline;
		}
		#add-menubar .sub:before,
		#add-menubar .sub:after {
			content: "";
			width: 6px;
			border-bottom: 2px solid #ccc;
			display: inline-block;
			transform: rotate(-45deg);
			transform-origin: left bottom;
		}
		#add-menubar .sub:before {
			transform: rotate(45deg);
			transform-origin: right bottom;
			margin-left: .3em;
		}
		@keyframes add-menu-feedin {
			0% { opacity: 0; transform: translateY(-10px); }
			100% { opacity: 1; transform: translateY(0); }
		}
	`;
	const createlist = ( obj ) => {
		let list = '';
		Object.keys(obj).forEach(key => {
			let url = obj[key][0], sub = obj[key][1];
			const has_sub = sub && Object.keys(sub).length;
			const test_id = /\[id\]/.test(url);
			url = url.replace(/\[id\]/, user_id);
			list += '<li'+ ( !user_id && test_id? ' class="none"' : '' ) +'><a href="'+url+'">'+ key + ( has_sub? '<span class="sub"></span>' : '' ) +'</a>';
			if( has_sub ) {
				list += createlist( sub );
			}
			list += '</li>';
		});
		return '<ul>'+ list + '</ul>';
	}
	const navi = document.createElement('div');
	navi.id = 'add-menubar';
	navi.innerHTML = createlist( menu );
	let insert = document.getElementById('js-mount-point-header') || document.getElementById('root').firstElementChild;
	insert.parentNode.insertBefore(navi, insert.nextSibling);

	const style = document.createElement('style');
	style.innerText = css;
	document.getElementsByTagName('head')[0].appendChild(style);
});

インストールと使い方

UserScriptはChromeの場合Tampermonkeyという拡張機能、Firefoxの場合Greasemonkeyというアドオンをインストールすると使用できます。
TampermonkeyはSafariやEdge版もあるみたいです。

ここではWindows版ChromeでのUserScriptの追加方法を解説します。

Tampermonkeyをインストールする

chromeウェブストアにあるTampermonkeyで「Chromeに追加」をクリック

ダッシュボードを開く
  1. Chromeに追加した「Tampermonkeyのアイコン」をクリック
  2. 「ダッシュボード」に移動します
Tampermonkeyのアイコンをクリックしてダッシュボードを開く
コードをコピペする
  1. 「+」タブをクリックすると<新規スクリプト>を追加できます。
  2. デフォルトでサンプルコードが記入されているのでそれを消去。
  3. pixivにメニューを追加するコードをコピペします。
+をクリック、新規スクリプトにコピペする
保存する
  1. 左上の「ファイル」をクリック
  2. 「保存」でコードを保存します。

もしくはCtrl+Sキーで保存できます。

コピペしたUserScriptを保存する
追加された事を確認

「インストール済みUserScript」タブに移動して「Pixivにメニューを追加」が表示されていればOKです。

不具合が起きた・不要になった場合には削除またはスクリプトを無効にしてください。

UserScriptとは?

ブラウザでユーザー側が用意したスクリプトを実行する為の仕組み、主にはそのスクリプトを指すと思います。中身は JavaScript です。

古く新しい!でも便利な UserScript を Chrome で使ってみよう!

この様に自由に用意できて様々な事が出来るので、配布されているスクリプトを利用する場合どのような動作をしているのか注意し信用できる物のみ利用しましょう。

カスタマイズする

メニューを追加・削除する

先頭に//がある行はコメントアウトされています。
//を削除すればメニューに表示されます。逆に非表示にしたいメニューには//を追加すればOKです。

例えば以下だとフォローは非表示になっています。

		"作品管理":["/manage/illusts"],
//		"フォロー":["/users/[id]/following"],

好きなメニューを追加する

menuは以下のような構造になっています。
好きなメニューを追加する時はこれにならってmenu={~}の中に追記すればOKです。

const menu = {
	"メニュー名":["メニューURL"],
	"メニュー名":["メニューURL", {"サブメニュー名":["サブメニューURL"]}],
}

URL内では[id]はユーザーIDに置換されます(ユーザーIDは手動で設定してください)
例えばユーザーIDが012345の場合、/users/[id]/following/users/012345/followingになります。

ユーザーIDを設定する

ユーザーIDが含まれるURLは[id]の部分をユーザーIDに置換するようになっています。
URLに[id]を含んだメニューを表示する時は手動で設定してください。

const user_id = 'ここにユーザーID(数字)を記入する'; // '012345' ←こんな感じ

※ユーザーIDは自分のプロフィールのURLでわかりますhttps://www.pixiv.net/users/ここの数字

デザインを変更する

const css = `~`のCSSを変更すればデザインをカスタマイズできます。
出力されるHTMLは次のような構造です。

<div id="add-menubar">
  <ul>
    <li><a href="URL">メニュー名<span class="sub"></span></a>
      <ul>
        <li><a href="URL">サブメニュー名</a></li>
        <li><a href="URL">サブメニュー名</a></li>
      </ul>
    </li>
    <li><a href="URL">メニュー名</a></li>
    <li><a href="URL">メニュー名</a></li>
  </ul>
</div>

除外(実行しない)ページを指定する

URLがhttps://www.pixiv.net/~のページでメニューが追加されますが(@matchで指定)
もし一部のページで除外したい場合は@excludeで除外できます。以下のように@matchの下あたりに追記すればOKです。

例えば以下だとイラストページでは実行しないようになります。

// @match       https://www.pixiv.net/*
// @exclude     https://www.pixiv.net/artworks/*

*はワイルドカードです。

注意点

pixivでは頻繁にHTMLの構造やclass名の変更が行われるようです。
もしかするとサーバに負荷が掛かるような改変への対策かもしれません。

ここで紹介しているメニュー追加はサーバ負荷になるような処理はないので大丈夫だと思いますが…。
ただ、構造の変更等で使用できなくなる場合がありますので予めご了承ください

メニューが追加される位置

上部にお知らせ等が表示されているとメニューが追加される位置がずれます。(サイト名より上部に追加されたりする)

例えばプライバシーポリシーに関するお知らせは「OK」を押すとお知らせが消えるので、再度ページを表示するとメニューが意図した位置に表示されるかと思います。

2020-06-27追記: 内部構造に微妙なアプデがありメニューの挿入位置がズレました。pixivはユーザー毎にアプデ時期にズレがあるため全体に反映されているかは不明です。
メニューがサイト名より上に来るようになったので、コードの158行目にある以下の部分を変更する事でサイト名の下に表示する事ができました。
位置が気になる方はお試しください。

変更前
document.getElementById('root').firstElementChild;
変更後
document.getElementById('root').children[1];

Firefoxで使う時

イラストページ等でメニューが表示されないかもしれません。
多分スクリプトの実行順の問題だと思うんですが知識不足によりスマートな解決法がわからず…とりあえず以下の部分を

insert.parentNode.insertBefore(navi, insert.nextSibling);

こんな感じで少し遅らせて実行すれば一応追加されます。

if( !insert ) {
	timeoutID = window.setTimeout( ()=> {
		insert = document.getElementById('root').firstElementChild;
		insert.parentNode.insertBefore(navi, insert.nextSibling);
	}, 1000);
} else {
	insert.parentNode.insertBefore(navi, insert.nextSibling);
}

コメント

タイトルとURLをコピーしました