您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A tool adding a touch overlay onto the stream of twitchplayspokemon.
// ==UserScript== // @name Twitch touches pokemon // @namespace https://github.com/lostcoaster/twitch-touches-pokemon // @author lostcoaster // @author MattiasBuelens // @version 1.6 // @description A tool adding a touch overlay onto the stream of twitchplayspokemon. // @grant unsafeWindow // this include string credits Twitch Plays Pokemon Chat Filter // @include /^https?://(www|beta)\.twitch\.tv\/twitchplayspokemon(\/?)$/ // @include /^https?://(www\.)?tinytwit\.ch\/twitchplayspokemon.*$/ // @include /^https?://(www\.)?twitchplayspokemon\.net\/?$/ // ==/UserScript== // for bookmarklet users : javascript:(function(){document.body.appendChild(document.createElement('script')).src='https://raw.githubusercontent.com/lostcoaster/twitch-touches-pokemon/master/touch.user.js';})(); /* jshint lastsemic:true, eqeqeq:true, unused:true */ /* global unsafeWindow:false */ (function () { 'use strict'; // ---------------------------- // Greasemonkey support // ---------------------------- // Greasemonkey userscripts run in a separate environment and cannot use global // variables from the page directly. They need to be accessed via `unsafeWindow` var myWindow; try { myWindow = unsafeWindow; } catch (e) { myWindow = window; } var $ = myWindow.jQuery; var Setting = function (key, defaultValue) { this.key = key; this.defaultValue = defaultValue; this.value = undefined; this.observers = []; }; Setting.prototype.getValue = function () { return (this.value !== undefined) ? this.value : this.defaultValue; }; Setting.prototype.setValue = function (value) { var newValue = (value !== undefined) ? value : this.defaultValue; if (newValue !== this.value) { this.value = newValue; this.fireObservers(newValue); } }; Setting.prototype.restoreDefault = function () { this.setValue(this.defaultValue); }; Setting.prototype.load = function (settings) { this.setValue(settings ? settings[this.key] : undefined); }; Setting.prototype.save = function (settings) { settings[this.key] = this.getValue(); }; Setting.prototype.observe = function (observer) { this.observers.push(observer); }; Setting.prototype.fireObservers = function (value) { for (var i = 0; i < this.observers.length; i++) { this.observers[i].call(null, value, this.key, this); } }; Setting.prototype.bind = function (input) { input = $(input); if (input.is(':checkbox')) { this.bindCheckbox(input); } }; Setting.prototype.bindCheckbox = function (checkbox) { var self = this; // set current value checkbox.prop('checked', this.getValue()); // bind checkbox to setting this.observe(function (newValue) { checkbox.prop('checked', newValue); }); // bind setting to checkbox checkbox.change(function () { self.setValue(checkbox.prop('checked')); }); }; var forIn = function (obj, f) { for (var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { f(k, obj[k]); } } }; var touch_pad = { parameters: { position_x: 0.359, position_y: 0.548, original_height: 434, bar_height: 30, ratio: 9 / 16, screen_height: 192, screen_width: 256 }, settings: { show_border: new Setting('show_border', true), direct_send: new Setting('direct_send', false) }, settings_key: 'twitch-touches-pokemon', scale: 1, interval_handle: (window.touch_pad === undefined ? undefined : touch_pad.interval_handle), // reflect mouse event to coordinate output. coords: function (event) { var x = Math.floor((event.pageX - $(event.target).offset().left) / touch_pad.scale); var y = Math.floor((event.pageY - $(event.target).offset().top) / touch_pad.scale); x = Math.min(Math.max(x, 1), touch_pad.parameters.screen_width); y = Math.min(Math.max(y, 1), touch_pad.parameters.screen_height); return x + ',' + y; }, // adjust position of the box, parameters are relative position of top-left corner of the box within stream screen // 0 <= rx,ry <= 1 position: function (rx, ry) { try{ var base = $('#player,#videoPlayer'); if(!base.is('object')) // in tinytwitch #player is that object. base = base.find('object'); // but in twitch player is just a div. var height = base.height() - touch_pad.parameters.bar_height; var base_offset = base.offset(); var real_height, real_width, left_margin, top_margin; if (height / base.width() > touch_pad.parameters.ratio) { // this is the behavior of BetterTTV, filling horizontally and leave margins on top and bottom real_width = base.width(); real_height = real_width * touch_pad.parameters.ratio; touch_pad.scale = real_height / touch_pad.parameters.original_height; left_margin = 0; top_margin = (height - real_height) / 2; } else { // this is the normal behavior of twitch, filling vertically and leave margins on left and right. real_height = height; touch_pad.scale = real_height / touch_pad.parameters.original_height; real_width = real_height / touch_pad.parameters.ratio; left_margin = (base.width() - real_width) / 2; top_margin = 0; } $('.touch_overlay').offset({ top: Math.floor(base_offset.top + top_margin + ry * real_height), left: Math.floor(base_offset.left + left_margin + rx * real_width) }) .height(Math.floor(touch_pad.parameters.screen_height * touch_pad.scale)) .width(Math.floor(touch_pad.parameters.screen_width * touch_pad.scale)); } catch(err) { console.error(err); //don't quit } }, aim: function () { touch_pad.position(touch_pad.parameters.position_x, touch_pad.parameters.position_y); // rough estimation No.2 }, init_settings: function () { forIn(touch_pad.settings, function (k, setting) { setting.observe(function () { touch_pad.save_settings(); }); }); }, load_settings: function () { var settings = JSON.parse(myWindow.localStorage.getItem(touch_pad.settings_key)); forIn(touch_pad.settings, function (k, setting) { setting.load(settings); }); }, save_settings: function () { var settings = {}; forIn(touch_pad.settings, function (k, setting) { setting.save(settings); }); myWindow.localStorage.setItem(touch_pad.settings_key, JSON.stringify(settings)); }, restore_default_settings: function () { forIn(touch_pad.settings, function (k, setting) { setting.restoreDefault(); }); }, init: function () { if ($('.touch_overlay').length === 0) { $('body') .append('<div class="touch_overlay" style="cursor:crosshair;z-index:99"></div>') .append('<style type="text/css">.touchborder{border:red solid 1px;}</style>'); $('.touch_overlay').unbind() .mouseup(function (event) { var output_text = touch_pad.coords(event); var output_area = $('textarea') .val(output_text) .change(); // on tinytwitch accessing the textarea is difficult. if (output_area.length === 0) myWindow.prompt('Twitch touches pokemon cannot locate the chat box on this page, possibly because it is not on the offical stream page, but you can copy the following value to send it yourself.', output_text); if (touch_pad.settings.direct_send.getValue()) { $('.send-chat-button button').click(); } }); // add the reaiming into settings menu. idea stolen from the chat-filter : http://redd.it/1y8ukl $('.chat-settings') .append('<div class="chat-menu-header">Touch pad</div>') .append($('<div class="chat-menu-content"></div>') .append('<p><label><input id="ttp-show-border" type="checkbox"> Show border</label></p>') .append('<p><label><input id="ttp-direct-send" type="checkbox"> Send on clicking</label></p>') .append($('<button>Reposition Touchpad</button>').click(function () { touch_pad.aim(); }))); } // initialize settings touch_pad.init_settings(); // bind inputs to settings touch_pad.settings.show_border.bind('#ttp-show-border'); touch_pad.settings.direct_send.bind('#ttp-direct-send'); // observe settings touch_pad.settings.show_border.observe(function (shown) { $('.touch_overlay').toggleClass("touchborder", shown); }); // load settings touch_pad.load_settings(); //start running touch_pad.aim(); if (touch_pad.interval_handle) { clearInterval(touch_pad.interval_handle); } //update the size every 50 ms , thanks to Meiguro's idea! touch_pad.interval_handle = setInterval(touch_pad.aim, 50); } }; // initialize on DOM ready $(function () { touch_pad.init(); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址