您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
dアニメストアに様々な機能を追加します
// ==UserScript== // @name dアニメストアPlus // @namespace https://github.com/chimaha/dAnimePlus // @match https://animestore.docomo.ne.jp/animestore/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @version 1.9.3 // @author chimaha // @description dアニメストアに様々な機能を追加します // @license MIT license // @icon https://animestore.docomo.ne.jp/favicon.ico // @compatible firefox // @compatible chrome // @supportURL https://github.com/chimaha/dAnimePlus/issues // ==/UserScript== /*! dアニメストアPlus | MIT license | https://github.com/chimaha/dAnimePlus/blob/main/LICENSE */ /*! *dアニメストア便利化 (https://greasyfork.org/ja/scripts/414008) *Copyright (c) 2020 家守カホウ *Released under the MIT license. *see https://opensource.org/licenses/MIT */ "use strict"; // 解像度表示 + 制作年度表示------------------------------------------------------------------ let qualityCount = 0; function addResolutionStyle() { if (document.getElementById("resolution-style")) { return; } document.head.insertAdjacentHTML("beforeend", '<style id="resolution-style"></style>'); document.head.lastElementChild.textContent = ` .quality, .production-year { position: absolute; top: 3px; border-radius: 4px; padding: 0.5px 4px; background-color: rgba(255,255,255,0.8); text-decoration: none !important; } .quality { left: 3px; } .production-year { right: 3px; } .quality > span, .production-year > span { font-size: 11px; font-weight: bold; text-decoration: none !important; }`; } function sort(workids, json) { const sorted = []; const yearSorted = []; for (const workid of workids) { const item = json.find((res) => res["id"] == workid); sorted.push(item["distribution"]["quality"]); yearSorted.push(item["details"]["production_year"]); } return [sorted, yearSorted]; } function resolutionBranch(div, quality) { switch (quality) { case "fhd": div("1080p"); break; case "hd": div("720p"); break; default: div("480p"); } } function qualityAndYear(torf) { addResolutionStyle(); const playerMypage = document.querySelectorAll(".thumbnailContainer > a"); if (playerMypage.length == 0) { return; } let workIds = []; for (let i = 0; i < playerMypage.length; i++) { const workId = new URL(document.querySelectorAll(".textContainer[href]")[i]).searchParams.get( "workId" ); workIds.push(workId); } workIds = workIds.slice(qualityCount); const fetchAsync = async () => { const url = "https://animestore.docomo.ne.jp/animestore/rest/v1/works?work_id=" + workIds.join(","); const response = await fetch(url); const json = await response.json(); const [sorted, yearSorted] = sort(workIds, json); for (let i = 0; i < sorted.length; i++) { const quality = sorted[i]; const year = yearSorted[i]; function div(quality) { let headerquality = ""; if (torf) { if (resolutionbool) { headerquality += ` <div class="quality"> <span>${quality}</span> </div> `; } if (addProductionYear) { headerquality += ` <div class="production-year"> <span>${year}年</span> </div> `; } } else { headerquality = ` <div class="quality"> <span>${quality}</span> </div>`; } playerMypage[i + qualityCount].insertAdjacentHTML("beforeend", headerquality); } resolutionBranch(div, quality); } qualityCount = qualityCount + sorted.length; }; fetchAsync(); } // ----------------------------------------------------------------------------------------- // サムネイルとテキストをクリックすると新規タブで開く + mouseover ------------------------------- function addHoverStyle() { if (!document.getElementById("mouseover-style")) { document.head.insertAdjacentHTML("beforeend", '<style id="mouseover-style"></style>'); document.head.lastElementChild.textContent = ` .textContainer:hover { cursor: pointer; } .itemModuleIn:hover .textContainer { text-decoration: underline; } .itemModuleIn:hover .thumbnailContainer > a > .imgWrap16x9 { opacity : .6; }`; } } function thumbnailclick() { const playerMypage = document.querySelectorAll(".thumbnailContainer > a"); if (playerMypage.length == 0) { return; } for (let i = 0; i < playerMypage.length; i++) { playerMypage[i].removeAttribute("onclick"); const getHref = document.querySelectorAll(".textContainer[href]")[i]; const urlGet = new URL(getHref.getAttribute("href")); const partId = urlGet.searchParams.get("partId"); const openUrl = "https://animestore.docomo.ne.jp/animestore/sc_d_pc?partId=" + partId; // サムネイルとテキストをクリックすると新規タブで開く playerMypage[i].addEventListener("click", () => { open(openUrl); }); getHref.addEventListener("click", () => { open(openUrl); }); } const getHref = document.querySelectorAll(".textContainer[href]"); for (let i = 0; i < getHref.length; i++) { getHref[i].removeAttribute("href"); } addHoverStyle(); } // ----------------------------------------------------------------------------------------- // 検索結果で常に順番の選択肢を表示 function showOrder() { document.head.insertAdjacentHTML("beforeend", '<style id="show-order"></style>'); document.head.lastElementChild.textContent = ` .minict_wrapper > span { display: none; } .minict_wrapper > ul { display: flex !important; border: none; border-top: none; box-shadow: none; width: max-content; background: none; top: -20px; right: -10px; opacity: 1 !important; user-select: none; } .minict_wrapper > ul > li { padding: 20px 30px; border-bottom: none; }`; } function restCount() { const observer = new MutationObserver(() => { qualityCount = 0; }); const config = { childList: true }; observer.observe(document.querySelector(".listHeader > p.headerText"), config); } // 解像度を表示選択 let resolutionbool = GM_getValue("menu", true); let addProductionYear = GM_getValue("addProductionYear", false); let titlebool = GM_getValue("seekbarTitle", true); let hideDetailBool = GM_getValue("hideDetail", false); const path = window.location.pathname.replace("/animestore/", ""); if (path == "mpa_fav_pc" || path == "mpa_hst_pc") { // 気になる、視聴履歴 if (resolutionbool) { qualityAndYear(false); } thumbnailclick(); } else if (path == "mp_viw_pc") { // 続きから見る const playerMypage = document.querySelectorAll(".thumbnailContainer > a"); for (let i = 0; i < playerMypage.length; i++) { const workId = new URL( document.querySelectorAll(".textContainer")[i].getAttribute("href") ).searchParams.get("workId"); // header作成 const hrefLink = "https://animestore.docomo.ne.jp/animestore/ci_pc?workId=" + workId; const title = document.querySelectorAll(".textContainer h2.line1 > span")[i].textContent; const id1 = workId.slice(0, 2); const id2 = workId.slice(2, 4); const id3 = workId.slice(4, 5); const imgId = "https://cs1.animestore.docomo.ne.jp/anime_kv/img/" + id1 + "/" + id2 + "/" + id3 + "/" + workId + "_1_3.png"; const header = ` <header class=""> <a href="${hrefLink}"> <p class="line2"><span class="ui-clamp webkit2LineClamp">${title}</span></p> <div class="titleThumbnail"> <div class="titleThumbnailIn"> <i class="icon "></i> <div class="imgWrap16x9"> <img class=" verticallyLong lazyloaded" src="${imgId}" alt="パッケージ画像" width="640" height="360"> </div> </div> </div> </a> </header>`; document.querySelectorAll(".itemModule > section")[i].insertAdjacentHTML("afterbegin", header); } if (resolutionbool) { qualityAndYear(false); } thumbnailclick(); } else if (path == "tp_pc") { // トップページ // 「現在放送中のアニメ」リンク先変更 let eventStop = false; let addOpen = false; const observer = new MutationObserver(() => { // リンク先変更 const itemLists = document.querySelectorAll(".itemWrapper > .p-slider__item > a.c-slide"); if (itemLists.length == 0) { return; } for (const itemList of itemLists) { const workId = new URL(itemList.getAttribute("href")).searchParams.get("workId"); const url = "https://animestore.docomo.ne.jp/animestore/ci_pc?workId=" + workId; itemList.setAttribute("href", `${url}`); } // 新規ウィンドウで開くeventを無効化 const playerImg = document.querySelectorAll(".thumbnailContainer > a > .imgWrap16x9")[0]; if (!eventStop && playerImg) { playerImg.addEventListener("click", (e) => { e.stopPropagation(); }); document .querySelector(".thumbnailContainer > a > .progress") .addEventListener("click", (e) => { e.stopPropagation(); }); eventStop = true; // アイコンのeventが削除できないので、imgWrap16x9の子に移動する const iconPlay = document.querySelector(".thumbnailContainer > a > i"); iconPlay ? playerImg.appendChild(iconPlay) : ""; // サムネイルをクリックすると新規タブで開く const openUrl = "https://animestore.docomo.ne.jp/animestore/sc_d_pc?partId=" + document.querySelector(".thumbnailContainer > a").getAttribute("data-partid"); if (!addOpen) { document.querySelector(".pageHeader").addEventListener("click", () => { open(openUrl); }); // 画像をホバーしても、上のでは動かないので playerImg.addEventListener("click", () => { open(openUrl); }); addOpen = true; } } // タイトルwidth、ホバー if (!document.getElementById("mouseover-style")) { document.head.insertAdjacentHTML("beforeend", '<style id="mouseover-style"></style>'); document.head.lastElementChild.textContent = ` @media screen and (min-width: 960px) { .pageHeader .subTitle { margin: 5px 0 0 5px !important; width: 100% !important; } .pageHeader .information, .pageHeader .thumbnailContainer { float: none !important; } .pageHeader .pageHeaderIn { display: flex !important; width: fit-content !important; } .pageHeader .information { max-width: 693px; width: fit-content !important; margin-left: 15px; } } .pageHeader .btnResume { display: none; } .pageHeader .thumbnailContainer { order: 0; margin-left: 0 !important; } .pageHeader .information { order: 1; } .pageHeader .title { width: 100% !important; } .pageHeader .subTitle > p { width: 100%; transform: none !important; transition: none !important; overflow: hidden; text-overflow: ellipsis; } .pageHeader:hover { cursor: pointer; } .pageHeader:hover :is(.title, .subTitle > p) { text-decoration: underline; } .pageHeader:hover .imgWrap16x9 { opacity : .6; }`; } if (resolutionbool) { addResolutionStyle(); const playerSlider = document.querySelectorAll( '.p-slider__item:not(.add-resolution,.isBlack,[data-link^="/animestore/series?seriesId="]) > div > input[data-workid]' ); if (playerSlider.length == 0) { return; } const insertTarget = document.querySelectorAll( `.p-slider__item:not(.add-resolution,.isBlack,[data-link^="/animestore/series?seriesId="]) > a.c-slide > .isAnime:not(.isOnAir)` ); const addClassTarget = document.querySelectorAll( '.p-slider__item:not(.add-resolution,.isBlack,[data-link^="/animestore/series?seriesId="]):has(> div > input[data-workid])' ); let workIds = []; for (let i = 0; i < playerSlider.length; i++) { const workId = playerSlider[i].getAttribute("data-workid"); addClassTarget[i].classList.add("add-resolution"); workIds.push(workId); } const fetchAsync = async () => { const url = "https://animestore.docomo.ne.jp/animestore/rest/v1/works?work_id=" + workIds.join(","); const response = await fetch(url); const json = await response.json(); const [sorted, yearSorted] = sort(workIds, json); for (let i = 0; i < sorted.length; i++) { const quality = sorted[i]; function div(quality) { insertTarget[i].insertAdjacentHTML( "afterend", `<div class="quality"><span>${quality}</span></div>` ); } resolutionBranch(div, quality); } }; fetchAsync(); } }); const config = { childList: true, subtree: true }; observer.observe(document.body, config); setTimeout(function () { observer.disconnect(); }, 2000); } else if (path == "ci_pc") { // 作品ページ const playerImges = document.querySelectorAll("section.clearfix > a"); for (const playerImg of playerImges) { const openUrl = "https://animestore.docomo.ne.jp/animestore/sc_d_pc" + playerImg.getAttribute("href").slice(5); // 詳しく見るを開かずに、タブで動画を開く playerImg.addEventListener("click", () => { open(openUrl); }); playerImg.style.cursor = "pointer"; playerImg.removeAttribute("href"); } } else if (path == "sc_d_pc") { // 再生画面 const video = document.querySelector("video"); const observerTarget = document.querySelector(".backInfoTxt1"); const observer = new MutationObserver(() => { // 再生ウィンドウ名をアニメ名に変更 const animeTitle = observerTarget.textContent; document.title = animeTitle; // シークバーにタイトルと話数を表示 const episode = document.querySelector(".backInfoTxt2").textContent; // 保存した音量に変更 const getVolume = GM_getValue("volume"); video.volume = getVolume ? getVolume : ""; let addElement; if (document.getElementById("volumeText") == undefined) { addElement = ` <div id="volumeText" style="display: table; position: relative; width: 25px; right: 5px;"> <span style="display: table-cell; color: #a0a09f; font-weight: 600; vertical-align: middle;"> ${Math.round(video.volume * 100)} </span> </div> `; } if (titlebool && document.getElementById("title") == undefined) { addElement += ` <div id="title" style="display: table; margin-left: 20px;"> <span style="display: table-cell; color: #a0a09f; font-weight: 700; vertical-align: middle;"> ${animeTitle} ${episode} </span> </div> `; } else if (titlebool) { document.querySelector("#title>span").textContent = `${animeTitle} ${episode}`; } addElement && document.querySelector(".buttonArea > .volume").insertAdjacentHTML("afterend", addElement); }); const config = { childList: true }; observer.observe(observerTarget, config); observer.disconnect; // マウスホイールで音量変更 window.addEventListener("wheel", (e) => { const wheelDelta = Math.sign(e.deltaY); let volume = video.volume; if (wheelDelta === 1) { volume -= 0.02; } else if (wheelDelta === -1) { volume += 0.02; } volume = Math.max(0, Math.min(volume, 1)); video.volume = volume; GM_setValue("volume", volume); const span = ` <span style="display: table-cell; color: #a0a09f; font-weight: 600; vertical-align: middle;"> ${Math.round(video.volume * 100)} </span> `; document.querySelector("#volumeText").innerHTML = span; }); // 音量バーを操作した場合 let isDragging = false; document.querySelector("#volumePopupIn").addEventListener("mousedown", (e) => { isDragging = true; }); document.addEventListener("mouseup", () => { isDragging = false; }); document.addEventListener("mousemove", () => { if (isDragging) { GM_setValue("volume", video.volume); document.querySelector("#volumeText > span").textContent = Math.round(video.volume * 100); } }); // 上下キーで音量変更した場合 document.addEventListener("keyup", (e) => { if (e.key == "ArrowDown" || e.key == "ArrowUp") { document.querySelector("#volumeText > span").textContent = Math.round(video.volume * 100); } }); // マウスホイールで動画の再生位置を移動 window.addEventListener("wheel", (e) => { const video = document.querySelector("video"); const wheelDelta = Math.sign(e.deltaX); const skipTime = 10; if (wheelDelta === 1) { video.currentTime -= skipTime; } else if (wheelDelta === -1) { video.currentTime += skipTime; } }); } else if ( path == "sch_pc" || path == "gen_pc" || path == "c_all_pc" || path == "series_pc" || path == "tag_pc" ) { // 検索結果、シリーズ、ランキング showOrder(); restCount(); addHoverStyle(); // 解像度表示 if (resolutionbool || addProductionYear) { const observer2 = new MutationObserver(() => { qualityAndYear(true); }); const config = { childList: true }; observer2.observe(document.querySelector("#listContainer"), config); } } else if (path == "mpa_cmp_pc") { // コンプリート // 解像度表示 if (resolutionbool) { qualityAndYear(false); } } else if (path == "CF/mylist_detail" || path == "mpa_shr_pc") { // リスト // 解像度表示 if (resolutionbool) { const observer = new MutationObserver(() => { addResolutionStyle(); if (document.querySelectorAll(".p-mylistItemList__item > a > .quality")[0]) { return; } const playerMypage = document.querySelectorAll(".p-mylistItemList__item > a"); let workIds = []; for (let i = 0; i < playerMypage.length; i++) { const workId = new URL(playerMypage[i].getAttribute("href")).searchParams.get("workId"); workIds.push(workId); } const fetchAsync = async () => { const url = "https://animestore.docomo.ne.jp/animestore/rest/v1/works?work_id=" + workIds.join(","); const response = await fetch(url); const json = await response.json(); const [sorted, yearSorted] = sort(workIds, json); for (let i = 0; i < sorted.length; i++) { const quality = sorted[i]; function div(quality) { const headerquality = ` <div class="quality"> <span>${quality}</span> </div>`; playerMypage[i].insertAdjacentHTML("beforeend", headerquality); } resolutionBranch(div, quality); } }; fetchAsync(); }); const config = { childList: true, subtree: true }; observer.observe(document.querySelector(".p-mylistItemList"), config); setTimeout(function () { observer.disconnect(); }, 2000); } } // 詳しく見るを非表示 if (!hideDetailBool) { document.head.insertAdjacentHTML("beforeend", '<style id="hide-detail"></style>'); document.head.lastElementChild.textContent = ` .itemModule > section > .detail { display: none; }`; } // 解像度を表示設定 let resolutionText = resolutionbool ? "解像度を表示:ON✔️" : "解像度を表示:OFF❌"; GM_registerMenuCommand(resolutionText, () => { if (resolutionbool) { GM_setValue("menu", false); } else { GM_setValue("menu", true); } }); let productionYearText = addProductionYear ? "制作年を表示:ON✔️" : "制作年を表示:OFF❌"; GM_registerMenuCommand(productionYearText, () => { if (addProductionYear) { GM_setValue("addProductionYear", false); } else { GM_setValue("addProductionYear", true); } }); // シークバーにタイトルと音量を表示設定 let titleText = titlebool ? "シークバーにタイトルを表示:ON✔️" : "シークバーにタイトルを表示:OFF❌"; GM_registerMenuCommand(titleText, () => { if (titlebool) { const showTitle = false; GM_setValue("seekbarTitle", showTitle); } else { const showTitle = true; GM_setValue("seekbarTitle", showTitle); } }); // 詳しく見るを非表示 let hideDetailText = hideDetailBool ? "詳しく見るを表示:ON✔️" : "詳しく見るを表示:OFF❌"; GM_registerMenuCommand(hideDetailText, () => { if (hideDetailBool) { GM_setValue("hideDetail", false); } else { GM_setValue("hideDetail", true); } });