Greasy Fork

Greasy Fork is available in English.

B站显示点赞率、投币率、收藏率

显示b站 | bilibili | 哔哩哔哩 点赞率、投币率、收藏率

目前为 2024-03-04 提交的版本。查看 最新版本

// ==UserScript==
// @name         B站显示点赞率、投币率、收藏率
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  显示b站 | bilibili | 哔哩哔哩 点赞率、投币率、收藏率
// @license      MIT
// @author       魂hp
// @website    https://space.bilibili.com/474989498
// @match        *.bilibili.com/video/*
// @icon          https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        GM.addStyle
// @grant        unsafeWindow
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
	"use strict";
	if (!(unsafeWindow?.__INITIAL_STATE__?.videoData?.stat?.view)) {
		return;
	}
	// representation字段表示比率的表示形式,该字段为 fractions 时表示为分数,该字段为 percentage 时表示为百分比
	let representation = GM_getValue("representation")
	if (representation == null) {
		GM_setValue("representation", "fractions")
		representation = "fractions"
	}
	const isFractions = representation == "fractions"

	// 注册脚本菜单以实现两种表示方式的相互转换
	GM_registerMenuCommand(
		"切换比率的表示方式(百分比和分数)",
		function () {
			representation = representation == "fractions" ? "percentage" : "fractions"
			GM_setValue("representation", representation)
			unsafeWindow.location.reload()
		}, {
			autoClose: false,
		}
	);

	// 修改样式
	GM.addStyle(`
        .video-toolbar-left-item{
            width:auto !important;
        }
        .toolbar-left-item-wrap{
	         display:flex !important;
             margin-right: 12px !important;
        }
        .video-share-info{
            width:auto !important;
            max-width:90px;
        }
        .video-share-info-text{
            position: relative !important;
        }
    `);
	// 百分比形式会占用更大的空间,需要额外添加样式
	if (!isFractions) {
		GM.addStyle(`
        .video-toolbar-item-icon {
            margin-right:6px !important;
        }
        .toolbar-right-note{
            margin-right:5px !important;
        }
        .toolbar-right-ai{
            margin-right:12px !important;
        }
    `);
	}

	class videoData {
		videoStat = {
			view: 0,
			like: 0,
			coin: 0,
			favorite: 0,
			share: 0
		};
		constructor() {
			this.initVideoStat();
		}
		initVideoStat() {
			for (let key in this.videoStat) {
				this.videoStat[key] = unsafeWindow.__INITIAL_STATE__.videoData.stat[key];
			}
		}
		// 计算点赞率、投币率、收藏率、转发率,并获取对应的颜色
		getRateAndColor(nameStr) {
			let res = {
				rate: 0,
				color: "#222"
			};
			if (!(nameStr in this.videoStat)) {
				return res;
			}
			let num = this.videoStat.view / this.videoStat[nameStr];
			if (num == Infinity) {
				return res;
			}
			// 当比率大于十分之一设置为橘色,大于二十五分之一设置为紫色,其他则设置为黑色(如果需要添加其他的范围对应的颜色或修改颜色可以改这部分)
			if (num <= 10) {
				if (isFractions) {
					res.rate = num.toFixed(2);
				} else {
					res.rate = (this.videoStat[nameStr] * 100 / this.videoStat.view).toFixed(2)
				}
				res.color = "DarkOrange";
			} else if (num <= 25) {
				if (isFractions) {
					res.rate = num.toFixed(1);
				} else {
					res.rate = (this.videoStat[nameStr] * 100 / this.videoStat.view).toFixed(2)
				}
				res.color = "#db03fc";
			} else {
				if (isFractions) {
					res.rate = num.toFixed(0);
				} else {
					res.rate = (this.videoStat[nameStr] * 100 / this.videoStat.view).toFixed(2)
				}
			}
			return res;
		}
	}

	const vData = new videoData();
	//添加元素
	const div = {
		like: {},
		coin: {},
		favorite: {},
		share: {}
	};
	for (let e in div) {
		div[e] = document.createElement("div");
		div[e].style.setProperty("display", "flex")
		div[e].style.setProperty("align-items", "center")
		if (isFractions) {
			div[e].innerHTML = `
			<span style="margin-left: 5px;margin-right: 3px;font-size:medium;">≈</span>
			<math xmlns="http://www.w3.org/1998/Math/MathML" style="font-size: 23px;">
				<mfrac>
					<mrow>
						<mn>1</mn>
						</mrow><mrow>
						<mi id="data"></mi>
					</mrow>
				</mfrac>
			</math>
			`;
		} else {
			div[e].innerHTML = `
			<span style="margin-left: 5px;margin-right: 3px;font-size:medium;">≈</span>
			<span id="data" style="font-family: math;font-size: initial;"></span><span style="font-family: math;margin-left: 2px;"> %</span>
			`
		}

	}
	// 更新数据
	function updateRate() {
		for (let e in div) {
			let data = div[e].querySelector("#data");
			let rateAndColor = vData.getRateAndColor(e);
			data.style.color = rateAndColor.color;
			data.textContent = rateAndColor.rate;
		}
	}
	updateRate();

	new MutationObserver(function (mutationsList) {
		for (let mutation of mutationsList) {
			if (mutation.type === "attributes") {
				document
					.querySelector(".video-like")
					.parentNode.appendChild(div.like);
				document
					.querySelector(".video-coin")
					.parentNode.appendChild(div.coin);
				document
					.querySelector(".video-fav")
					.parentNode.appendChild(div.favorite);
				document
					.querySelector(".video-share-wrap")
					.parentNode.appendChild(div.share);
			}
		}
	}).observe(document.querySelector(".toolbar-left-item-wrap"), {
		attributes: true,
	});

	new MutationObserver(function (mutationsList) {
		for (let mutation of mutationsList) {
			if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
				vData.initVideoStat();
				updateRate();
			}
		}
	}).observe(document.querySelector(".video-fav-info"), {
		childList: true,
	});
})();