// ==UserScript==
// @name bilibili关灯
// @namespace hhh2000
// @version 0.8.4
// @description bilibili关灯(把被新版B站藏起来的关灯按钮揪出来,在关闭弹幕按钮左边,还可以用快捷键,默认'A')、弹幕控制快捷操作、非全屏滚轮音量控制等
// @author hhh2000
// @include *://*.bilibili.com/video/*
// @include *://*.bilibili.tv/video/*
// @include *://*.bilibili.com/bangumi/*
// @include *://*.bilibili.tv/bangumi/*
// @require https://cdn.staticfile.org/jquery/1.12.4/jquery.min.js
// @run-at document-end
// @grant none
// ==/UserScript==
'use strict';
hhh_lightoff_main = {
init() {
var //
fps,
h5Player;
const [BILI_2_X, BILI_3_X, ALL] = ['bili_2.x', 'bili_3.x', 'all'];
var //切换番剧和一般视频class
bb = {},
bb_type = '',
bb_config = {
bb_class_data: {
//'player':{BILI_2_X:'.player', [BILI_3_X]:'.bpx-player'}, //main player
'webFullScreen':{[BILI_2_X]:'.bilibili-player-video-web-fullscreen', [BILI_3_X]:'.squirtle-video-pagefullscreen.squirtle-video-item'}, //网页全屏
'wideScreen':{[BILI_2_X]:'.bilibili-player-video-btn-widescreen', [BILI_3_X]:'.squirtle-video-widescreen.squirtle-video-item'}, //宽屏
'danmukuTopClose':{[BILI_2_X]:'.bilibili-player-block-filter-type[data-name=ctlbar_danmuku_top_close]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeTop.bpx-player-active'}, //顶部弹幕
'danmukuTop' :{[BILI_2_X]:'.bilibili-player-block-filter-type[ftype=top]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeTop'}, //顶部弹幕
'danmukuBottomClose':{[BILI_2_X]:'.bilibili-player-block-filter-type[data-name=ctlbar_danmuku_bottom_close]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeBottom.bpx-player-active'}, //底部弹幕
'danmukuBottom' :{[BILI_2_X]:'.bilibili-player-block-filter-type[ftype=bottom]', [BILI_3_X]:'.bpx-player-block-filter-type.bpx-player-block-typeBottom'}, //底部弹幕
'progressVal' :{[ALL]:'.bui-progress-val'}, //弹幕透明度读数
'progressWrap' :{[ALL]:'.bui-progress-wrap'}, //弹幕透明度进度条
'settingOpacity':{[BILI_2_X]:'.bilibili-player-setting-opacity', [BILI_3_X]:'.bpx-player-dm-setting-ui-opacity'}, //弹幕透明度
'settingArea' :{[BILI_2_X]:'.bilibili-player-setting-area'}, //显示区域
'volumeHint' :{[BILI_2_X]:'.bilibili-player-volumeHint'}, //音量显示
'volumeHintText':{[BILI_2_X]:'.bilibili-player-volumeHint-text'}, //音量显示百分比读数
'volumeHintIcon':{[BILI_2_X]:'.bilibili-player-volumeHint-icon'}, //音量显示图标
'switchBody':{[ALL]:'.bui-switch-body'}, //系统关灯css设置
'switchDot':{[ALL]:'.bui-switch-dot'}, //系统弹幕设置按钮wrap进度条拖动点
'switchInput':{[ALL]:'.bui-switch-input'}, //弹幕设置switch按钮
'danmakuRoot':{[BILI_2_X]:'.bilibili-player-video-danmaku-root', [BILI_3_X]:'.bpx-player-dm-root'}, //系统弹幕设置条
'danmakuSwitch':{[BILI_2_X]:'.bilibili-player-video-danmaku-switch', [BILI_3_X]:'.bpx-player-dm-switch'}, //关闭弹幕按钮
'danmakuSetting':{[BILI_2_X]:'.bilibili-player-video-danmaku-setting', [BILI_3_X]:'bpx-player-dm-setting'}, //系统弹幕设置按钮
'danmakuSettingWrap':{[BILI_2_X]:'.bilibili-player-video-danmaku-setting-wrap', [BILI_3_X]:'.bpx-player-dm-setting-wrap'}, //系统弹幕设置按钮wrap
'videoWrap':{[BILI_2_X]:'.bilibili-player-video-wrap', [BILI_3_X]:'.bpx-player-video-area'}, //播放wrap
'videoContextMenu':{[BILI_2_X]:'.bilibili-player-video-wrap', [BILI_3_X]:'.bpx-player-video-perch'}, //播放contextmenu
'video':{[BILI_2_X]:'.bilibili-player-video', [BILI_3_X]:'.bpx-player-video-wrap'}, //播放
'videoTopMask':{[BILI_2_X]:'.bilibili-player-video-top-mask'}, //全屏时鼠标悬停时产生的顶端mask
'playVideo':{[BILI_2_X]:'.bilibili-player-video-btn'}, //系统设置
'playSetting':{[BILI_2_X]:'.bilibili-player-video-btn-setting'}, //系统播放设置
'playSettingWrap':{[BILI_2_X]:'.bilibili-player-video-btn-setting-wrap'}, //系统播放设置wrap
'playSettingAutoplay':{[BILI_2_X]:'.bilibili-player-video-btn-setting-left-autoplay'}, //自动播放
'playSettingRepeatInput':{[BILI_2_X]:'.bilibili-player-video-btn-setting-left-repeat input', [BILI_3_X]:'input.squirtle-setting-loop'}, //洗脑循环按钮
'playSettingLightoff':{[BILI_2_X]:'.bilibili-player-video-btn-setting-right-others-content-lightoff input', [BILI_3_X]:'.squirtle-single-setting-other-choice.squirtle-lightoff'}, //关灯按钮
'bpxStateLightOff':{[BILI_3_X]:'.bpx-state-light-off'}, //关灯bpx
'playerContextMenu':{[BILI_2_X]:'.bilibili-player-context-menu-container.black.bilibili-player-context-menu-origin', [BILI_3_X]:'.bpx-player-contextmenu.bpx-player-black.bpx-player-active'}, //右键菜单
'hotkeyPanel':{[BILI_2_X]:'.bilibili-player-hotkey-panel'}, //快捷键说明面板
'videoInfo':{[BILI_2_X]:'.bilibili-player-video-info', [BILI_3_X]:'.bpx-player-info'}, //视频统计信息
'videoInfoContainer':{[BILI_2_X]:'.bilibili-player-video-info-container', [BILI_3_X]:'.bpx-player-info-container'}, //视频统计信息
'videoInfoShow':{[BILI_2_X]:'.bilibili-player-video-info-container active', [BILI_3_X]:'.bpx-player-info-container'}, //视频统计信息面板显示
'DOMNodeInsertedVideoInfoShow':{[BILI_2_X]:'.bilibili-player-video-info-container active', [BILI_3_X]:'.info-line'}, //
},
set_bb(bb_type) {
for(var k in this.bb_class_data){
var class_str = this.bb_class_data[k][bb_type]!==undefined? this.bb_class_data[k][bb_type]: this.bb_class_data[k][[ALL]];
bb[k] = class_str;
}
}
};
const [ON, OFF] = [true, false];
var //config
keycode = {
'left': 37,
'right': 39,
'up': 38,
'down': 40,
}
config = {
//一些主要开关设置
sets: {},
getCheckboxSetting(key) {
return this.sets[key]['status'];
},
saveCheckboxSetting() {
for(var o in this){
if(o.indexOf('b_') === 0){
var op = this[o]['options'];
for(var k in op){
this.sets[k] = op[k];
}
}
}
},
b_playerCheckbox: {
options: {
lightOffWhenPlaying: { text: '播放时自动关灯', status: OFF },
lightOnWhenPause: { text: '暂停时自动开灯', status: OFF },
autoPlay: { text: '开启自动播放', status: OFF, fn: '', tips: '' },
repeat: { text: '开启洗脑循环', status: ON, tips: '' },
lightOff: { text: '自动关灯', status: OFF, tips: '' },
volumeControlWhenNonFullScreen: { text: '开启非全屏滚轮音量调节', status: ON, tips: '' },
volumeControlWhenPause: { text: '非全屏暂停时滚轮音量调节', status: ON, tips: '' },
danmuOpacityControl: { text: '开启滚轮弹幕透明度控制', status: ON, tips: '' }, //ctrl+滚轮
removeVideoTopMask: { text: '去掉顶部mask', status: ON, tips: '' },
//不显示有明显变化的提示,关灯、关弹幕等,因为对有些人来说这些操作变化明显可见,提示反而多余且遮挡屏幕
hotKeyHint: { text: '快捷键屏幕提示', status: ON, tips: '' },
},
btn: '设置'
},
//快捷键
QDs: {}, //未使用
getQD(key) {
return this.QDs[key];
}, //未使用
saveQD() {
for (let [key, { value, text }] of Object.entries(this.hotKeyMenu)) {
this.QDs[key] = {value: value, keyCode: value.charCodeAt(), text: text};
}
}, //未使用
hotKeyMenu: { //只是右键菜单的数据,如需改动快捷键改run函数
'lightOff': { value: 'A', text: '关灯/开灯', },
'webFullscreen': { value: 'W', text: '网页全屏', },
'widescreen': { value: 'Q', text: '宽屏模式', },
'danmu': { value: 'D', text: '弹幕/关闭弹幕', },
'danmuTopBottom': { value: 'T/B', text: '顶部/底部弹幕', },
'videoRepeat': { value: 'R', text: '洗脑循环', },
'addsubDanmuOpacity': { value: 'Z/C', text: '减增弹幕透明度10%', },
'quarterArea': { value: '1', text: '1/4屏', },
'halfArea': { value: '2', text: '半屏', },
'threeQuarterArea': { value: '3', text: '3/4屏', },
'nonOverArea': { value: '4', text: '不重叠', },
'fullArea': { value: '5', text: '不限', },
'wheelDanmuOpacity': { value: 'Ctrl + 滚轮', text: '增减弹幕透明度5%', },
'fastForwardBackward30s': { value: 'Ctrl + ←/→', text: '快进/快退30s', },
'1/FPS': { value: 'Shift + ←/→', text: '逐帧操作', },
},
};
function log(e) {console.log(e)}
function dir(e) {console.dir(e)}
function waitForNode(nodeSelector, callback, times) {
if(times < 0) return;
var node = nodeSelector();
if (node) {
callback(node);
} else {
times-=1;
setTimeout(function() { waitForNode(nodeSelector, callback, times); }, 100);
}
}
function waitForTrue(ifTrue, callback) {
if (ifTrue()) {
callback();
} else {
setTimeout(function() { waitForTrue(ifTrue, callback); }, 100);
}
}
function is_fullscreen() {
if(bb_type === BILI_2_X){ return player.isFullScreen() }
else if(bb_type === BILI_3_X){ return $('.bpx-player-container').attr('data-screen') === 'web' || $('.bpx-player-container').attr('data-screen') === 'full' } //normal wide web full
}
function is_lightoff() {
if (bb_type === BILI_2_X) { return !player.getPlayerState().lightOn }
else if(bb_type === BILI_3_X) { return $(bb['playSettingLightoff']).hasClass('active') }
}
function is_danmaku_show(){
return $(bb['danmakuSwitch']+' '+bb['switchInput']+':last')[0].checked;
}
function lightoff() {
$(bb['playSettingLightoff']).click()
}
//关灯按钮样式
function lightoff_btn_css() {
var body_brgb = 'rgb(160, 130, 110)';
var dot_crgb = 'rgb(230, 200, 180)';
var dot_brgb = 'rgb(50, 50, 50)';
var dark_rgb = 'rgb(77, 77, 77)';
if ($('#hhh_lightoff '+bb['switchInput'])[0].checked === false) { //关灯
$('#hhh_lightoff '+bb['switchBody']+':first').css('background-color', dark_rgb);
$('#hhh_lightoff '+bb['switchBody']+':first>'+bb['switchDot']).css('color', dark_rgb);
}
else {
$('#hhh_lightoff '+bb['switchBody']+':first').css('background-color', body_brgb);
$('#hhh_lightoff '+bb['switchBody']+':first>'+bb['switchDot']).css({'color': dot_crgb, 'background-color': dot_brgb});
}
}
//关灯按钮
function lightoff_btn() {
lightoff();
if(is_lightoff() === $('#hhh_lightoff '+bb['switchInput'])[0].checked) { //checked==true开灯 false关灯
$('#hhh_lightoff '+bb['switchInput'])[0].checked = !$('#hhh_lightoff '+bb['switchInput'])[0].checked;
}
lightoff_btn_css();
}
//显示提示
function showHint(parent, selector_str, text){
$(bb['volumeHint']).css('display', 'none'); //隐藏所有提示,避免提示重叠
$(`${selector_str}>${bb['volumeHintText']}`).text(text); //百分比显示
var Hint = $(selector_str); //显示及渐隐效果(抄bilibili^^)
clearTimeout(parent.showHintTimer),
Hint.stop().css("opacity", 1).show(),
parent.showHintTimer = window.setTimeout((function() {
Hint.animate({
opacity: 0
}, 300, (function() {
$(this).hide()
}
))
}
), 1e3)
}
//非全屏滚轮音量调节 0~1 (b站默认滚轮操作某些情况会失效,一并处理全屏情况)
//两个参数指定屏幕范围(按百分比),第三个参数表示滚动一下增加的音量百分比,参数四表示暂停时是否调解
function wheel_volumeHint(screenLeft=0.3, screenRight=0.7, delta=3, isPauseVolume){
//div(抄bilibili^^)
var volumeHint = `<div id=hhh_volumeHint class="${bb['volumeHint'].substr(1)}" style="opacity: 0; display: none;">
<span class="${bb['volumeHintIcon'].substr(1)}">
<i class="bilibili-player-iconfont bilibili-player-iconfont-volume icon-24soundsmall"></i>
<i class="bilibili-player-iconfont bilibili-player-iconfont-volume-max icon-24soundlarge"></i>
<i class="bilibili-player-iconfont bilibili-player-iconfont-volume-min icon-24soundoff"></i>
</span>
<span class="${bb['volumeHintText'].substr(1)}">57%</span>
</div>`;
if($('#hhh_volumeHint').length === 0) $(bb['videoWrap']).append(volumeHint);
//add wheelevent
$(bb['videoWrap']).off('mousewheel.hhh_volumeHint');
$(bb['videoWrap']).on('mousewheel.hhh_volumeHint', function(e){
if(e.ctrlKey || e.altKey || e.shiftKey) return;
//缺省屏幕百分比参数,默认0.3~0.7
screenLeft = (screenLeft<0 || screenLeft>1)? 0.3: screenLeft;
screenRight = (screenRight<0 || screenRight>1)? 0.7: screenRight;
//缺省音量百分比,默认3
delta = (delta<1 || delta>100)? 3: delta;
//非暂停(可选) && 鼠标在屏幕指定位置时处理
var pauseState = isPauseVolume || player.getState() !== 'PAUSED';
var Rect = $(bb['videoWrap'])[0].getBoundingClientRect();
var offsetX = e.originalEvent.x - Rect.x;
var inLimit = offsetX > Rect.width*screenLeft && offsetX < Rect.width*screenRight;
if(is_fullscreen() || (pauseState && inLimit)) {
e.preventDefault(); //阻止页面滚动
e.stopPropagation(); //阻止冒泡
var wheelDelta = e.originalEvent.wheelDelta;
var volume = player.volume();
if(wheelDelta >= 120) { //向上滚动,减少音量
player.volume(volume+(delta/100));
} else if(wheelDelta <= -120) { //向下滚动,增大音量
player.volume(volume-(delta/100));
}
var vol = player.volume();
var $volumeHintIcon = $(`#hhh_volumeHint ${bb['volumeHintIcon']}`);
if(vol <= 0) $volumeHintIcon.attr('class', `${bb['volumeHintIcon'].substr(1)} video-state-volume-min`);
else if(vol >= 1) $volumeHintIcon.attr('class', `${bb['volumeHintIcon'].substr(1)} video-state-volume-max`);
else $volumeHintIcon.attr('class', bb['volumeHintIcon'].substr(1));
if(vol <= 0) showHint(this, '#hhh_volumeHint', '静音');
else showHint(this, '#hhh_volumeHint', Math.round(vol*100)+'%');
}
});
}
/*
* 控制进度条
* .bilibili-player-setting-opacity 透明度
* .bilibili-player-setting-area 显示区域
* .bilibili-player-setting-speedplus 弹幕速度 等
* 利用系统mousedown事件
* 0 ~ 100
*/
function set_progress(selector_str, percent){
var selector = document.querySelector(selector_str);
var e1 = new MouseEvent('mousedown'); var e2 = new MouseEvent('mouseup');
function calc_bar_len(percent, bar_width){
var p = percent - 10;
p = p<0? 0: p>90? 90: p;
return p*bar_width/90; //进度条对应百分比的系统算法
}
$(bb['danmakuSettingWrap']).css({"display":"block"});
var selector_rect = selector.getClientRects();
var clientX = selector_rect[0].left + calc_bar_len(percent, $(`${selector_str} ${bb['progressWrap']}`).innerWidth());
e1.initMouseEvent('mousedown',1,1,window,1,0,0,clientX,0,0,0,0,0,0,null);
e2.initMouseEvent('mouseup' ,1,1,window,1,0,0,clientX,0,0,0,0,0,0,null);
selector.dispatchEvent(e1); selector.dispatchEvent(e2);
$(bb['danmakuSettingWrap']).css({"display":"none"});
$(bb['danmakuSetting']).mouseleave(); //激活设置,记忆进度条位置
return $(`${selector_str} ${bb['progressVal']}`).text();
}
function set_progress2(selector_str, percent){
var selector = document.querySelector(selector_str);
var e1 = new MouseEvent('mousedown'); var e2 = new MouseEvent('mouseup');
function calc_bar_len(percent, bar_width){
var p = percent - 10;
p = p<0? 0: p>90? 90: p;
return p*bar_width/90; //进度条对应百分比的系统算法
}
$(bb['danmakuSettingWrap']).css({"display":"block"});
var selector_rect = selector.getClientRects();
var clientX = selector_rect[0].left + calc_bar_len(percent, $(`${selector_str}>div:first`).innerWidth());
e1.initMouseEvent('mousedown',1,1,window,1,0,0,clientX,0,0,0,0,0,0,null);
e2.initMouseEvent('mouseup' ,1,1,window,1,0,0,clientX,0,0,0,0,0,0,null);
selector.dispatchEvent(e1); selector.dispatchEvent(e2);
$(bb['danmakuSettingWrap']).css({"display":"none"});
$(bb['danmakuSetting']).mouseleave(); //激活设置,记忆进度条位置
return $(`${selector_str}>div:last`).text();
}
/*
* 调节透明度
* 利用系统mousedown事件
* '正数': right, '负数': left, -100 ~ +100
*/
function adjust_progress(selector_str, inc_percent){
var curr_percent = Number($(`${selector_str} ${bb['progressVal']}`).text().slice(0,-1));
return set_progress(selector_str, curr_percent + inc_percent);
}
//滚轮调节弹幕透明度(ctrl),参数表示滚动一下增加的透明度百分比
function wheel_opacity(delta=5){
//add wheelevent
$(bb['videoWrap']).off('mousewheel.hhh_opacity');
$(bb['videoWrap']).on('mousewheel.hhh_opacity', function(e){
if(e.ctrlKey === true) {
//缺省透明度百分比,默认5
delta = (delta<1 || delta>100)? 5: delta;
e.preventDefault(); //阻止页面滚动
e.stopPropagation(); //阻止冒泡
var wheelDelta = e.originalEvent.wheelDelta;
var opacity;
if(wheelDelta >= 120) { //向上滚动,增大透明度
opacity = adjust_progress(bb['settingOpacity'], delta);
} else if(wheelDelta <= -120) { //向下滚动,减少透明度
opacity = adjust_progress(bb['settingOpacity'], -delta);
}
if(opacity !== undefined) showHint(document, '#hhh_opacityHint', '透 '+opacity);
}
});
}
//取得视频FPS(Frames Per Second)
function get_video_fps() {
var evt = new MouseEvent('contextmenu', { clientX:-9999, clientY:-9999 });
$(bb['videoContextMenu'])[0].dispatchEvent(evt);
var oV = $(bb['videoWrap'])[0];
oV.addEventListener('DOMNodeInserted', function(e) {
//bpx...
//if(typeof e.target.className === 'string' && e.target.className.indexOf(`bpx-player-loading-panel-text-row`) !== -1) {
//}
//插入info面板时截取fps值
if(typeof e.target.className === 'string' && e.target.className.indexOf(`${bb['DOMNodeInsertedVideoInfoShow'].substr(1)}`) !== -1) {
this.removeEventListener('DOMNodeInserted', arguments.callee);
if(bb_type === BILI_2_X){
$('.bilibili-player-video-info-close').click(); //模拟关闭统计信息面板
}
else if(bb_type === BILI_3_X){
$('.bpx-player-info-close').click(); //模拟关闭统计信息面板
$('.bpx-player-info-close').click(); //XXX:未知原因,执行一次关不掉面板
}
//text中取得fps值
var get_title_text = function(title) { return $(bb['videoInfoContainer']).find(`.info-title:contains("${title}")`).next().text(); }
fps = Number(get_title_text('Resolution').match(/\d+\.\d+/)) || Number(get_title_text('FPS')) || 30;
}
})
//模拟点击,激活热键菜单DOM
if(bb_type === BILI_2_X) $(`${bb['playerContextMenu']} a:contains("视频统计信息")`).click();
else if(bb_type === BILI_3_X) {
var event = new MouseEvent('mousedown',{ bubbles:true });
$(`${bb['playerContextMenu']} li:contains("视频统计信息")`)[0].dispatchEvent(event);
}
}
//添加右键菜单自定义快捷键说明
function add_custom_hotkey_menu(custom_hotkey) {
if($('#hhh_hotkey').length === 1) return;
//模拟右键菜单消息,激活菜单DOM
var evt = new MouseEvent('contextmenu', { clientX:-9999, clientY:-9999 });
$(bb['videoWrap'])[0].dispatchEvent(evt);
//主class名,没有"."
var hotkey_panel_class = bb['hotkeyPanel'].substr(1);
//右键菜单弹出时添加项
(function add_menu() {
var oV = $(bb['playerContextMenu'])[0];
oV.addEventListener('DOMSubtreeModified', function(e) {
if(typeof e.target.className === 'string' && e.target.className.indexOf(bb['playerContextMenu'].replace(/\./g, ' ').substr(1)) !== -1 && $(this).attr('id') === undefined) {
this.removeEventListener('DOMSubtreeModified', arguments.callee);
var $sys_hotkey = $(this).find('a:contains("快捷键说明")').parent();
var $hhh_hotkey = $sys_hotkey.clone(false, false).insertAfter($sys_hotkey).css('display', '').find('a').text('快捷键说明(bilibili关灯)');
$sys_hotkey.find('a').click(function(){
$('#sys_hotkey').clone(true,true).replaceAll($(`.${hotkey_panel_class}-container:last`)).attr({'id': '', 'class': `${hotkey_panel_class}-container`, 'style': ''});
});
$hhh_hotkey.click(function(){
$('#hhh_hotkey').clone(true,true).replaceAll($(`.${hotkey_panel_class}-container:last`)).attr({'id': '', 'class': `${hotkey_panel_class}-container`, 'style': ''});
});
add_menu();
}
});
})();
//生成自定义快捷键说明页面
(function add_custom_hotkey() {
var oV = $(bb['videoWrap'])[0];
oV.addEventListener('DOMNodeInserted', function(e) {
if(typeof e.target.className === 'string' && e.target.className.indexOf(`${hotkey_panel_class}-container active`) !== -1) {
this.removeEventListener('DOMNodeInserted', arguments.callee);
var $hotkey = $(e.target).attr('class', `${hotkey_panel_class}-container`);
$hotkey.clone().insertBefore($hotkey).attr({'class': '','id': 'sys_hotkey'}).css('display', 'none');
$hotkey.clone().insertBefore($hotkey).attr({'class': '','id': 'hhh_hotkey'}).css('display', 'none');
(function set_custom_hotkey($hotkey, hotkey) {
var $hotkey_panel = $hotkey.find(`.${hotkey_panel_class}:first`);
var $hotkey_item = $hotkey.find(`.${hotkey_panel_class}-item:first`);
$hotkey_panel.empty();
for (let [key, { value, text }] of Object.entries(hotkey)) {
$hotkey_item.clone().appendTo($hotkey_panel);
var $hotkey_key = $hotkey_panel.find(`.${hotkey_panel_class}-key:last`);
$hotkey_key.text(value);
$hotkey_key.next().text(text);
}
})($('#hhh_hotkey'), custom_hotkey);
}
});
})();
//模拟点击,激活热键菜单DOM
$(`${bb['playerContextMenu']} a:contains("快捷键说明")`).click();
}
//主程序
function run(){
waitForNode(() => document.querySelector('video'),
(node) => {
bb_type = $('.bilibili-player-area').length===1? BILI_2_X:$('.bpx-player-primary-area').length===1? BILI_3_X: 'unknown_version';
if(bb_type !== 'unknown_version') bb_config.set_bb(bb_type);
}, 10000);
//未知版本
if(bb_type === 'unknown_version') return;
waitForNode(() => document.querySelector(`${bb['danmakuSwitch']} ${bb['switchDot']}`),
(node) => {
//保存设置信息 && 快捷键信息
config.saveCheckboxSetting();
//防止重复加载
if ($('#hhh_lightoff').length === 1) return;
//取得h5 video
h5Player = $(`#bilibili-player ${bb['video']}>video`)[0];
//取得视频fps
get_video_fps();
//bpx test
function bpx_test(){
log('-------------------');
log('fps: '+fps);
log('------h5Player-----');
dir(h5Player);
log('currentTime : '+h5Player.currentTime);
log('duration : '+h5Player.duration);
log('playbackRate : '+h5Player.playbackRate);
log('volume : '+h5Player.volume);
log('paused : '+h5Player.paused);
log('pause() : '+'h5Player.pause()');
log('videoHeight : '+h5Player.videoHeight);
log('videoWidth : '+h5Player.videoWidth);
log('-------------------');
}
//插入关灯按钮
$(`${bb['danmakuSwitch']}:first`).clone().prependTo(`${bb['danmakuRoot']}:first`)[0].id = 'hhh_lightoff';
$(`#hhh_lightoff ${bb['switchDot']}`)[0].innerHTML = '灯';
//点击关灯
$(`#hhh_lightoff ${bb['switchInput']}:first`).click(function(){ lightoff_btn() });
//初始化关灯按钮
lightoff_btn_css();
//键盘关灯等
var opacity;
var parent = document;
var is_show_hint = config.getCheckboxSetting('hotKeyHint');
$(document).off('keydown.hhh_lightoff');
$(document).on('keydown.hhh_lightoff',function(e){
if(e.shiftKey && (e.keyCode === keycode['left'] || e.keyCode === keycode['right'])) { //逐帧 shift+ left right
h5Player.pause();
h5Player.currentTime = e.keyCode === keycode['left']? h5Player.currentTime - 1/fps: h5Player.currentTime + 1/fps;
} else if(e.ctrlKey && (e.keyCode === keycode['left'] || e.keyCode === keycode['right'])) { //+ -30s ctrl+ left right
h5Player.currentTime = e.keyCode === keycode['left']? h5Player.currentTime - 30: h5Player.currentTime + 30;
}
//以下不使用功能键
if(e.ctrlKey || e.altKey || e.shiftKey) return;
//不使用功能键
if(e.keyCode === 'A'.charCodeAt()){ //开关灯
is_show_hint && (is_lightoff() ? showHint(parent, '#hhh_wordsHint', '开灯') : showHint(parent, '#hhh_wordsHint', '关灯'));
lightoff_btn();
} else if(e.keyCode === 'W'.charCodeAt()) { //网页全屏
$(bb['webFullScreen']).click();
} else if(e.keyCode === 'Q'.charCodeAt()) { //宽屏模式
is_fullscreen() ? $(bb['webFullScreen']).click() : $(bb['wideScreen']).click();
} else if(e.keyCode === 'D'.charCodeAt()) { //开关弹幕
$(bb['danmakuSwitch']+' '+bb['switchInput']+':last').click();
is_show_hint && (is_danmaku_show() === true ? showHint(parent, '#hhh_wordsHint', '开弹幕') : showHint(parent, '#hhh_wordsHint', '关弹幕'));
} else if(e.keyCode === 'T'.charCodeAt()) { //开关顶部弹幕
$(bb['danmukuTopClose']).length === 0 ? showHint(parent, '#hhh_wordsHint', '关闭顶部弹幕') : showHint(parent, '#hhh_wordsHint', '打开顶部弹幕');
$(bb['danmukuTop']).click();
} else if(e.keyCode === 'B'.charCodeAt()) { //开关底部弹幕
$(bb['danmukuBottomClose']).length === 0 ? showHint(parent, '#hhh_wordsHint', '关闭底部弹幕') : showHint(parent, '#hhh_wordsHint', '打开底部弹幕');
$(bb['danmukuBottom']).click();
} else if(e.keyCode === 'R'.charCodeAt()) { //开关洗脑循环
$(bb['playSettingRepeatInput']).click();
} else if(e.keyCode === 'X'.charCodeAt()) { //显示、隐藏video-control
if($('.bilibili-player-area').hasClass('video-control-show') === true) $(bb['videoWrap']).mouseout();
else $(bb['videoWrap']).mousemove();
} else if(e.keyCode === 'Z'.charCodeAt()) { //-弹幕透明度
window.setTimeout((function() { //长按时保持DOM更新
//bpx-player-dm-setting-left-opacity-content
opacity = adjust_progress(bb['settingOpacity'], -10);
showHint(parent, '#hhh_opacityHint', '透 '+opacity);
}),0);
} else if(e.keyCode === 'C'.charCodeAt()) { //+弹幕透明度
window.setTimeout((function() {
opacity = adjust_progress(bb['settingOpacity'], 10);
showHint(parent, '#hhh_opacityHint', '透 '+opacity);
}),0);
} else if(e.keyCode >= '1'.charCodeAt() && e.keyCode <= '5'.charCodeAt()) { //弹幕显示区域
var area_text = {0:'1/4屏',25:'半屏',50:'3/4屏',75:'不重叠',100:'不限'};
var percent = (e.keyCode - '1'.charCodeAt()) * 25; //((0~4)*25)%
set_progress(bb['settingArea'], percent);
showHint(parent, '#hhh_wordsHint', area_text[percent]);
} else if(e.keyCode === keycode['up'] || e.keyCode === keycode['down']) { //
$(bb['volumeHint']).css('display', 'none'); //隐藏所有提示,避免提示重叠
}else{
//console.dir(e);
}
});
//TEST
bpx_test();
if(bb_type === BILI_3_X) return;
//初始化关灯按钮
//lightoff_btn_css();
//激活系统弹幕设置,以此使用网页全屏等
$(bb['danmakuSetting']).mouseenter().mouseleave();
//激活系统关灯设置,以此使用关灯等
//去掉mouseout(),否则如果太快执行mouseout()无法激活关灯class,应该是mouseenter()未执行完就被mouseout打断了
$(`${bb['playVideo']}${bb['playSetting']}`).mouseenter();
//避免显示设置页面
waitForNode(() => document.querySelector(bb['playSettingWrap']),
(node) => {
$(node).css({"visibility":"hidden"}); //visible
})
//解决因为激活关灯class,导致全屏时滚轮操作(系统自带)无法调节音量的问题
waitForTrue(()=> $(bb['playSettingWrap']).css('display') === 'block',
() => {
$(bb['playSettingWrap']).css('display', 'none').css('visibility', 'visible');
});
//非全屏滚轮音量调节
//两个参数指定屏幕范围(按百分比),第三个参数表示滚动一下增加的音量百分比,参数四表示暂停时是否调节
if(config.getCheckboxSetting('volumeControlWhenNonFullScreen') === ON) wheel_volumeHint(0.30, 0.70, 3, config.getCheckboxSetting('volumeControlWhenPause'));
//添加wordsHint opacityHint DOM
$('#hhh_volumeHint').clone().appendTo(bb['videoWrap']).attr('id','hhh_wordsHint')
.css({'opacity':0,'display':'none','width':'auto','margin-left':'0px','padding-left':'8px','padding-right':'15px','transform':'translate(-50%)'})
.find('.bilibili-player-volumeHint-icon').remove().end()
.find('.bilibili-player-volumeHint-text').css({'width': 'auto', 'padding-left': '10px'});
$('#hhh_volumeHint').clone().appendTo(bb['videoWrap']).attr('id','hhh_opacityHint')
.css({'opacity':0,'display':'none'})
.find('.bilibili-player-volumeHint-icon').remove().end()
.find('.bilibili-player-volumeHint-text').css({'padding-right': '6px'});
//滚轮调节弹幕透明度(ctrl),参数表示滚动一下增加的透明度百分比,默认5
if(config.getCheckboxSetting('danmuOpacityControl') === ON) wheel_opacity(5);
//因为遮挡弹幕,去掉全屏时鼠标悬停时产生的顶端mask
if(config.getCheckboxSetting('removeVideoTopMask') === ON) $(bb['videoTopMask']).removeClass();
//添加自定义快捷键说明到右键菜单
add_custom_hotkey_menu(config.hotKeyMenu);
//播放关灯,暂停开灯
player.addEventListener('video_media_playing', () => config.getCheckboxSetting('lightOffWhenPlaying') === ON && !is_lightoff() && lightoff_btn());
player.addEventListener('video_media_pause', () => config.getCheckboxSetting('lightOnWhenPause') === ON && is_lightoff() && lightoff_btn());
//自动运行
if(config.getCheckboxSetting('autoPlay') === ON && $(`${bb['playSettingAutoplay']}>${bb['switchInput']}`)[0].checked === false) //开启自动播放
$(`${bb['playSettingAutoplay']}>${bb['switchInput']}`).click();
if(config.getCheckboxSetting('repeat') === ON) $(bb['playSettingRepeatInput']).click(); //开启洗脑循环
if(config.getCheckboxSetting('lightOff') === ON) lightoff_btn(); //自动关灯
}, 10000);
}
//初始化
function init() {
//内部加载视频窗口
waitForNode(() => document.querySelector('video'),
(node) => {
var oV = document.getElementsByTagName("video")[0];
oV.addEventListener('DOMNodeInserted', () => {
run();
});
});
run();
}
init();
}
}
hhh_lightoff_main.init();