计时器掌控者|视频广告跳过|视频广告加速器

控制网页计时器速度|加速跳过页面计时广告|视频快进(慢放)|跳过广告|支持几乎所有网页.

安装此脚本?
作者推荐脚本

您可能也喜欢万用网页标记器

安装此脚本
  1. // ==UserScript==
  2. // @name 计时器掌控者|视频广告跳过|视频广告加速器
  3. // @name:en TimerHooker
  4. // @namespace https://gitee.com/HGJing/everthing-hook/
  5. // @version 1.0.62
  6. // @description 控制网页计时器速度|加速跳过页面计时广告|视频快进(慢放)|跳过广告|支持几乎所有网页.
  7. // @description:en it can hook the timer speed to change.
  8. // @include *
  9. // @require https://gf.qytechs.cn/scripts/372672-everything-hook/code/Everything-Hook.js?version=881251
  10. // @author Cangshi
  11. // @match http://*/*
  12. // @run-at document-start
  13. // @grant none
  14. // @license GPL-3.0-or-later
  15. // ==/UserScript==
  16. /**
  17. * ---------------------------
  18. * Time: 2017/11/20 19:28.
  19. * Author: Cangshi
  20. * View: http://palerock.cn
  21. * ---------------------------
  22. */
  23.  
  24. /**
  25. * 1. hook Object.defineProperty | Object.defineProperties
  26. * 2. set configurable: true
  27. * 3. delete property
  28. * 4. can set property for onxx event method
  29. */
  30.  
  31. window.isDOMLoaded = false;
  32. window.isDOMRendered = false;
  33.  
  34. document.addEventListener('readystatechange', function () {
  35. if (document.readyState === "interactive" || document.readyState === "complete") {
  36. window.isDOMLoaded = true;
  37. }
  38. });
  39.  
  40. ~function (global) {
  41.  
  42. var workerURLs = [];
  43. var extraElements = [];
  44. var suppressEvents = {};
  45.  
  46. var helper = function (eHookContext, timerContext, util) {
  47. return {
  48. applyUI: function () {
  49. var style = '._th-container ._th-item{margin-bottom:3px;position:relative;width:0;height:0;cursor:pointer;opacity:.3;background-color:aquamarine;border-radius:100%;text-align:center;line-height:30px;-webkit-transition:all .35s;-o-transition:all .35s;transition:all .35s;right:30px}._th-container ._th-item,._th-container ._th-click-hover,._th_cover-all-show-times ._th_times{-webkit-box-shadow:-3px 4px 12px -5px black;box-shadow:-3px 4px 12px -5px black}._th-container:hover ._th-item._item-x2{margin-left:18px;width:40px;height:40px;line-height:40px}._th-container:hover ._th-item._item-x-2{margin-left:17px;width:38px;height:38px;line-height:38px}._th-container:hover ._th-item._item-xx2{width:36px;height:36px;margin-left:16px;line-height:36px}._th-container:hover ._th-item._item-xx-2{width:32px;height:32px;line-height:32px;margin-left:14px}._th-container:hover ._th-item._item-reset{width:30px;line-height:30px;height:30px;margin-left:10px}._th-click-hover{position:relative;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s;height:45px;width:45px;cursor:pointer;opacity:.3;border-radius:100%;background-color:aquamarine;text-align:center;line-height:45px;right:0}._th-container:hover{left:-5px}._th-container{font-size:12px;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s;left:-35px;top:20%;position:fixed;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:100000;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}._th-container ._th-item:hover{opacity:.8;background-color:#5fb492;color:aliceblue}._th-container ._th-item:active{opacity:.9;background-color:#1b3a26;color:aliceblue}._th-container:hover ._th-click-hover{opacity:.8}._th-container:hover ._th-item{opacity:.6;right:0}._th-container ._th-click-hover:hover{opacity:.8;background-color:#5fb492;color:aliceblue}._th_cover-all-show-times{position:fixed;top:0;right:0;width:100%;height:100%;z-index:99999;opacity:1;font-weight:900;font-size:30px;color:#4f4f4f;background-color:rgba(0,0,0,0.1)}._th_cover-all-show-times._th_hidden{z-index:-99999;opacity:0;-webkit-transition:1s all;-o-transition:1s all;transition:1s all}._th_cover-all-show-times ._th_times{width:300px;height:300px;border-radius:50%;background-color:rgba(127,255,212,0.51);text-align:center;line-height:300px;position:absolute;top:50%;right:50%;margin-top:-150px;margin-right:-150px}';
  50.  
  51. var displayNum = (1 / timerContext._percentage).toFixed(2);
  52.  
  53. // 在页面左边添加一个半圆便于修改
  54. var html = '<div class="_th-container">\n' +
  55. ' <div class="_th-click-hover _item-input">\n' +
  56. ' x' + displayNum + '\n' +
  57. ' </div>\n' +
  58. ' <div class="_th-item _item-x2">&gt;</div>\n' +
  59. ' <div class="_th-item _item-x-2">&lt;</div>\n' +
  60. ' <div class="_th-item _item-xx2">&gt;&gt;</div>\n' +
  61. ' <div class="_th-item _item-xx-2">&lt;&lt;</div>\n' +
  62. ' <div class="_th-item _item-reset">O</div>\n' +
  63. '</div>\n' +
  64. '<div class="_th_cover-all-show-times _th_hidden">\n' +
  65. ' <div class="_th_times">x' + displayNum + '</div>\n' +
  66. '</div>' +
  67. '';
  68. var stylenode = document.createElement('style');
  69. stylenode.setAttribute("type", "text/css");
  70. if (stylenode.styleSheet) {// IE
  71. stylenode.styleSheet.cssText = style;
  72. } else {// w3c
  73. var cssText = document.createTextNode(style);
  74. stylenode.appendChild(cssText);
  75. }
  76. var node = document.createElement('div');
  77. node.innerHTML = html;
  78.  
  79. var clickMapper = {
  80. '_item-input': function () {
  81. changeTime();
  82. },
  83. '_item-x2': function () {
  84. changeTime(2, 0, true);
  85. },
  86. '_item-x-2': function () {
  87. changeTime(-2, 0, true);
  88. },
  89. '_item-xx2': function () {
  90. changeTime(0, 2);
  91. },
  92. '_item-xx-2': function () {
  93. changeTime(0, -2);
  94. },
  95. '_item-reset': function () {
  96. changeTime(0, 0, false, true);
  97. }
  98. };
  99.  
  100. Object.keys(clickMapper).forEach(function (className) {
  101. var exec = clickMapper[className];
  102. var targetEle = node.getElementsByClassName(className)[0];
  103. if (targetEle) {
  104. targetEle.onclick = exec;
  105. }
  106. });
  107.  
  108. if (!global.isDOMLoaded) {
  109. document.addEventListener('readystatechange', function () {
  110. if ((document.readyState === "interactive" || document.readyState === "complete") && !global.isDOMRendered) {
  111. document.head.appendChild(stylenode);
  112. document.body.appendChild(node);
  113. global.isDOMRendered = true;
  114. console.log('Time Hooker Works!');
  115. }
  116. });
  117. } else {
  118. document.head.appendChild(stylenode);
  119. document.body.appendChild(node);
  120. global.isDOMRendered = true;
  121. console.log('Time Hooker Works!');
  122. }
  123. },
  124. applyGlobalAction: function (timer) {
  125. // 界面半圆按钮点击的方法
  126. timer.changeTime = function (anum, cnum, isa, isr) {
  127. if (isr) {
  128. global.timer.change(1);
  129. return;
  130. }
  131. if (!global.timer) {
  132. return;
  133. }
  134. var result;
  135. if (!anum && !cnum) {
  136. var t = prompt("输入欲改变计时器变化倍率(当前:" + 1 / timerContext._percentage + ")");
  137. if (t == null) {
  138. return;
  139. }
  140. if (isNaN(parseFloat(t))) {
  141. alert("请输入正确的数字");
  142. timer.changeTime();
  143. return;
  144. }
  145. if (parseFloat(t) <= 0) {
  146. alert("倍率不能小于等于0");
  147. timer.changeTime();
  148. return;
  149. }
  150. result = 1 / parseFloat(t);
  151. } else {
  152. if (isa && anum) {
  153. if (1 / timerContext._percentage <= 1 && anum < 0) {
  154. return;
  155. }
  156. result = 1 / (1 / timerContext._percentage + anum);
  157. } else {
  158. if (cnum <= 0) {
  159. cnum = 1 / -cnum
  160. }
  161. result = 1 / ((1 / timerContext._percentage) * cnum);
  162. }
  163. }
  164. timer.change(result);
  165. };
  166. global.changeTime = timer.changeTime;
  167. },
  168. applyHooking: function () {
  169. var _this = this;
  170. // 劫持循环计时器
  171. eHookContext.hookReplace(window, 'setInterval', function (setInterval) {
  172. return _this.getHookedTimerFunction('interval', setInterval);
  173. });
  174. // 劫持单次计时
  175. eHookContext.hookReplace(window, 'setTimeout', function (setTimeout) {
  176. return _this.getHookedTimerFunction('timeout', setTimeout)
  177. });
  178. // 劫持循环计时器的清除方法
  179. eHookContext.hookBefore(window, 'clearInterval', function (method, args) {
  180. _this.redirectNewestId(args);
  181. });
  182. // 劫持循环计时器的清除方法
  183. eHookContext.hookBefore(window, 'clearTimeout', function (method, args) {
  184. _this.redirectNewestId(args);
  185. });
  186. var newFunc = this.getHookedDateConstructor();
  187. eHookContext.hookClass(window, 'Date', newFunc, '_innerDate', ['now']);
  188. Date.now = function () {
  189. return new Date().getTime();
  190. };
  191. eHookContext.hookedToString(timerContext._Date.now, Date.now);
  192. var objToString = Object.prototype.toString;
  193.  
  194. Object.prototype.toString = function toString() {
  195. 'use strict';
  196. if (this instanceof timerContext._mDate) {
  197. return '[object Date]';
  198. } else {
  199. return objToString.call(this);
  200. }
  201. };
  202.  
  203. eHookContext.hookedToString(objToString, Object.prototype.toString);
  204. eHookContext.hookedToString(timerContext._setInterval, setInterval);
  205. eHookContext.hookedToString(timerContext._setTimeout, setTimeout);
  206. eHookContext.hookedToString(timerContext._clearInterval, clearInterval);
  207. timerContext._mDate = window.Date;
  208. this.hookShadowRoot();
  209. },
  210. getHookedDateConstructor: function () {
  211. return function () {
  212. if (arguments.length === 1) {
  213. Object.defineProperty(this, '_innerDate', {
  214. configurable: false,
  215. enumerable: false,
  216. value: new timerContext._Date(arguments[0]),
  217. writable: false
  218. });
  219. return;
  220. } else if (arguments.length > 1) {
  221. var definedValue;
  222. switch (arguments.length) {
  223. case 2:
  224. definedValue = new timerContext._Date(
  225. arguments[0],
  226. arguments[1]
  227. );
  228. break;
  229. case 3:
  230. definedValue = new timerContext._Date(
  231. arguments[0],
  232. arguments[1],
  233. arguments[2],
  234. );
  235. break;
  236. case 4:
  237. definedValue = new timerContext._Date(
  238. arguments[0],
  239. arguments[1],
  240. arguments[2],
  241. arguments[3],
  242. );
  243. break;
  244. case 5:
  245. definedValue = new timerContext._Date(
  246. arguments[0],
  247. arguments[1],
  248. arguments[2],
  249. arguments[3],
  250. arguments[4]
  251. );
  252. break;
  253. case 6:
  254. definedValue = new timerContext._Date(
  255. arguments[0],
  256. arguments[1],
  257. arguments[2],
  258. arguments[3],
  259. arguments[4],
  260. arguments[5]
  261. );
  262. break;
  263. default:
  264. case 7:
  265. definedValue = new timerContext._Date(
  266. arguments[0],
  267. arguments[1],
  268. arguments[2],
  269. arguments[3],
  270. arguments[4],
  271. arguments[5],
  272. arguments[6]
  273. );
  274. break;
  275. }
  276.  
  277. Object.defineProperty(this, '_innerDate', {
  278. configurable: false,
  279. enumerable: false,
  280. value: definedValue,
  281. writable: false
  282. });
  283. return;
  284. }
  285. var now = timerContext._Date.now();
  286. var passTime = now - timerContext.__lastDatetime;
  287. var hookPassTime = passTime * (1 / timerContext._percentage);
  288. // console.log(__this.__lastDatetime + hookPassTime, now,__this.__lastDatetime + hookPassTime - now);
  289. Object.defineProperty(this, '_innerDate', {
  290. configurable: false,
  291. enumerable: false,
  292. value: new timerContext._Date(timerContext.__lastMDatetime + hookPassTime),
  293. writable: false
  294. });
  295. };
  296. },
  297. getHookedTimerFunction: function (type, timer) {
  298. var property = '_' + type + 'Ids';
  299. return function () {
  300. var uniqueId = timerContext.genUniqueId();
  301. var callback = arguments[0];
  302. if (typeof callback === 'string') {
  303. callback += ';timer.notifyExec(' + uniqueId + ')';
  304. arguments[0] = callback;
  305. }
  306. if (typeof callback === 'function') {
  307. arguments[0] = function () {
  308. var returnValue = callback.apply(this, arguments);
  309. timerContext.notifyExec(uniqueId);
  310. return returnValue;
  311. }
  312. }
  313. // 储存原始时间间隔
  314. var originMS = arguments[1];
  315. // 获取变速时间间隔
  316. arguments[1] *= timerContext._percentage;
  317. var resultId = timer.apply(window, arguments);
  318. // 保存每次使用计时器得到的id以及参数等
  319. timerContext[property][resultId] = {
  320. args: arguments,
  321. originMS: originMS,
  322. originId: resultId,
  323. nowId: resultId,
  324. uniqueId: uniqueId,
  325. oldPercentage: timerContext._percentage,
  326. exceptNextFireTime: timerContext._Date.now() + originMS
  327. };
  328. return resultId;
  329. };
  330. },
  331. redirectNewestId: function (args) {
  332. var id = args[0];
  333. if (timerContext._intervalIds[id]) {
  334. args[0] = timerContext._intervalIds[id].nowId;
  335. // 清除该记录id
  336. delete timerContext._intervalIds[id];
  337. }
  338. if (timerContext._timeoutIds[id]) {
  339. args[0] = timerContext._timeoutIds[id].nowId;
  340. // 清除该记录id
  341. delete timerContext._timeoutIds[id];
  342. }
  343. },
  344. registerShortcutKeys: function (timer) {
  345. // 快捷键注册(不可用)
  346. addEventListener('keydown', function (e) {
  347. switch (e.keyCode) {
  348. case 57:
  349. if (e.ctrlKey || e.altKey) {
  350. // custom
  351. timer.changeTime();
  352. }
  353. break;
  354. // [=]
  355. case 190:
  356. case 187: {
  357. if (e.ctrlKey) {
  358. // console.log('+2');
  359. timer.changeTime(2, 0, true);
  360. } else if (e.altKey) {
  361. // console.log('xx2');
  362. timer.changeTime(0, 2);
  363. }
  364. break;
  365. }
  366. // [-]
  367. case 188:
  368. case 189: {
  369. if (e.ctrlKey) {
  370. // console.log('-2');
  371. timer.changeTime(-2, 0, true);
  372. } else if (e.altKey) {
  373. // console.log('xx-2');
  374. timer.changeTime(0, -2);
  375. }
  376. break;
  377. }
  378. // [0]
  379. case 48: {
  380. if (e.ctrlKey || e.altKey) {
  381. // console.log('reset');
  382. timer.changeTime(0, 0, false, true);
  383. }
  384. break;
  385. }
  386. default:
  387. // console.log(e);
  388. }
  389. });
  390. },
  391. /**
  392. * 当计时器速率被改变时调用的回调方法
  393. * @param percentage
  394. * @private
  395. */
  396. percentageChangeHandler: function (percentage) {
  397. // 改变所有的循环计时
  398. util.ergodicObject(timerContext, timerContext._intervalIds, function (idObj, id) {
  399. idObj.args[1] = Math.floor((idObj.originMS || 1) * percentage);
  400. // 结束原来的计时器
  401. this._clearInterval.call(window, idObj.nowId);
  402. // 新开一个计时器
  403. idObj.nowId = this._setInterval.apply(window, idObj.args);
  404. });
  405. // 改变所有的延时计时
  406. util.ergodicObject(timerContext, timerContext._timeoutIds, function (idObj, id) {
  407. var now = this._Date.now();
  408. var exceptTime = idObj.exceptNextFireTime;
  409. var oldPercentage = idObj.oldPercentage;
  410. var time = exceptTime - now;
  411. if (time < 0) {
  412. time = 0;
  413. }
  414. var changedTime = Math.floor(percentage / oldPercentage * time);
  415. idObj.args[1] = changedTime;
  416. // 重定下次执行时间
  417. idObj.exceptNextFireTime = now + changedTime;
  418. idObj.oldPercentage = percentage;
  419. // 结束原来的计时器
  420. this._clearTimeout.call(window, idObj.nowId);
  421. // 新开一个计时器
  422. idObj.nowId = this._setTimeout.apply(window, idObj.args);
  423. });
  424. },
  425. hookShadowRoot: function () {
  426. var origin = Element.prototype.attachShadow;
  427. eHookContext.hookAfter(Element.prototype, 'attachShadow',
  428. function (m, args, result) {
  429. extraElements.push(result);
  430. return result;
  431. }, false);
  432. eHookContext.hookedToString(origin, Element.prototype.attachShadow);
  433. },
  434. hookDefine: function () {
  435. const _this = this;
  436. eHookContext.hookBefore(Object, 'defineProperty', function (m, args) {
  437. var option = args[2];
  438. var ele = args[0];
  439. var key = args[1];
  440. var afterArgs = _this.hookDefineDetails(ele, key, option);
  441. afterArgs.forEach((arg, i) => {
  442. args[i] = arg;
  443. })
  444. });
  445. eHookContext.hookBefore(Object, 'defineProperties', function (m, args) {
  446. var option = args[1];
  447. var ele = args[0];
  448. if (ele && ele instanceof Element) {
  449. Object.keys(option).forEach(key => {
  450. var o = option[key];
  451. var afterArgs = _this.hookDefineDetails(ele, key, o);
  452. args[0] = afterArgs[0];
  453. delete option[key];
  454. option[afterArgs[1]] = afterArgs[2]
  455. })
  456. }
  457. })
  458. },
  459. hookDefineDetails: function (target, key, option) {
  460. if (option && target && target instanceof Element && typeof key === 'string' && key.indexOf('on') >= 0) {
  461. option.configurable = true;
  462. }
  463. if (target instanceof HTMLVideoElement && key === 'playbackRate') {
  464. option.configurable = true;
  465. console.warn('[Timer Hook]', '已阻止默认操作视频倍率');
  466. key = 'playbackRate_hooked'
  467. }
  468. return [target, key, option];
  469. },
  470. suppressEvent: function (ele, eventName) {
  471. if (ele) {
  472. delete ele['on' + eventName];
  473. delete ele['on' + eventName];
  474. delete ele['on' + eventName];
  475. ele['on' + eventName] = undefined;
  476. }
  477. if (!suppressEvents[eventName]) {
  478. eHookContext.hookBefore(EventTarget.prototype, 'addEventListener',
  479. function (m, args) {
  480. var eName = args[0];
  481. if (eventName === eName) {
  482. console.warn(eventName, 'event suppressed.')
  483. args[0] += 'suppressed';
  484. }
  485. }, false);
  486. suppressEvents[eventName] = true;
  487. }
  488. },
  489. changePlaybackRate: function (ele, rate) {
  490. delete ele.playbackRate;
  491. delete ele.playbackRate;
  492. delete ele.playbackRate;
  493. ele.playbackRate = rate
  494. if (rate !== 1) {
  495. timerContext.defineProperty.call(Object, ele, 'playbackRate', {
  496. configurable: true,
  497. get: function () {
  498. return 1;
  499. },
  500. set: function () {
  501. }
  502. });
  503. }
  504. }
  505. }
  506. };
  507.  
  508. var normalUtil = {
  509. isInIframe: function () {
  510. let is = global.parent !== global;
  511. try {
  512. is = is && global.parent.document.body.tagName !== 'FRAMESET'
  513. } catch (e) {
  514. // ignore
  515. }
  516. return is;
  517. },
  518. listenParentEvent: function (handler) {
  519. global.addEventListener('message', function (e) {
  520. var data = e.data;
  521. var type = data.type || '';
  522. if (type === 'changePercentage') {
  523. handler(data.percentage || 0);
  524. }
  525. })
  526. },
  527. sentChangesToIframe: function (percentage) {
  528. var iframes = document.querySelectorAll('iframe') || [];
  529. var frames = document.querySelectorAll('frame');
  530. if (iframes.length) {
  531. for (var i = 0; i < iframes.length; i++) {
  532. iframes[i].contentWindow.postMessage(
  533. {type: 'changePercentage', percentage: percentage}, '*');
  534. }
  535. }
  536. if (frames.length) {
  537. for (var j = 0; j < frames.length; j++) {
  538. frames[j].contentWindow.postMessage(
  539. {type: 'changePercentage', percentage: percentage}, '*');
  540. }
  541. }
  542. }
  543. };
  544.  
  545. var querySelectorAll = function (ele, selector, includeExtra) {
  546. var elements = ele.querySelectorAll(selector);
  547. elements = Array.prototype.slice.call(elements || []);
  548. if (includeExtra) {
  549. extraElements.forEach(function (element) {
  550. elements = elements.concat(querySelectorAll(element, selector, false));
  551. })
  552. }
  553. return elements;
  554. };
  555.  
  556. var generate = function () {
  557. return function (util) {
  558. // disable worker
  559. workerURLs.forEach(function (url) {
  560. if (util.urlMatching(location.href, 'http.*://.*' + url + '.*')) {
  561. window['Worker'] = undefined;
  562. console.log('Worker disabled');
  563. }
  564. });
  565. var eHookContext = this;
  566. var timerHooker = {
  567. // 用于储存计时器的id和参数
  568. _intervalIds: {},
  569. _timeoutIds: {},
  570. _auoUniqueId: 1,
  571. // 计时器速率
  572. __percentage: 1.0,
  573. // 劫持前的原始的方法
  574. _setInterval: window['setInterval'],
  575. _clearInterval: window['clearInterval'],
  576. _clearTimeout: window['clearTimeout'],
  577. _setTimeout: window['setTimeout'],
  578. _Date: window['Date'],
  579. __lastDatetime: new Date().getTime(),
  580. __lastMDatetime: new Date().getTime(),
  581. videoSpeedInterval: 1000,
  582. defineProperty: Object.defineProperty,
  583. defineProperties: Object.defineProperties,
  584. genUniqueId: function () {
  585. return this._auoUniqueId++;
  586. },
  587. notifyExec: function (uniqueId) {
  588. var _this = this;
  589. if (uniqueId) {
  590. // 清除 timeout 所储存的记录
  591. var timeoutInfos = Object.values(this._timeoutIds).filter(
  592. function (info) {
  593. return info.uniqueId === uniqueId;
  594. }
  595. );
  596. timeoutInfos.forEach(function (info) {
  597. _this._clearTimeout.call(window, info.nowId);
  598. delete _this._timeoutIds[info.originId]
  599. })
  600. }
  601. // console.log(uniqueId, 'called')
  602. },
  603. /**
  604. * 初始化方法
  605. */
  606. init: function () {
  607. var timerContext = this;
  608. var h = helper(eHookContext, timerContext, util);
  609.  
  610. h.hookDefine();
  611. h.applyHooking();
  612.  
  613. // 设定百分比属性被修改的回调
  614. Object.defineProperty(timerContext, '_percentage', {
  615. get: function () {
  616. return timerContext.__percentage;
  617. },
  618. set: function (percentage) {
  619. if (percentage === timerContext.__percentage) {
  620. return percentage;
  621. }
  622. h.percentageChangeHandler(percentage);
  623. timerContext.__percentage = percentage;
  624. return percentage;
  625. }
  626. });
  627.  
  628. if (!normalUtil.isInIframe()) {
  629. console.log('[TimeHooker]', 'loading outer window...');
  630. h.applyUI();
  631. h.applyGlobalAction(timerContext);
  632. h.registerShortcutKeys(timerContext);
  633. } else {
  634. console.log('[TimeHooker]', 'loading inner window...');
  635. normalUtil.listenParentEvent((function (percentage) {
  636. console.log('[TimeHooker]', 'Inner Changed', percentage)
  637. this.change(percentage);
  638. }).bind(this))
  639. }
  640. },
  641. /**
  642. * 调用该方法改变计时器速率
  643. * @param percentage
  644. */
  645. change: function (percentage) {
  646. this.__lastMDatetime = this._mDate.now();
  647. this.__lastDatetime = this._Date.now();
  648. this._percentage = percentage;
  649. var oldNode = document.getElementsByClassName('_th-click-hover');
  650. var oldNode1 = document.getElementsByClassName('_th_times');
  651. var displayNum = (1 / this._percentage).toFixed(2);
  652. (oldNode[0] || {}).innerHTML = 'x' + displayNum;
  653. (oldNode1[0] || {}).innerHTML = 'x' + displayNum;
  654. var a = document.getElementsByClassName('_th_cover-all-show-times')[0] || {};
  655. a.className = '_th_cover-all-show-times';
  656. this._setTimeout.bind(window)(function () {
  657. a.className = '_th_cover-all-show-times _th_hidden';
  658. }, 100);
  659. this.changeVideoSpeed();
  660. normalUtil.sentChangesToIframe(percentage);
  661. },
  662. changeVideoSpeed: function () {
  663. var timerContext = this;
  664. var h = helper(eHookContext, timerContext, util);
  665. var rate = 1 / this._percentage;
  666. rate > 16 && (rate = 16);
  667. rate < 0.065 && (rate = 0.065);
  668. var videos = querySelectorAll(document, 'video', true) || [];
  669. if (videos.length) {
  670. for (var i = 0; i < videos.length; i++) {
  671. h.changePlaybackRate(videos[i], rate);
  672. }
  673. }
  674. }
  675. };
  676. // 默认初始化
  677. timerHooker.init();
  678. return timerHooker;
  679. }
  680. };
  681.  
  682. if (global.eHook) {
  683. global.eHook.plugins({
  684. name: 'timer',
  685. /**
  686. * 插件装载
  687. * @param util
  688. */
  689. mount: generate()
  690. });
  691. }
  692. }(window);

QingJ © 2025

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