视频全屏显示时间

因为大多数视频全屏后就看不到时间了,要看时间还得退出全屏,看到有的播放器全屏播放时可以在右上角显示一个系统当前时间,这种方式很不错,所以决定给视频网站也做一个这样的增强。这个脚本的作用只有一个,就是在视频左上角显示一个系统时间,方便全屏看视频期间随时了解时间。

  1. // ==UserScript==
  2. // @name 视频全屏显示时间
  3. // @namespace http://tampermonkey.net/
  4. // @namespace https://www.medfav.com/webnav/
  5. // @version 0.4.11
  6. // @description 因为大多数视频全屏后就看不到时间了,要看时间还得退出全屏,看到有的播放器全屏播放时可以在右上角显示一个系统当前时间,这种方式很不错,所以决定给视频网站也做一个这样的增强。这个脚本的作用只有一个,就是在视频左上角显示一个系统时间,方便全屏看视频期间随时了解时间。
  7. // @description 0.2.1 增加搜狐视频 0.2.2 增加mkv、mp4结尾的链接匹配,时间标签层级从3改为11 0.2.3增加YouTube支持
  8. // @description 0.2.4 增加avi,mov,rmvb,webm,flv格式视频支持;修复带参数的视频链接播放时不显示时间;修复某些页面时间位置不在画面上的问题;
  9. // @description 0.2.5 本次更新为时间标签添加了自由拖动功能,以解决某些视频网站视频右上角水印对时间显示产生干扰;0.2.6 紧急修复一个时间标签拖动的问题,影响0.2.5版,正在使用0.2.5版的尽快升级;0.2.7 修复拖动导致的一些问题 0.2.8 修复一些体验问题 0.2.9 修复拖动时间标签导致视频暂停的问题:
  10. // @description 0.3.0 修复拖动的一些问题;添加 左上角/顶部中间/右上角 三个固定位置循环切换;添加恢复位置功能;0.3.1 修复标签位置调整的一些问题 0.3.2 小样式修复
  11. // @description 0.3.3 移除拖动功能,拖动导致较多问题 0.3.4 修复一些显示问题 0.3.5 增加更多级别字体大小
  12. // @description 0.3.6 增加设置弹框;增加顶部间距设置;增加字体大小设置;优化计时器字体宽度;0.3.7 修复设置界面样式,修改字体样式,添加www.bdys03.com支持;0.3.8 修正上一版为兼容MacOS字体导致Windows字体丑的问题 0.3.9 增加欧乐影院\AcFun\虎牙\斗鱼(标签位置有问题,请通过偏移处理)\YY(首页有遮盖问题,请调节位置解决)\抖音\快手\企鹅体育\芒果TV;增加了左右偏移设置;扩大了偏移范围
  13. // @description 0.4.0 增加仅全屏显示计时器选项;百度网盘使用canvas播放视频,不支持(除非有办法替换成video标签播放);0.4.1 设置窗口允许自由拖动;设置窗口标题栏增加关闭按钮;适配秒懂百科; 0.4.2 修复B站首页Banner显示计时器问题 0.4.3 增加颜色和透明度自定义;增加时钟偏移;增加 hxzxer.com 网站支持; 0.4.4 修复时间格式支持 0.4.5 修复时区问题 0.4.6 修复设置窗口位置问题
  14. // @description 0.4.7 增加隐藏时间条功能,修复潜在的问题;0.4.8 增加显示秒功能,修复一些问题;0.4.9 修复哔哩哔哩直播不显示时间标签;0.4.10 修复TrustedHTML问题 0.4.11 修复上一个版本引入TrustedHTML导致的浏览器兼容性问题
  15. // @author medfav
  16. // @match *://www.tvyb03.com/*
  17. // @match *://lpl.qq.com/*
  18. // @match *://v.qq.com/*
  19. // @match *://live.qq.com/*
  20. // @match *://*.bilibili.com/*/*
  21. // @match *://*.bilibili.com/*?*
  22. // @match *://tv.cctv.com/*
  23. // @match *://www.mgtv.com/*
  24. // @match *://*.iqiyi.com/*
  25. // @match *://*.youku.com/*
  26. // @match *://*.le.com/*
  27. // @match *://weibo.com/*
  28. // @match *://*.sohu.com/*
  29. // @match *://*.youtube.com/*
  30. // @match *://*.acfun.cn/*
  31. // @match *://*.huya.com/*
  32. // @match *://*.douyu.com/*
  33. // @match *://*.yy.com/*
  34. // @match *://*.douyin.com/*
  35. // @match *://*.kuaishou.com/*
  36. // @match *://*.ixigua.com/*
  37. // @match *://*.gfysys1.com/*
  38. // @match *://*.buyaotou.xyz/*
  39. // @match *://*.bdys03.com/*
  40. // @match *://*.olevod.com/*
  41. // @match *://pan.baidu.com/*
  42. // @match *://baike.baidu.com/video*
  43. // @match *://hxzxer.com/*
  44. // @match *://*/*.mkv*
  45. // @match *://*/*.mp4*
  46. // @match *://*/*.avi*
  47. // @match *://*/*.mov*
  48. // @match *://*/*.rmvb*
  49. // @match *://*/*.webm*
  50. // @match *://*/*.flv*
  51. // @match *://*/*.m3u8*
  52. // @grant GM_registerMenuCommand
  53. // @grant GM_setValue
  54. // @grant GM_getValue
  55. // @icon https://www.google.com/s2/favicons?sz=64&domain=qq.com
  56. // @run-at document-end
  57. // @grant unsafeWindow
  58. // @license GPLv3
  59. // ==/UserScript==
  60.  
  61. (function() {
  62. 'use strict';
  63.  
  64. // Your code here...
  65. // let timerInterval = 0;
  66. let fullShow = GM_getValue("fullShow");
  67. let hideTimeBar = GM_getValue("hideTimeBar");
  68. let showSecond = GM_getValue("showSecond");
  69. let pos = GM_getValue("pos");//左(0)、中(1)、右(2)
  70. let pos_top_space = GM_getValue("pos_top");//标签和顶部的距离
  71. let pos_transverse_space = GM_getValue("pos_transverse");//标签左右偏移
  72. let fontSize_min = GM_getValue("min_font");//最小
  73. let fontSize_small = GM_getValue("small_font");//小
  74. let fontSize_medium = GM_getValue("medium_font");//中等
  75. let fontSize_large = GM_getValue("large_font");//大
  76. let fontSize_max = GM_getValue("max_font");//最大
  77. let fontStyle = "微软雅黑";//字体样式
  78. let fontColor = GM_getValue("font_color");//字体颜色
  79. let bgColor = GM_getValue("bg_color");//背景颜色
  80. let barOpacity = GM_getValue("bar_opacity");//时间标签整体透明度
  81. let timeOffset = GM_getValue("time_offset");//时间偏移
  82. // if(pos == undefined){
  83. // GM_setValue("pos",2);
  84. // pos = 2;
  85. // }
  86. // if(pos_top_space == undefined){
  87. // GM_setValue("pos_top",10);
  88. // pos_top_space = 10;
  89. // }
  90. // 初始化值
  91. fullShow = (fullShow == undefined)?false:fullShow;
  92. hideTimeBar = (hideTimeBar == undefined)?false:hideTimeBar;
  93. showSecond = (showSecond == undefined)?true:showSecond;
  94. pos = (pos == undefined)?2:pos;
  95. pos_top_space = (pos_top_space == undefined)?10:pos_top_space;
  96. pos_transverse_space = (pos_transverse_space == undefined)?0:pos_transverse_space;
  97.  
  98. fontSize_min = (fontSize_min == undefined)?10:fontSize_min;
  99. fontSize_small = (fontSize_small == undefined)?10:fontSize_small;
  100. fontSize_medium = (fontSize_medium == undefined)?20:fontSize_medium;
  101. fontSize_large = (fontSize_large == undefined)?24:fontSize_large;
  102. fontSize_max = (fontSize_max == undefined)?28:fontSize_max;
  103.  
  104. fontColor = (fontColor == undefined)?"#e1e1e1ff":fontColor;
  105. bgColor = (bgColor == undefined)?"#0000004d":bgColor;
  106. barOpacity = (barOpacity == undefined)?1:barOpacity;
  107. timeOffset = (timeOffset == undefined)?8:timeOffset;
  108.  
  109. let menu1 = GM_registerMenuCommand ("设置", openSetting, "");
  110. // // 计时器位置
  111. // var pos = 2;
  112. // // 计时器字体大小
  113. // var fontSize = 32;
  114. // // 计时器字体
  115. // var fontStyle = "微软雅黑";
  116.  
  117. function openSetting() {
  118. var settingBox = document.querySelector("#vt-setting");
  119. if(settingBox){
  120. return;
  121. }
  122. var settingStyle = document.createElement("style");
  123. settingStyle.type="text/css";
  124. settingStyle.id="vt-classs";
  125. var settingStyleInner = `
  126. div#vt-setting {
  127. top: 200px;
  128. left: calc(100vw - 300px);
  129. width: 250px;
  130. border: 1px solid gray;
  131. position: absolute;
  132. display: block;
  133. z-index: 100000;
  134. margin: 0;
  135. padding: 0;
  136. border-radius: 6px;
  137. font-size: small;
  138. color: black;
  139. background-color: white;
  140. }
  141. #vts-title {
  142. background-color:gray;
  143. display: inline-block;
  144. width: 100%;
  145. border-top-left-radius: 5px;
  146. border-top-right-radius: 5px;
  147. padding: 3px 0px;
  148. text-align: center;
  149. color: white;
  150. cursor: move;
  151. hight: 20px;
  152. line-hight: 20px;
  153. user-select:none;
  154. }
  155. #vts-close-btn {
  156. right: 0px;top:
  157. 0px;font-size: 17px;
  158. position: absolute;
  159. background-color: #d77c84;
  160. width: 44px;
  161. height: 26px;
  162. line-hight: 27px;
  163. border-top-right-radius: 5px;
  164. user-select:none;
  165. }
  166. #vts-close-btn:hover {
  167. background-color: #e81123;
  168. cursor: default;
  169. }
  170. #vts-pos input,#vts-general input {
  171. margin-right: 5px;
  172. }
  173. #vts-pos input:is(:nth-child(4),:nth-child(6)) {
  174. margin-left: 35px;
  175. }
  176. .vts-fieldset {
  177. border: 1px solid #c7c7c7;
  178. padding: 5px;
  179. margin: auto 5px;
  180. }
  181. .vts-fieldset>legend {
  182. font-size: small;
  183. color: gray;
  184. width: auto;
  185. padding: 0px 5px;
  186. }
  187. #vts-font input,#vts-pos-top,#vts-pos-transverse,#vts-font-style-name,#vts-color input {
  188. width: 110px;
  189. font-size: revert;
  190. outline: revert;
  191. border: revert;
  192. appearance: revert;
  193. }
  194. .vts-input-number,.vts-input,.vts-select {
  195. line-height: revert;
  196. appearance: revert;
  197. margin-top: 1px;
  198. }
  199. .vts-select {
  200. margin-top: 2px;
  201. }
  202. #vts-font select {
  203. width: 150px;
  204. }
  205. #vts-submit {
  206. margin-top: 10px;
  207. text-align: center;
  208. }
  209. #vts-submit>input {
  210. margin: 0;
  211. padding: 0 10px;
  212. appearance: auto;
  213. border: revert;
  214. border-radius: revert;
  215. background: revert;
  216. font-size: revert;
  217. }
  218. #vts-submit>input:not(:first-child) {
  219. margin-left: 20px;
  220. }
  221. #vts-save.disable {
  222. cursor: not-allowed;
  223. pointer-events: none;
  224. background-color: #c0c0c0;
  225. border-color: #8a8a8a;
  226. border-width: 1px;
  227. border-radius: 3px;
  228. color: azure;
  229. padding: 1px 10px;
  230. }
  231. #vts-tips {
  232. font-size: 13px;
  233. color: green;
  234. margin: 10px auto 5px 10px;
  235. }`;
  236. settingStyle.textContent = settingStyleInner;
  237. document.querySelector("head").appendChild(settingStyle);
  238. // CreateStyleElement("vt-classs", settingStyleInner, false)
  239.  
  240. settingBox = document.createElement("div");
  241. settingBox.id = "vt-setting";
  242. var innerHtml = `<span id="vts-title">设置
  243. <span id="vts-close-btn">╳</span>
  244. </span>
  245. <div id="vts-general">
  246. <fieldset class="vts-fieldset">
  247. <legend>通用设置</legend>
  248. <input type="checkbox" name="show-full-screen" id="vts-general-check0">
  249. <label for="left">仅全屏时显示</label>
  250. <input type="checkbox" name="hide-time-bar" id="vts-general-check1">
  251. <label for="left">隐藏时间条</label><br>
  252. <input type="checkbox" name="show-second" id="vts-general-check2">
  253. <label for="left">显示秒</label><br>
  254. <label title="时钟偏移,范围-12 ~ 14,单位小时">时钟偏移💬:</label><input type="number" name="time-offset" id="vts-time-offset"
  255. class="vts-input-number" min="-12" max="14" value="8">
  256. </fieldset>
  257. </div>
  258. <div id="vts-pos">
  259. <fieldset class="vts-fieldset">
  260. <legend>计时器位置</legend>
  261. <input type="radio" name="timer-position" id="vts-pos-radio0"><label for="left">左</label>
  262. <input type="radio" name="timer-position" id="vts-pos-radio1"><label for="left">中</label>
  263. <input type="radio" name="timer-position" id="vts-pos-radio2"><label for="left">右</label>
  264. <br><label for="fontSize">顶部距离:</label><input type="number" name="fontSize" id="vts-pos-top"
  265. class="vts-input-number" min="-1000" max="1000" value="10">
  266. <br><label for="fontSize">左右偏移:</label><input type="number" name="fontSize" id="vts-pos-transverse"
  267. class="vts-input-number" min="-2000" max="2000" value="10">
  268. </fieldset>
  269. </div>
  270. <div id="vts-font">
  271. <fieldset class="vts-fieldset">
  272. <legend>计时器字体</legend>
  273. <label title="视频画幅很小时,显示最小字体">最小💬:</label><input type="number" name="fontSize" id="vts-font-size-min"
  274. class="vts-input-number" min="9" max="99" value="10"><br>
  275. <label title="视频画幅小时,显示较小字体">较小💬:</label><input type="number" name="fontSize" id="vts-font-size-small"
  276. class="vts-input-number" min="9" max="99" value="10"><br>
  277. <label title="视频画幅一般大小时,显示一般大小字体">一般💬:</label><input type="number" name="fontSize"
  278. id="vts-font-size-medium" class="vts-input-number" min="9" max="99" value="20"><br>
  279. <label title="视频画幅大时,显示较大字体">较大💬:</label><input type="number" name="fontSize" id="vts-font-size-large"
  280. class="vts-input-number" min="9" max="99" value="24"><br>
  281. <label title="视频画幅很大时,显示最大字体">最大💬:</label><input type="number" name="fontSize" id="vts-font-size-max"
  282. class="vts-input-number" min="9" max="99" value="28"><br />
  283. <br style="display:none;" />
  284. <label for="fontStyle">字体:</label>
  285. <select disabled name="fontStyle" class="vts-select" id="vts-font-style-name">
  286. <option value="微软雅黑">微软雅黑</option>
  287. <option value="宋体">宋体</option>
  288. <option value="黑体">黑体</option>
  289. </select>
  290. </fieldset>
  291. </div>
  292. <div id="vts-color">
  293. <fieldset class="vts-fieldset">
  294. <legend>颜色/透明度</legend>
  295. <label title="文字颜色: CSS支持的所有颜色格式(命名(如:Red、Green、Blue等),hex,rgb,hsl,lch)">前景色💬:</label><input type="text" name="font-color" id="vts-font-color"
  296. class="vts-input" size="9" maxlength="30" value="#e1e1e1ff"><br>
  297. <label title="背景颜色: CSS支持的所有颜色格式(命名(如:Red、Green、Blue等),hex,rgb,hsl,lch)">背景色💬:</label><input type="text" name="bg-color" id="vts-bg-color"
  298. class="vts-input" size="9" maxlength="30" value="#0000004d"><br>
  299. <label title="整体透明度(范围0-1,可以为小数)">透明度💬:</label><input type="number" name="opacity" id="vts-opacity"
  300. class="vts-input-number" step="0.05" min="0" max="1" value="1"><br>
  301. </fieldset>
  302. </div>
  303. <div id="vts-submit">
  304. <input id="vts-save" type="button" value="保存">
  305. <input id="vts-close" type="button" value="关闭">
  306. <input id="vts-reset" type="button" value="重置">
  307. </div>
  308. <div id="vts-tips">Tips:点击保存记住设置</div>`;
  309. const escapeHTMLPolicy = getEscapeHTMLPolicy();
  310. if (escapeHTMLPolicy != undefined ) {
  311. var escaped = getEscapeHTMLPolicy().createHTML(innerHtml);
  312. settingBox.innerHTML = escaped;
  313. } else {
  314. settingBox.innerHTML = innerHtml;
  315. }
  316. document.querySelector("body").appendChild(settingBox);
  317. // 添加事件
  318. document.querySelector("#vts-general-check0").addEventListener("change",function(){radioChange(this.checked,'check')});
  319. document.querySelector("#vts-general-check1").addEventListener("change",function(){radioChange(this.checked,'hidetimebar')});
  320. document.querySelector("#vts-general-check2").addEventListener("change",function(){radioChange(this.checked,'showSecond')});
  321. document.querySelector("#vts-pos-radio0").addEventListener("change",function(){radioChange(0,'radio')});
  322. document.querySelector("#vts-pos-radio1").addEventListener("change",function(){radioChange(1,'radio')});
  323. document.querySelector("#vts-pos-radio2").addEventListener("change",function(){radioChange(2,'radio')});
  324. document.querySelector("#vts-pos-top").addEventListener("input",function(){radioChange(this.value,'top')});
  325. document.querySelector("#vts-pos-transverse").addEventListener("input",function(){radioChange(this.value,'transverse')});
  326. document.querySelector("#vts-font-size-min").addEventListener("input",function(){radioChange(this.value,'fontsize-min')});
  327. document.querySelector("#vts-font-size-small").addEventListener("input",function(){radioChange(this.value,'fontsize-small')});
  328. document.querySelector("#vts-font-size-medium").addEventListener("input",function(){radioChange(this.value,'fontsize-medium')});
  329. document.querySelector("#vts-font-size-large").addEventListener("input",function(){radioChange(this.value,'fontsize-large')});
  330. document.querySelector("#vts-font-size-max").addEventListener("input",function(){radioChange(this.value,'fontsize-max')});
  331.  
  332. document.querySelector("#vts-font-color").addEventListener("input",function(){radioChange(this.value,'font-color')});
  333. document.querySelector("#vts-bg-color").addEventListener("input",function(){radioChange(this.value,'bg-color')});
  334. document.querySelector("#vts-opacity").addEventListener("input",function(){radioChange(this.value,'opacity')});
  335.  
  336. document.querySelector("#vts-time-offset").addEventListener("input",function(){radioChange(this.value,'timeoffset')});
  337.  
  338. document.querySelector("#vts-save").addEventListener("click",vtsSaveSetting);
  339. document.querySelector("#vts-close").addEventListener("click",vtsClose);
  340. document.querySelector("#vts-close-btn").addEventListener("click",vtsClose);
  341. document.querySelector("#vts-reset").addEventListener("click",vtsResetSetting);
  342. initSetting();
  343. // 使设置窗口可拖动:
  344. dragElement(document.getElementById("vt-setting"));
  345. }
  346.  
  347. // 转换为可信元素
  348. function getEscapeHTMLPolicy() {
  349. if (window.trustedTypes && trustedTypes.createPolicy) {
  350. return trustedTypes.createPolicy("myEscapePolicy", {
  351. createHTML: (string) => string,
  352. });
  353. }
  354. return undefined;
  355. }
  356.  
  357. // 初始化设置界面
  358. function initSetting() {
  359. document.querySelector("#vts-general-check0").checked = fullShow;
  360. document.querySelector("#vts-general-check1").checked = hideTimeBar;
  361. document.querySelector("#vts-general-check2").checked = showSecond;
  362. switch (pos) {
  363. case 0:
  364. document.querySelector("#vts-pos-radio0").checked = true;
  365. break;
  366. case 1:
  367. document.querySelector("#vts-pos-radio1").checked = true;
  368. break;
  369. case 2:
  370. document.querySelector("#vts-pos-radio2").checked = true;
  371. }
  372. document.querySelector("#vts-pos-top").value = pos_top_space;
  373. document.querySelector("#vts-pos-transverse").value = pos_transverse_space;
  374. document.querySelector("#vts-font-size-min").value = fontSize_min;
  375. document.querySelector("#vts-font-size-small").value = fontSize_small;
  376. document.querySelector("#vts-font-size-medium").value = fontSize_medium;
  377. document.querySelector("#vts-font-size-large").value = fontSize_large;
  378. document.querySelector("#vts-font-size-max").value = fontSize_max;
  379. //document.querySelector("#vts-font-size-number").value = fontSize;
  380. document.querySelector("#vts-font-color").value = fontColor;
  381. document.querySelector("#vts-bg-color").value = bgColor;
  382. document.querySelector("#vts-opacity").value = barOpacity;
  383. document.querySelector("#vts-time-offset").value = timeOffset;
  384. }
  385.  
  386. var tempPos = 0;
  387. function radioChange(params,type) {
  388. if(type=="check") {
  389. fullShow = params;
  390. }
  391. if(type=="hidetimebar") {
  392. hideTimeBar = params;
  393. }
  394. if(type=="showSecond") {
  395. showSecond = params;
  396. }
  397. if(type=="radio") {
  398. pos = params;
  399. }
  400. if (type=="top") {
  401. if ((params < -1000 || params > 1000)) {
  402. document.querySelector("#vts-save").classList.add("disable");
  403. } else {
  404. pos_top_space = Number(params);
  405. document.querySelector("#vts-save").classList.remove("disable");
  406. }
  407. }
  408. if (type=="transverse") {
  409. if ((params < -2000 || params > 2000)) {
  410. document.querySelector("#vts-save").classList.add("disable");
  411. } else {
  412. pos_transverse_space = Number(params);
  413. document.querySelector("#vts-save").classList.remove("disable");
  414. }
  415. }
  416. if (type=="number") {
  417. if ((params < 9 || params > 99)) {
  418. document.querySelector("#vts-save").classList.add("disable");
  419. } else {
  420. document.querySelector("#vts-save").classList.remove("disable");
  421. }
  422. }
  423. if (type.indexOf("fontsize")==0) {
  424. if ((params < 9 || params > 99)) {
  425. document.querySelector("#vts-save").classList.add("disable");
  426. } else {
  427. switch (type) {
  428. case "fontsize-min":
  429. fontSize_min = params;
  430. break;
  431. case "fontsize-small":
  432. fontSize_small = params;
  433. break;
  434. case "fontsize-medium":
  435. fontSize_medium = params;
  436. break;
  437. case "fontsize-large":
  438. fontSize_large = params;
  439. break;
  440. case "fontsize-max":
  441. fontSize_max = params;
  442. }
  443. fontStyle = "微软雅黑";//字体样式
  444. document.querySelector("#vts-save").classList.remove("disable");
  445. }
  446. }
  447. if (type.indexOf("color")>0) {
  448. if ( isColor(params) ) {
  449. switch (type) {
  450. case "font-color":
  451. fontColor = params;
  452. break;
  453. case "bg-color":
  454. bgColor = params;
  455. break;
  456. }
  457. document.querySelector("#vts-save").classList.remove("disable");
  458. } else {
  459. document.querySelector("#vts-save").classList.add("disable");
  460. }
  461. }
  462. if (type == "opacity") {
  463. if (params < 0 || params >1 ) {
  464. document.querySelector("#vts-save").classList.add("disable");
  465. } else {
  466. barOpacity = params;
  467. document.querySelector("#vts-save").classList.remove("disable");
  468. }
  469. }
  470. if (type == "timeoffset") {
  471. if (params < -12 || params > 14 || params % 1 != 0 ) {
  472. document.querySelector("#vts-save").classList.add("disable");
  473. } else {
  474. timeOffset = params;
  475. document.querySelector("#vts-save").classList.remove("disable");
  476. }
  477. }
  478. }
  479.  
  480. // 保存按钮
  481. function vtsSaveSetting() {
  482. //pos = tempPos;
  483. GM_setValue("fullShow",fullShow);
  484. GM_setValue("hideTimeBar",hideTimeBar);
  485. GM_setValue("showSecond",showSecond);
  486. GM_setValue("pos",pos);
  487. GM_setValue("pos_top",pos_top_space);
  488. GM_setValue("pos_transverse",pos_transverse_space);
  489. GM_setValue("min_font",fontSize_min);
  490. GM_setValue("small_font",fontSize_small);
  491. GM_setValue("medium_font",fontSize_medium);
  492. GM_setValue("large_font",fontSize_large);
  493. GM_setValue("max_font",fontSize_max);
  494.  
  495. GM_setValue("font_color",fontColor);
  496. GM_setValue("bg_color",bgColor);
  497. GM_setValue("bar_opacity",barOpacity);
  498.  
  499. GM_setValue("time_offset",timeOffset);
  500.  
  501. //fontSize = document.querySelector("#vts-font-size-number").value;
  502. fontStyle = document.querySelector("#vts-font-style-name").value;
  503.  
  504. let textTips1 = "Tips:保存成功!";
  505. let textTips2 = "Tips:再次保存成功!";
  506. let currentText = document.querySelector("#vts-tips").innerText;
  507. if(currentText == textTips1) {
  508. document.querySelector("#vts-tips").innerText = textTips2;
  509. } else {
  510. document.querySelector("#vts-tips").innerText = textTips1;
  511. }
  512. }
  513. // 取消按钮
  514. function vtsClose() {
  515. var settingBox = document.querySelector("#vt-setting");
  516. var settingStyle = document.querySelector("#vt-classs");
  517. if(settingBox){
  518. settingBox.parentNode.removeChild(settingBox);
  519. }
  520. if(settingStyle){
  521. settingStyle.parentNode.removeChild(settingStyle);
  522. }
  523. }
  524. // 重置按钮
  525. function vtsResetSetting() {
  526. fullShow = false;
  527. hideTimeBar = false;
  528. showSecond = true;
  529. pos = 2;
  530. pos_top_space = 10;
  531. pos_transverse_space = 0;
  532. fontSize_min = 10;//最小
  533. fontSize_small = 10;//小
  534. fontSize_medium = 20;//中等
  535. fontSize_large = 24;//大
  536. fontSize_max = 28;//最大
  537. //fontSize = 32;
  538. fontStyle = "微软雅黑";
  539. fontColor = "#e1e1e1ff";
  540. bgColor = "#0000004d";
  541. barOpacity = 1;
  542. timeOffset = 8;
  543.  
  544. initSetting();
  545. document.querySelector("#vts-tips").innerText = "已重置为默认,点击“保存”记住设置!";
  546. //vtsClose();
  547. }
  548. /**
  549. * [isFullscreen 判断浏览器是否全屏]
  550. * @return [全屏则返回当前调用全屏的元素,不全屏返回false]
  551. */
  552. function isFullscreen(){
  553. return document.fullscreenElement ||
  554. document.msFullscreenElement ||
  555. document.mozFullScreenElement ||
  556. document.webkitFullscreenElement || false;
  557. }
  558.  
  559. // 创建时间标签,width:视频宽度,用于设置时间数字大小
  560. function createTag(element){
  561. let style = "z-index: 101;/*color: #e1e1e1;*/margin:5px;padding: 5px;border-radius: 4px;line-height: 0.8em;/*background-color: #0000004d;opacity: 0.8;*/user-select: none;/*text-shadow: 1px 1px 2px black, -1px -1px 2px black;*/height: min-content;font-family:Arial;font-weight:400;letter-spacing:0px;/*pointer-events: none;*/";
  562. let videoWidth = element.offsetWidth;
  563. let videoTop = element.offsetTop;
  564. let videoLeft = element.offsetLeft;
  565. let space = 10;
  566. let fontSize = 10;
  567. let tagWidth = 50;
  568. if(videoWidth >= 1700){
  569. space = 10;
  570. fontSize = fontSize_max;
  571. tagWidth = 120;
  572. } else if(videoWidth >= 1200){
  573. space = 10;
  574. fontSize = fontSize_large;
  575. tagWidth = 104;
  576. } else if(videoWidth >= 720){
  577. space = 10;
  578. fontSize = fontSize_medium;
  579. tagWidth = 77;
  580. } else if(videoWidth <= 200){
  581. space = 5;
  582. fontSize = fontSize_min;
  583. tagWidth = 50;
  584. } else {
  585. space = 10;
  586. fontSize = fontSize_small;
  587. tagWidth = 50;
  588. }
  589. style += "font-size: "+fontSize+"px;top: " + (videoTop + pos_top_space) + "px;";
  590. style += "color: " + fontColor + ";background-color: " + bgColor + ";opacity: " + barOpacity + ";"
  591. switch(pos) {
  592. case 0:
  593. style += "position: absolute;left: " + videoLeft + pos_transverse_space + space + "px;";
  594. break;
  595. case 1:
  596. style += "position: absolute;left: " + videoLeft + pos_transverse_space + ((videoWidth - tagWidth)/2) + "px;";
  597. break;
  598. case 2:
  599. style += "position: absolute;right: " + videoLeft + pos_transverse_space + space + "px;";
  600. break;
  601. }
  602. let timeBar = document.createElement("div");
  603. timeBar.className = "timer";
  604. timeBar.style = style;
  605. timeBar.title = "点击可临时隐藏时间条";
  606. // CreateStyleElement("timerbar-style", ".timer {" + style + "}", true);
  607. return timeBar;
  608. }
  609.  
  610. // 改变时间标签样式
  611. function changeTag(element){
  612. let fullScreenElement = isFullscreen();
  613. // let settingElement = document.body.querySelector("#vt-setting");
  614. // if(fullScreenElement != false && settingElement != undefined) {
  615. // let fullScrSetting = fullScreenElement.querySelector("#vt-setting");
  616. // if(fullScrSetting == undefined){
  617. // fullScreenElement.querySelector(".timer").parentElement.appendChild(settingElement);
  618. // } else {
  619. // fullScreenElement.remove();
  620. // }
  621. // }
  622. if((fullScreenElement == false && fullShow == true) || hideTimeBar == true){
  623. element.parentElement.querySelector(".timer").style.display = "none";
  624. return;
  625. } else {
  626. element.parentElement.querySelector(".timer").style.display = "unset";
  627. }
  628. let videoTop = element.offsetTop;
  629. let videoLeft = element.offsetLeft;
  630. if(element.offsetWidth > 200){
  631. if(element.offsetWidth >= 1700){
  632. element.parentElement.querySelector(".timer").style.fontSize = fontSize_max + "px";
  633. }else if(element.offsetWidth >= 1200){
  634. element.parentElement.querySelector(".timer").style.fontSize = fontSize_large + "px";
  635. } else if(element.offsetWidth >= 720){
  636. element.parentElement.querySelector(".timer").style.fontSize = fontSize_medium + "px";
  637. } else if(element.offsetWidth <= 200) {
  638. element.parentElement.querySelector(".timer").style.fontSize = fontSize_min + "px";
  639. } else {
  640. element.parentElement.querySelector(".timer").style.fontSize = fontSize_small + "px";
  641. }
  642. // element.previousSibling.style.top = videoTop + 10 + "px";
  643. // element.previousSibling.style.right = videoLeft + 10 + "px";
  644. } else {
  645. // element.previousSibling.style.top = videoTop + 5 + "px";
  646. // element.previousSibling.style.right = videoLeft + 5 + "px";
  647. }
  648. // 改变颜色和透明度
  649. element.parentElement.querySelector(".timer").style.color = fontColor;
  650. element.parentElement.querySelector(".timer").style.backgroundColor = bgColor;
  651. element.parentElement.querySelector(".timer").style.opacity = barOpacity;
  652.  
  653. changePos(element);
  654. }
  655.  
  656. function changePos(videoTag){
  657. let videoTop = videoTag.offsetTop;
  658. let videoLeft = videoTag.offsetLeft;
  659. let videoWidth = videoTag.offsetWidth;
  660. let space = 10;
  661. if(videoWidth <= 200){
  662. space = 5;
  663. } else {
  664. space = 10;
  665. }
  666. videoTag.parentElement.querySelector(".timer").style.top = (videoTop + pos_top_space) + "px";
  667. // videoTag.previousSibling.style.marginTop = space + "px";
  668. switch(pos) {
  669. case 0:
  670. videoTag.parentElement.querySelector(".timer").style.removeProperty("right");
  671. //videoTag.previousSibling.style.position = 'absolute';
  672. videoTag.parentElement.querySelector(".timer").style.left = videoLeft + pos_transverse_space + space + "px";
  673. break;
  674. case 1:
  675. videoTag.parentElement.querySelector(".timer").style.removeProperty("right");
  676. //videoTag.previousSibling.style.position = 'unset';
  677. videoTag.parentElement.querySelector(".timer").style.left = videoLeft + pos_transverse_space + ((videoWidth - videoTag.parentElement.querySelector(".timer").offsetWidth)/2) + "px";
  678. break;
  679. case 2:
  680. videoTag.parentElement.querySelector(".timer").style.removeProperty("left");
  681. //videoTag.previousSibling.style.position = 'absolute';
  682. videoTag.parentElement.querySelector(".timer").style.right = videoLeft + pos_transverse_space + space + "px";
  683. break;
  684. }
  685. }
  686.  
  687. // 获取Video标签
  688. function getVideoTag(){
  689. setTimeout(()=>{
  690. let videoTagList = Array.from(document.getElementsByTagName('video'));
  691. if(videoTagList.length == 0){
  692. getVideoTag();
  693. } else {
  694. insertTimeBar(videoTagList);
  695. // setTimer();
  696. getVideoTag();
  697. }
  698. },1000)
  699. }
  700. getVideoTag();
  701.  
  702. // 加入时间标签
  703. function insertTimeBar(videoTagList){
  704. videoTagList.forEach((element)=>{
  705. if (element.parentElement.querySelector(".timer") == null ){
  706. // 多个时间条不能用同一个对象
  707. let timeBar = createTag(element);
  708. // 给时间标签添加事件
  709. addElementEvent(timeBar);
  710. element.parentElement.insertBefore(timeBar,element);
  711. } else {
  712. changeTag(element);
  713. }
  714. })
  715. }
  716.  
  717. // 给元素添加事件
  718. function addElementEvent(element){
  719. element.onmouseover = function(even) {
  720. even.stopPropagation();
  721. }
  722. element.onmousemove = function(even) {
  723. even.stopPropagation();
  724. }
  725. element.onmouseenter = function(even) {
  726. even.stopPropagation();
  727. }
  728. //点击时临时隐藏时间条
  729. element.onclick = function(even) {
  730. even.stopPropagation();
  731. hideTimeBar = true;
  732. element.style.display = "none";
  733. }
  734. }
  735.  
  736. // 设置计时器
  737. function setTimer(){
  738. // clearInterval(timerInterval);
  739. // timerInterval =
  740. setInterval(()=>{
  741. var date = new Date(Date.now() + (new Date().getTimezoneOffset() + (timeOffset * 60)) * 60 * 1000);
  742. // var hour = date.getHours();
  743. // var min = date.getMinutes()>9?date.getMinutes():'0' + date.getMinutes();
  744. // var sec = date.getSeconds()>9?date.getSeconds():'0' + date.getSeconds();
  745. let timer = document.getElementsByClassName("timer");
  746. // 当没有时间条时,添加(懒加载会出现这种情况)
  747. if(timer == undefined){
  748. let videoTagList = Array.from(document.getElementsByTagName('video'));
  749. insertTimeBar(videoTagList);
  750. }
  751. // 给每一个时间条设置时间
  752. let timeBarList = Array.from(document.getElementsByClassName("timer"));
  753. timeBarList.forEach((timeBar)=>{
  754. timeBar.innerText = showSecond ? formatDateTime(date, "H:mm:ss") : formatDateTime(date, "H:mm");
  755. })
  756. },1000)
  757. }
  758. // 启动计时器
  759. setTimer();
  760.  
  761. function formatDateTime(date, format) {
  762. const o = {
  763. 'M+': date.getMonth() + 1, // 月份
  764. 'd+': date.getDate(), // 日
  765. 'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时
  766. 'H+': date.getHours(), // 小时
  767. 'm+': date.getMinutes(), // 分
  768. 's+': date.getSeconds(), // 秒
  769. 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
  770. S: date.getMilliseconds(), // 毫秒
  771. a: date.getHours() < 12 ? '上午' : '下午', // 上午/下午
  772. A: date.getHours() < 12 ? 'AM' : 'PM', // AM/PM
  773. };
  774. if (/(y+)/.test(format)) {
  775. format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  776. }
  777. for (let k in o) {
  778. if (new RegExp('(' + k + ')').test(format)) {
  779. format = format.replace(
  780. RegExp.$1,
  781. RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
  782. );
  783. }
  784. }
  785. return format;
  786. }
  787.  
  788. // 提示框,调用方法:Toast('提示:好用记得点赞哦!',1000);
  789. let dialog;
  790. let timer;
  791. function Toast(msg,duration){
  792. if(timer != null && dialog != null){
  793. clearTimeout(timer);
  794. document.body.removeChild(dialog);
  795. dialog = null;
  796. }
  797. duration=isNaN(duration)?3000:duration;
  798. dialog = document.createElement('div');
  799. dialog.innerText = msg;
  800. dialog.style.cssText="font-size:.32rem;color:green;background-color:white;border:solid green 2px;padding:10px 15px;margin:0 0 0 -60px;border-radius:4px;position:fixed;top:2%;left:93%;/*width:200px;*/text-align:left;z-index:9999";
  801. document.body.appendChild(dialog);
  802. timer = setTimeout(function() {
  803. document.body.removeChild(dialog);
  804. dialog = null;
  805. }, duration);
  806. }
  807.  
  808. // 移动设置窗口
  809. function dragElement(elmnt) {
  810. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  811. var originalonmousemove = null, originalonmouseup = null;
  812. if (document.getElementById("vts-title")) {
  813. // 如果存在,标题是您从中移动 DIV 的位置:
  814. document.getElementById("vts-title").onmousedown = dragMouseDown;
  815. // 防止在子元素上拖动
  816. document.getElementById("vts-title").children.onmousedown = function(){};
  817. } else {
  818. // 否则,从 DIV 内的任何位置移动 DIV:
  819. elmnt.onmousedown = dragMouseDown;
  820. }
  821. elmnt.onmouseup = closeDragElement;
  822.  
  823. function dragMouseDown(e) {
  824. e = e || window.event;
  825. if(e.target.id == "vts-close-btn"){
  826. return;
  827. }
  828. e.preventDefault();
  829. // 在启动时获取鼠标光标位置:
  830. pos3 = e.clientX;
  831. pos4 = e.clientY;
  832. // 记录原事件
  833. originalonmousemove = document.onmousemove;
  834. originalonmouseup = document.onmouseup;
  835. // 每当光标移动时调用一个函数:
  836. document.onmousemove = elementDrag;
  837. document.onmouseup = closeDragElement;
  838. }
  839.  
  840. function elementDrag(e) {
  841. e = e || window.event;
  842. e.preventDefault();
  843. // 计算新的光标位置:
  844. pos1 = pos3 - e.clientX;
  845. pos2 = pos4 - e.clientY;
  846. pos3 = e.clientX;
  847. pos4 = e.clientY;
  848. // 设置元素的新位置:
  849. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  850. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  851. }
  852.  
  853. function closeDragElement() {
  854. // 释放鼠标按钮时停止移动:
  855. // document.onmousemove = null;
  856. // document.onmouseup = null;
  857. // 释放鼠标按钮时停止移动,还原原事件
  858. document.onmousemove = originalonmousemove;
  859. document.onmouseup = originalonmouseup;
  860. }
  861. }
  862.  
  863. function CreateStyleElement(id, cssText, isUpdate){
  864. var styleElement = document.getElementById(id);
  865. if (styleElement == undefined) {
  866. // 创建一个新的 <style> 元素
  867. styleElement = document.createElement("style");
  868. styleElement.id = id;
  869.  
  870. // 创建包含 CSS 规则的文本
  871. // var cssText = ".highlight { background-color: yellow; }"
  872. var cssTextNode = document.createTextNode(cssText);
  873.  
  874. // 将文本添加到 <style> 元素中
  875. styleElement.appendChild(cssTextNode);
  876.  
  877. // 将 <style> 元素添加到网页的 <head> 元素中
  878. document.head.appendChild(styleElement);
  879. } else {
  880. if (isUpdate) {
  881. styleElement.innerText = cssText;
  882. }
  883. }
  884. }
  885.  
  886. function isColor(strColor) {
  887. const s = new Option().style;
  888. s.color = strColor;
  889. return s.color !== '';
  890. }
  891. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址