Greasy Fork is available in English.
计算B站视频的互动播放比并显示,点击可复制信息并随机显示酷炫或可爱浮动特效
当前为
// ==UserScript==
// @name B站♥视频评级
// @namespace http://tampermonkey.net/
// @version 1.13
// @description 计算B站视频的互动播放比并显示,点击可复制信息并随机显示酷炫或可爱浮动特效
// @author Zola
// @match https://www.bilibili.com/video/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 工具函数:解析包含“万”或“亿”的数字
function parseCount(text) {
if (!text) return 0;
if (text.includes('万')) return parseFloat(text) * 10000;
if (text.includes('亿')) return parseFloat(text) * 100000000;
return parseInt(text.replace(/,/g, '')) || 0;
}
// 计算互动与播放量的比率
function calculateRatio(totalInteractions, viewCount) {
return ((totalInteractions / viewCount) * 100).toFixed(2);
}
// 获取带颜色的评级HTML
function getRating(ratio) {
const r = parseFloat(ratio);
const ratings = [
{ min: 30, text: '满分视频', color: '#02c8d3' },
{ min: 19, text: '好评如潮', color: 'green' },
{ min: 16, text: '特别好评', color: 'limegreen' },
{ min: 14, text: '多半好评', color: 'yellowgreen' },
{ min: 8, text: '褒贬不一', color: 'orange' },
{ min: 4, text: '多半差评', color: 'orangered' },
{ min: 1, text: '差评如潮', color: 'red' },
{ min: 0, text: '惨不忍睹', color: 'grey' }
];
const { text, color } = ratings.find(rating => r >= rating.min) || ratings[ratings.length - 1];
return `<span style="color:${color}">${text}</span>`;
}
// 获取纯文本评级(无HTML)
function getPlainRating(ratio) {
const r = parseFloat(ratio);
if (r > 30) return '满分视频';
if (r >= 19) return '好评如潮';
if (r >= 16) return '特别好评';
if (r >= 14) return '多半好评';
if (r >= 8) return '褒贬不一';
if (r >= 4) return '多半差评';
if (r >= 1) return '差评如潮';
return '惨不忍睹';
}
// 创建并显示浮动特效(随机酷炫或可爱)
function showCopyEffect(event) {
const effect = document.createElement('div');
const isCool = Math.random() > 0.5; // 50%概率选择酷炫或可爱
// 基础样式
effect.style.position = 'absolute';
effect.style.left = `${event.pageX}px`;
effect.style.top = `${event.pageY - 30}px`;
effect.style.padding = '6px 12px';
effect.style.zIndex = '9999';
effect.style.pointerEvents = 'none';
effect.style.opacity = '1';
effect.style.transition = 'all 0.6s ease-out';
if (isCool) {
// 酷炫风格
effect.textContent = 'Copied!';
effect.style.background = 'linear-gradient(45deg, #ff00cc, #3333ff)';
effect.style.color = '#fff';
effect.style.borderRadius = '8px';
effect.style.fontSize = '14px';
effect.style.fontFamily = 'monospace';
effect.style.boxShadow = '0 0 15px rgba(255, 0, 204, 0.8)';
effect.style.transform = 'translateY(0) rotate(5deg)';
setTimeout(() => {
effect.style.opacity = '0';
effect.style.transform = 'translateY(-30px) rotate(-5deg)';
}, 50);
} else {
// 可爱风格
effect.textContent = '复制啦~';
effect.style.background = 'rgba(255, 182, 193, 0.9)';
effect.style.color = '#fff';
effect.style.border = '2px solid #ff69b4';
effect.style.borderRadius = '15px';
effect.style.fontSize = '14px';
effect.style.fontFamily = 'Comic Sans MS, cursive';
effect.style.transform = 'translateY(0) scale(1)';
setTimeout(() => {
effect.style.opacity = '0';
effect.style.transform = 'translateY(-20px) scale(1.1)';
}, 50);
}
document.body.appendChild(effect);
setTimeout(() => effect.remove(), 650); // 动画结束后移除
}
// 绑定复制事件
function bindCopyEvent(element, displayText, ratio, viewCount) {
if (element.hasAttribute('data-click-bound')) return;
element.addEventListener('click', (event) => {
event.stopPropagation();
const title = document.title;
const url = `${window.location.origin}${window.location.pathname}`;
const praiseRate = displayText.replace('好评:', '');
const plainRating = viewCount < 1000 ? '' : getPlainRating(ratio);
const textToCopy = `【${title}】【${url}】 好评率: ${praiseRate} 好评分级: ${plainRating}`;
navigator.clipboard.writeText(textToCopy).then(() => {
showCopyEffect(event);
}).catch(err => {
console.error('复制失败:', err);
alert('复制失败,请手动复制');
});
});
element.setAttribute('data-click-bound', 'true');
}
// 创建工具栏元素
function createToolbarItem(className, title, content) {
const wrapper = document.createElement('div');
wrapper.className = 'toolbar-left-item-wrap';
wrapper.setAttribute('data-v-1359e6fc', '');
const item = document.createElement('div');
item.className = `${className} video-toolbar-left-item`;
item.setAttribute('data-v-1359e6fc', '');
item.setAttribute('title', title);
item.innerHTML = `<span class="${className}-info video-toolbar-item-text">${content}</span>`;
wrapper.appendChild(item);
return { wrapper, item };
}
// 更新或添加比率和评级
function updateRatioDisplay() {
const viewText = document.querySelector('.view-text')?.innerText.trim() || '0';
const likeText = document.querySelector('.video-like-info.video-toolbar-item-text')?.innerText.trim().replace(/,/g, '') || '0';
const coinText = document.querySelector('.video-coin-info.video-toolbar-item-text')?.innerText.trim().replace(/,/g, '') || '0';
const favText = document.querySelector('.video-fav-info.video-toolbar-item-text')?.innerText.trim().replace(/,/g, '') || '0';
const shareText = document.querySelector('.video-share-info-text')?.innerText.trim().replace(/,/g, '') || '0';
const viewCount = parseCount(viewText);
const totalInteractions = parseCount(likeText) + parseCount(coinText) + parseCount(favText) + parseCount(shareText);
if (isNaN(viewCount) || isNaN(totalInteractions)) return;
const ratio = viewCount < 1000 ? 0 : calculateRatio(totalInteractions, viewCount);
const displayText = viewCount < 1000 ? '播放不足' : `好评:${(ratio * 5).toFixed(1)}%`;
const ratingText = viewCount < 1000 ? '' : getRating(ratio);
const toolbarLeftMain = document.querySelector('.video-toolbar-left-main');
if (!toolbarLeftMain) return;
let ratioElement = document.querySelector('.video-like-ratio');
let ratingElement = document.querySelector('.video-like-rating');
if (ratioElement) {
ratioElement.querySelector('.video-like-ratio-info').innerText = displayText;
} else {
const { wrapper, item } = createToolbarItem('video-like-ratio', '互动播放比', displayText);
toolbarLeftMain.appendChild(wrapper);
ratioElement = item;
}
if (ratingElement) {
ratingElement.querySelector('.video-like-rating-info').innerHTML = ratingText;
} else {
const { wrapper, item } = createToolbarItem('video-like-rating', '评价', ratingText);
toolbarLeftMain.appendChild(wrapper);
ratingElement = item;
}
bindCopyEvent(ratioElement, displayText, ratio, viewCount);
bindCopyEvent(ratingElement, displayText, ratio, viewCount);
}
// 定期刷新显示
function startPeriodicRefresh() {
setInterval(updateRatioDisplay, 3000);
}
// 初始化
window.addEventListener('load', startPeriodicRefresh);
})();