// ==UserScript== // @name 手机端浏览器功能扩展 // @name:en Add additional functions to mobile browser // @description 手机端可装插件浏览器(如Yandex,Kiwi)添加额外的功能。例如:视频双击全屏,双击快速搜索,视频快进/快退和倍速播放,单手手势操作等。(手势如:↓↑回到顶部,↑↓回到底部,→←后退,←→前进,→↓关闭标签页,→↑重新打开页面等) // @description:en Add additional functions to mobile browser(Yandex and Kiwi).For example, video double-click full screen, double-click fast search, video fast forward / backward and variable speed play, one hand gesture operation, etc // @version 6.2.0 // @author L.Xavier // @namespace https://greasyfork.org/zh-CN/users/128493 // @include * // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant unsafeWindow // @grant window.close // @grant GM_openInTab // @grant GM_setClipboard // @grant GM_addValueChangeListener // @run-at document-start // @note 功能说明:1.视频重力感应横屏 2.视频双击全屏/退出全屏 3.双击快速搜索 4.单手手势功能 4-①.文字手势 4-②.图片手势 4-③.视频手势 (功能详情请查看”脚本描述“) // @v6.1.1 2021-02-09 - 综合考虑操作习惯和浏览器限制等原因,将双击搜索固定为在当前页上方,将新建页面手势固定为在所有页面上方,不将由弹出网页开关控制。 // @v6.1.2 2021-02-11 - 调整为方便一些小屏手机更灵敏的操作,讲手指距离可调整范围增大,现在默认为0.5(等于之前的0.0)。 // @v6.2.0 2021-02-13 - 建议重新安装下脚本!!!整合双击功能进手势功能,图标为◆(单击)◆◆(双击)。可自行在手势界面设置,设置方式详情查看描述图片。功能开关界面,去除双击功能开关按钮。 // @downloadURL none // ==/UserScript== (function(){ 'use strict'; var Ti=null; //手势功能原始数据 var gesture={ '↑→↓←':'打开设置', '→←':'后退', '←→':'前进', '↓↑':'回到顶部', '↑↓':'回到底部', '←↓':'刷新页面', '←↑':'新建页面', '→↓':'关闭页面', '→↑':'恢复页面', '↑←↓':'关闭其他页面', '→↓↑←':'视频解析', 'T→↑':'百度翻译', 'T←↑':'谷歌翻译', 'I→↑●':'打开图片', 'I←↑●':'百度搜图', 'V→':'前进10s', 'V←':'后退10s', 'V↑':'增加倍速', 'V↓':'减小倍速', 'V→●':'快进播放', 'V→○':'停止快进', 'V←●':'快退播放', 'V←○':'停止快退', '◆◆':'双击全屏', 'T◆◆':'双击搜索' }, pathFn={ '打开设置':'openSet()', '后退':'var oldUrl=location.href;history.go(-1);setTimeout(function(){if(oldUrl==location.href && (!document.referrer || history.length<2)){GM_setValue("lastTab",location.href);window.close();}},500)', '前进':'history.go(1)', '回到顶部':'document.documentElement.scrollTop=0', '回到底部':'document.documentElement.scrollTop=document.documentElement.scrollHeight', '刷新页面':'document.body.style.cssText="filter:grayscale(100%);";history.go(0)', '新建页面':'GM_openInTab("https://nav.uvooc.com/m/")', '关闭页面':'GM_setValue("lastTab",location.href);window.close()', '恢复页面':'openURL(GM_getValue("lastTab"))', '关闭其他页面':'GM_setValue("closeAll", Date())', '视频解析':'openURL("http://jx.51yfx.com/?url="+location.href)', '百度翻译':'openURL("https://fanyi.baidu.com/#auto/auto/"+window.getSelection().toString())', '谷歌翻译':'openURL("https://translate.google.cn/?sl=auto&tl=auto&text="+window.getSelection().toString())', '打开图片':'openURL(touchEle.src)', '百度搜图':'openURL("https://graph.baidu.com/details?isfromtusoupc=1&tn=pc&carousel=0&promotion_name=pc_image_shituindex&extUiData%5bisLogoShow%5d=1&image="+touchEle.src)', '前进10s':'videoPlayer.currentTime+=10;tipBox.innerHTML="+10s ";tipBox.style.display="block";setTimeout(function(){tipBox.style.display="none";},500)', '后退10s':'videoPlayer.currentTime-=10;tipBox.innerHTML="-10s ";tipBox.style.display="block";setTimeout(function(){tipBox.style.display="none";},500)', '增加倍速':'if(document.webkitFullscreenElement || document.mozFullscreenElement){speedNum+=1;speedNum=(speedNum>7) ? 7 : speedNum;tipBox.innerHTML="x"+speedItem[speedNum]+" ∞ ";tipBox.style.display="block";videoPlayer.playbackRate=speedItem[speedNum];setTimeout(function(){tipBox.style.display="none";},500)}', '减小倍速':'if(document.webkitFullscreenElement || document.mozFullscreenElement){speedNum-=1;speedNum=(speedNum<0) ? 0 : speedNum;tipBox.innerHTML="x"+speedItem[speedNum]+" ∞ ";tipBox.style.display="block";videoPlayer.playbackRate=speedItem[speedNum];setTimeout(function(){tipBox.style.display="none";},500)}', '快进播放':'videoPlayer.playbackRate=5;tipBox.innerHTML="x5 ";tipBox.style.display="block"', '停止快进':'videoPlayer.playbackRate=speedItem[speedNum];setTimeout(function(){tipBox.style.display="none";},500)', '快退播放':'backTimer=setInterval(function(){videoPlayer.currentTime-=5;},500);tipBox.innerHTML="- x5 ";tipBox.style.display="block"', '停止快退':'clearTimeout(backTimer);setTimeout(function(){tipBox.style.display="none";},500)', '双击全屏':'if(document.webkitFullscreenElement || document.mozFullscreenElement){if(document.webkitExitFullscreen){document.webkitExitFullscreen();}else if(document.mozCancelFullScreen){document.mozCancelFullScreen();}GM_setClipboard(videoPlayer.src,{type:"text"});}else if(videoPlayer){if(videoPlayer.webkitRequestFullscreen){videoPlayer.webkitRequestFullScreen();}else if(videoPlayer.mozRequestFullScreen){videoPlayer.mozRequestFullScreen();}}else if(iframeEle.length>0){GM_setValue("fullscreen",Date());}', '双击搜索':'if(!regURL.test(selectWords)){selectWords="https://www.baidu.com/s?wd="+selectWords;}else if(selectWords.indexOf("http")<0){selectWords="//"+selectWords;}window.open(selectWords)' }, settings={ '滑动距离':0.5, '文字手势':true, '图片手势':true, '视频手势':true, '弹出网页':false }; //存储数据读取 gesture=GM_getValue('gesture',gesture); pathFn=GM_getValue('pathFn',pathFn); settings=GM_getValue('settings',settings); //手指滑动变量 var startX=0,startY=0,endX=0,endY=0,calcX=0,calcY=0,path='',regTYPE=/[TIV]/,touchEle=null,gestureTimer=null; var pressTime=0,raiseTime=0,slideTime=0,limit=(window.screen.width>window.screen.height) ? window.screen.height/(4-2*settings['滑动距离']) : window.screen.width/(4-2*settings['滑动距离']); var backTimer=null,speedNum=3,speedItem=[0.25,0.5,0.75,1,1.5,2,3,5],selectWords='',regURL=/^(https?:\/\/)?([\w\-]+\.)+\w{2,4}(\/\S*)?$/; //手势方法 function openURL(url){if(settings['弹出网页']){window.open(url)}else{GM_openInTab(url)}} function runGesture(pathStr){ if(gesture[path]){ if(top.location==location || regTYPE.test(path.slice(0,1))){try{eval(pathFn[gesture[path]]);}catch(error){alert('“'+path+'” 手势执行脚本错误:\n'+error+' !');}} else{GM_setValue('gestureIfr',path);} path=pathStr || ''; }else if(gesture[path.slice(1)] && regTYPE.test(path.slice(0,1))){ if(top.location==location){try{eval(pathFn[gesture[path.slice(1)]]);}catch(error){alert('“'+path.slice(1)+'” 手势执行脚本错误:\n'+error+' !');}} else{GM_setValue('gestureIfr',path.slice(1));} path=pathStr || ''; } } //手指接触屏幕 window.addEventListener('touchstart',function(e){ pressTime=new Date().getTime(); if((pressTime-raiseTime)>167){ slideTime=pressTime; path=''; touchEle=e.srcElement; if(window.getSelection().toString() && settings['文字手势']){selectWords=window.getSelection().toString();path='T';} else if(e.srcElement.tagName=='IMG' && settings['图片手势']){path='I';} else if(videoPlayer && settings['视频手势']){ startX=e.changedTouches[0].clientX; startY=e.changedTouches[0].clientY; Ti=videoPlayer.getBoundingClientRect(); if(startX>Ti.x && startX<(Ti.x+Ti.width) && startY>Ti.y && startY<(Ti.y+Ti.height)){path='V';} } startX=e.changedTouches[0].screenX; startY=e.changedTouches[0].screenY; }else{clearTimeout(gestureTimer);} }); //手指滑动屏幕 window.addEventListener('touchmove',function(e){ if(e.changedTouches.length==1){ endX=e.changedTouches[0].screenX; endY=e.changedTouches[0].screenY; calcX=(endX-startX)*(endX-startX); calcY=(endY-startY)*(endY-startY); if((calcX+calcY)>(limit*limit/(path.length/2+1)) && path.slice(-1)!='○'){ slideTime=new Date().getTime(); if(calcX>calcY){Ti=(endX>startX) ? '→' : '←';} else{Ti=(endY>startY) ? '↓' : '↑';} if(path.slice(-1)!=Ti){path+=Ti;} startX=endX;startY=endY; }else if((new Date().getTime()-slideTime)>500 && path && path.slice(-1)!='●' && path.slice(-1)!='○'){//长按执行 slideTime=new Date().getTime(); if(regTYPE.test(path.slice(-1)) && (calcX+calcY)>(limit*limit/4)){ if(calcX>calcY){Ti=(endX>startX) ? '→' : '←';} else{Ti=(endY>startY) ? '↓' : '↑';} path+=Ti; startX=endX;startY=endY; } path+='●'; runGesture(path.slice(0,-1)+'○'); } }else{path='';} }); //手指离开屏幕。 window.addEventListener('touchend',function(e){ raiseTime=new Date().getTime(); if(regTYPE.test(path.slice(-1)) && (calcX+calcY)>(limit*limit/4)){ if(calcX>calcY){Ti=(endX>startX) ? '→' : '←';} else{Ti=(endY>startY) ? '↓' : '↑';} path+=Ti; } if((raiseTime-pressTime)<167){//点击 path+='◆'; videoEvent(); } gestureTimer=setTimeout(runGesture(),167); }); //video标签变量 var videoEle=document.getElementsByTagName('video'),_videoEle=[],videoPlayer=null,videoNum=0; var oriHway='landscape-primary',oriHgamma=0,oriHbeta=0,isLock=0,tipBox=null; //video判定 function setVideo(){videoPlayer=this;videoOriLock();} function videoOriLock(){ if(videoPlayer.videoWidth>videoPlayer.videoHeight){isLock=1;} else{isLock=0;screen.orientation.unlock();} } //video标签事件绑定 function videoEvent(){ if(videoEle.length>videoNum){ if(!videoNum){ //重力感应 window.addEventListener('deviceorientation',function(e){ if(isLock){ oriHgamma=e.gamma; oriHbeta=(e.beta>0) ? e.beta : -e.beta; if((oriHbeta<65 || oriHbeta>115) && (oriHgamma<-25 || oriHgamma>25)){ oriHway=((oriHbeta<65 && oriHgamma<-25) || (oriHbeta>115 && oriHgamma>25)) ? 'landscape-primary' : 'landscape-secondary'; } screen.orientation.lock(oriHway); } }); tipBox=document.createElement('div'); tipBox.style.cssText='width:100px;height:50px;position:fixed;text-align:center;z-index:2147483647;top:calc(50% - 25px);left:calc(50% - 50px);display:none;color:#1e87f0;font-size:24px;line-height:50px;background-color:#ffffff;border-radius:20px;'; document.body.appendChild(tipBox); } //播放video标签查找 for(Ti=videoNum;Ti0){ for(Ti=0;Ti<_videoEle.length;Ti++){ if(!_videoEle[Ti].offsetWidth>0){ for(Ti=0;Tilabel{display:inline-block;margin-top:2rem;position:relative;overflow:hidden}'+ '#gestureBox #editGesture .label_box>label>input{position:absolute;top:0;left:-2rem}'+ '#gestureBox #editGesture .label_box>label>div{width:8rem;text-align:center;border:#dddddd solid 1px;height:4rem;line-height:4rem;color:#666666;user-select:none;overflow:hidden;position:relative}'+ '#gestureBox #editGesture .label_box>label>input:checked + div{border:#d51917 solid 1px;color:#d51917}'+ '#gestureBox #editGesture .label_box>label>input:checked + div:after{content:"";display:block;width:2rem;height:2rem;background-color:#d51917;transform:skewY(-45deg);position:absolute;bottom:-1rem;right:0;z-index:999992}'+ '#gestureBox #editGesture .label_box>label>input:checked + div:before{content:"";display:block;width:3px;height:8px;border-right:#ffffff solid 2px;border-bottom:#ffffff solid 2px;transform:rotate(35deg);position:absolute;bottom:2px;right:4px;z-index:999993}'+ '#gestureBox #editGesture #pathFn{width:80%;margin-top:2rem;height:40%;font-size:2rem;text-align:left;line-height:2.2rem;padding:1rem;border:0.1rem solid #dadada;border-radius:1rem}'+ '#gestureBox #editGesture button{width:10rem;height:5rem;font-size:3rem;line-height:5rem;display:inline-block;color:#fff;background-color:#2866bd;margin:3rem 1rem 0rem 1rem;border:none}'+ '#gestureBox #settingsBox{background-color:#fff;width:100%;height:100%;position:fixed;top:0;left:0;overflow:hidden;z-index:999991;display:none;color:#000}'+ '#gestureBox #settingsBox p{color:#3339f9;font-size:2rem;text-align:left;margin:3rem 0 0 3rem;float:left;height:2rem;line-height:2rem;clear:both}'+ '#gestureBox #settingsBox #container{width:20rem;background-color:#a8a8a8;float:left;margin:4rem 0 0 3rem;height:0.2rem;position:relative}'+ '#gestureBox #settingsBox #container #gestureLimit{text-align:center;line-height:3rem;color:#fff;background-color:#2196f3;width:3rem;height:3rem;border-radius:3rem;font-size:1.5rem;position:absolute;top:-1.5rem;left:-15px;box-shadow:1px 1px 6px #5e8aee}'+ '#gestureBox #settingsBox .switch{position:relative;display:inline-block;width:6rem;height:3rem;float:left;margin:2.5rem 42% 0 1rem}'+ '#gestureBox #settingsBox .switch input{display:none}'+ '#gestureBox #settingsBox .slider{border-radius:3rem;position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;transition:.4s}'+ '#gestureBox #settingsBox .slider:before{border-radius:50%;position:absolute;content:"";height:2.6rem;width:2.6rem;left:0.2rem;bottom:0.2rem;background-color:white;transition:.4s}'+ '#gestureBox #settingsBox input:checked + .slider{background-color:#2196F3}'+ '#gestureBox #settingsBox input:checked + .slider:before{transform:translateX(3rem)}'+ '#gestureBox #settingsBox #saveSettings{display:block;clear:both;width:10rem;height:5rem;font-size:3rem;line-height:5rem;color:#fff;background-color:#2866bd;border:none;margin:4rem 0 0 calc(50% - 5rem);float:left}'); Ti=document.createElement('div'); Ti.id='gestureBox'; document.body.appendChild(Ti); Ti.innerHTML='

手势轨迹设置

+
'+ '
'+ '

请滑动手指

Clear
Cancle
'+ '

手势名称:

'+ '

手势类型:

'+ '

手势路径脚本:

'+ '
'+ '

功能开关设置

滑动距离:

0%
'+ '
'; gestureUL=document.getElementById('gestureUL'); pathEle=document.getElementById('path'); //编辑手势 function editGesture(){ gestureName=this.parentNode.getAttribute('name'); gesturePath=this.parentNode.getAttribute('path'); Ti=gesturePath.slice(0,1); if(!regTYPE.test(gesturePath.slice(0,1))){Ti='GG';} document.getElementById(Ti).click(); document.getElementById('gestureName').value=gestureName; document.getElementById('pathFn').value=pathFn[gestureName]; document.getElementById('editGesture').style.display='block'; } //修改路径 function revisePath(){ gestureName=this.parentNode.getAttribute('name'); gesturePath=this.parentNode.getAttribute('path'); pathEle.innerHTML=''; document.getElementById('revisePath').style.display='block'; } //删除手势 function delGesture(){ gestureName=this.parentNode.getAttribute('name'); gesturePath=this.parentNode.getAttribute('path'); delete pathFn[gestureName]; delete gesture[gesturePath]; GM_setValue('pathFn',pathFn); GM_setValue('gesture',gesture); init(); } //界面初始化 function init(){ gestureUL.innerHTML=''; for(gestureName in pathFn){ gesturePath=''; for(Ti in gesture){ if(gesture[Ti]==gestureName){ gesturePath=Ti; break; } } gestureUL.innerHTML+='

'+gestureName+'

'+gesturePath+'
删除
'; } //操作绑定 gestureEle=document.querySelectorAll('#gestureBox .gestureLi p'); for(Ti=0;Tilimit*limit && pathEle.innerHTML.slice(-1)!='○'){ if(calcX>calcY){Ti=(endX>startX) ? '→' : '←';} else{Ti=(endY>startY) ? '↓' : '↑';} if(pathEle.innerHTML.slice(-1)!=Ti){pathEle.innerHTML+=Ti;} startX=endX;startY=endY; slideTime=new Date().getTime(); }else if((new Date().getTime()-slideTime)>1000 && pathEle.innerHTML && pathEle.innerHTML.slice(-1)!='●' && pathEle.innerHTML.slice(-1)!='○'){ pathEle.innerHTML+='●'; slideTime=new Date().getTime(); } } }); document.getElementById('revisePath').addEventListener('touchend',function(e){ e.stopPropagation(); raiseTime=new Date().getTime(); if((raiseTime-clickTime)<334 && (pressTime-clickTime)<167){//双击 clearTimeout(gestureTimer); if(pathEle.innerHTML.slice(-1)=='●'){pathEle.innerHTML=pathEle.innerHTML.slice(0,-1)+'○';} else if(pathEle.innerHTML.slice(-1)=='○'){pathEle.innerHTML=pathEle.innerHTML.slice(0,-1)+'●';} }else if((raiseTime-pressTime)<167){//点击 clickTime=raiseTime; gestureTimer=setTimeout(function(){pathEle.innerHTML+='◆';},167); } }); //清除路径 document.getElementById('clearPath').addEventListener('touchend',function(e){ e.stopPropagation(); raiseTime=new Date().getTime(); if((raiseTime-clickTime)<334 && (pressTime-clickTime)<167){//双击 pathEle.innerHTML=''; }if((raiseTime-pressTime)<167){//点击 clickTime=raiseTime; pathEle.innerHTML=pathEle.innerHTML.slice(0,-1); } }); //修改路径 document.getElementById('cancleRevise').addEventListener('touchend',function(e){ e.stopPropagation(); raiseTime=new Date().getTime(); if((raiseTime-pressTime)<167){ if(pathEle.innerHTML){ if(regTYPE.test(gesturePath.slice(0,1))){pathEle.innerHTML=gesturePath.slice(0,1)+pathEle.innerHTML;} delete gesture[gesturePath]; gesture[pathEle.innerHTML]=gestureName; GM_setValue('gesture',gesture); init(); } document.getElementById('revisePath').style.display='none'; } }); //打开功能开关设置 document.getElementById('openSettings').addEventListener('dblclick',function(){ document.getElementById('settingsBox').style.display='block'; Ti=document.getElementById('container').offsetWidth*settings['滑动距离']-15; document.getElementById('gestureLimit').style.left=Ti+'px'; document.getElementById('gestureLimit').innerHTML=settings['滑动距离'].toFixed(1); document.getElementById('switchList').innerHTML=''; for(Ti in settings){ if(typeof(settings[Ti])=='boolean'){ document.getElementById('switchList').innerHTML+='

'+Ti+':

'; if(settings[Ti]){ document.getElementById('switchList').innerHTML+=''; }else{ document.getElementById('switchList').innerHTML+=''; } } } }); //拖动条 document.getElementById('gestureLimit').addEventListener('touchmove',function(e){ e.stopPropagation(); e.preventDefault(); if(e.changedTouches.length==1){ endX=e.changedTouches[0].screenX; calcX=endX-startX; Ti=parseFloat(document.getElementById('gestureLimit').style.left)+calcX; if(Ti>=-15 && Ti<=(document.getElementById('container').offsetWidth-15)){ document.getElementById('gestureLimit').style.left=Ti+'px'; Ti=(Ti+15)/document.getElementById('container').offsetWidth; document.getElementById('gestureLimit').innerHTML=Ti.toFixed(1); startX=endX; } } }); //保存功能开关设置 document.getElementById('saveSettings').addEventListener('click',function(){ settings['滑动距离']=parseFloat(document.getElementById('gestureLimit').innerHTML); for(Ti in settings){ if(typeof(settings[Ti])=='boolean'){ settings[Ti]=document.getElementById(Ti).checked; } } GM_setValue('settings',settings); document.getElementById('settingsBox').style.display='none'; }); } //关闭其他页面 GM_addValueChangeListener('closeAll',function(name,old_value,new_value,remote){if(remote){window.close();}}); //iframe视频全屏 var iframeEle=document.getElementsByTagName('iframe'); GM_addValueChangeListener('fullscreen',function(name,old_value,new_value,remote){if(remote && !document.hidden && videoPlayer && top.location!=location){if(videoPlayer.webkitRequestFullscreen){videoPlayer.webkitRequestFullScreen();}else if(videoPlayer.mozRequestFullScreen){videoPlayer.mozRequestFullScreen();}}}); //iframe手势执行 GM_addValueChangeListener('gestureIfr',function(name,old_value,new_value,remote){if(remote && !document.hidden && new_value && top.location==location){try{eval(pathFn[gesture[new_value]]);}catch(error){alert('“'+new_value+'” 手势执行脚本错误:\n'+error+' !');}GM_setValue('gestureIfr','');}}); })();