// ==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 5.1.1 // @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.单手手势功能。(↑→↓←打开手势设置界面) 5.双击快速搜索。 6.图片滑动搜图。 (详情请查看”脚本描述“) // @v5.0.0 2021-01-14 - 精简代码,调整排版。1.增加手势滑动超时判定,误滑动时可以长按取消手势操作。2.新增双击搜索同时复制关键词到剪切板。 // @v5.1.0 2021-01-14 - 新增图片滑动手势。在图片上→滑,在新页面打开该图片;在图片上←滑,百度识图搜索该图片。 // @v5.1.1 2021-01-14 - 网页上偶尔会有在图片上滑动的功能,固将图片滑动操作修改为在图片上滑动不松手。 // @downloadURL none // ==/UserScript== (function(){ 'use strict'; var Ti=null; //video标签变量 var videoEle=document.getElementsByTagName('video'),_videoEle=[],videoPlayer=null,videoNum=0; var oriHway='landscape-primary',oriHgamma=0,oriHbeta=0,isLock=true; //手指滑动变量 var startX=0,startY=0,endX=0,endY=0,angX=0,angY=0,path=''; var touchTime=0,nowTime=0,clickTime=0,limit=(window.screen.width>window.screen.height) ? window.screen.height/4 : window.screen.width/4; var saveWords='',saveTime=0,reg=new RegExp(/^(https?:\/\/)?([\w\-]+\.)+\w{2,4}(\/\S*)?$/); var videoTimer=null,backTimer=null,imgTimer=null,moveINvideo=false,isSpeed=false,speedNum=3,speedItem=[0.25,0.5,0.75,1,1.5,2,3,5]; //手势功能原始数据 var gesture={ '↑→↓←':'打开设置', '→←':'后退', '←→':'前进', '↓↑':'回到顶部', '↑↓':'回到底部', '←↓':'刷新页面', '←↑':'新建页面', '→↓':'关闭页面', '→↑':'恢复页面', '↑→↓':'关闭其他页面', '→↓↑←':'视频解析' }, 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', '刷新页面':'history.go(0)', '新建页面':'GM_openInTab("https://nav.uvooc.com/m/",{insert:true})', '关闭页面':'GM_setValue("lastTab",location.href);window.close()', '恢复页面':'GM_openInTab(GM_getValue("lastTab"),{insert:true})', '关闭其他页面':'GM_setValue("closeAll", Date())', '视频解析':'GM_openInTab("http://jx.51yfx.com/?url="+location.href,{insert:true})' }; //手指接触屏幕 window.addEventListener('touchstart',function(e){ touchTime=new Date().getTime(); if((touchTime-nowTime)>167){path='';} if(videoPlayer){//视频计时 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)){ moveINvideo=true; videoTimer=setTimeout(function(){ if(path=='→'){isSpeed=true;videoPlayer.playbackRate=5;} else if(path=='←'){isSpeed=true;backTimer=setInterval(function(){videoPlayer.currentTime-=5},500)} },1500); } } if(e.srcElement.tagName=="IMG"){//图片计时 imgTimer=setTimeout(function(){ if(path=='→'){GM_openInTab(e.srcElement.src,{insert:true});} else if(path=='←'){GM_openInTab('https://graph.baidu.com/details?isfromtusoupc=1&tn=pc&carousel=0&promotion_name=pc_image_shituindex&extUiData%5bisLogoShow%5d=1&image='+e.srcElement.src,{insert:true});} },1000); } if(window.getSelection().toString()){ saveWords=window.getSelection().toString(); saveTime=touchTime; } startX=e.changedTouches[0].screenX; startY=e.changedTouches[0].screenY; }); //手指滑动屏幕 window.addEventListener('touchmove',function(e){ e.preventDefault(); if(e.changedTouches.length==1){ endX=e.changedTouches[0].screenX; endY=e.changedTouches[0].screenY; angX=(endX-startX)*(endX-startX); angY=(endY-startY)*(endY-startY); if((angX+angY)>limit*limit){ if(angX>angY){Ti=(endX>startX) ? '→' : '←';} else{Ti=(endY>startY) ? '↓' : '↑';} if(path.charAt(path.length-1)!=Ti){path+=Ti;} startX=endX;startY=endY; } }else{path='';} }); //手指离开屏幕。 window.addEventListener('touchend',function(e){ nowTime=new Date().getTime(); //操作判定 if((nowTime-clickTime)<334 && (touchTime-clickTime)<167){//双击 if((nowTime-saveTime)<501){ GM_setClipboard(saveWords,{type:'text'}); if(!reg.test(saveWords)){ saveWords='https://www.baidu.com/s?wd='+saveWords; }else if(saveWords.indexOf('http')<0){ saveWords='//'+saveWords; } GM_openInTab(saveWords,{insert:true}); }else{ if(document.webkitFullscreenElement){ e.preventDefault(); document.webkitExitFullscreen(); GM_setClipboard(videoPlayer.src,{type:'text'}); } else if(videoPlayer){videoPlayer.webkitRequestFullScreen();} else if(iframeEle.length>0){GM_setValue('fullscreen',Date());} } }else if((touchTime-clickTime)<167 && (nowTime-touchTime)>167){//双击长按(滑动) }else if((nowTime-touchTime)<167){//点击 clickTime=nowTime; videoEvent(); }else{//长按(滑动) if(moveINvideo && (path.length<2 || isSpeed)){ //视频滑动 if(!isSpeed){ if(path=='→'){videoPlayer.currentTime+=10} else if(path=='←'){videoPlayer.currentTime-=10} else if(path=='↑'){speedNum+=1;speedNum=(speedNum>7) ? 7 : speedNum;} else if(path=='↓'){speedNum-=1;speedNum=(speedNum<0) ? 0 : speedNum;} } videoPlayer.playbackRate=speedItem[speedNum]; }else if(gesture[path] && (nowTime-touchTime)<500*path.length){ //手势执行 if(top.location==location){ try{eval(pathFn[gesture[path]]);} catch(error){alert('“'+path+'” 手势执行脚本错误:\n'+error+' !');} }else{ GM_setValue('gestureIfr',path); } } } if(moveINvideo){clearTimeout(videoTimer);clearInterval(backTimer);moveINvideo=false;isSpeed=false;} if(e.srcElement.tagName=="IMG"){clearTimeout(imgTimer);} }); //手势存储数据读取 gesture=GM_getValue('gesture',gesture); pathFn=GM_getValue('pathFn',pathFn); //关闭其他页面 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){videoPlayer.webkitRequestFullScreen();}}); //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','');}}); //video判定 function setVideo(){videoPlayer=this;videoOriLock();} function videoOriLock(){ if(videoPlayer.videoWidth>videoPlayer.videoHeight){isLock=true;} else{isLock=false;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); } }); } //播放video标签查找 for(Ti=videoNum;Ti0){ for(Ti=0;Ti<_videoEle.length;Ti++){ if(!_videoEle[Ti].offsetWidth>0){ for(Ti=0;Ti'+ '

请滑动手指

'+ '
Clear
Cancle
'+ '

手势名称:

'+ '

手势路径脚本:

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

'+Ti+'

'+gesturePath+'
删除
'; } //操作绑定 gestureEle=document.querySelectorAll('#gestureBox .gestureLi p'); for(Ti=0;Tilimit*limit){ if(angX>angY){Ti=(endX>startX) ? '→' : '←';} else{Ti=(endY>startY) ? '↓' : '↑';} if(pathEle.innerHTML.charAt(pathEle.innerHTML.length-1)!=Ti){pathEle.innerHTML+=Ti;} startX=endX;startY=endY; } } }); //清除路径 document.getElementById('clearPath').addEventListener('click',function(){pathEle.innerHTML='';}); //修改路径 document.getElementById('cancleRevise').addEventListener('click',function(){ if(pathEle.innerHTML){ delete gesture[gesturePath]; gesture[pathEle.innerHTML]=gestureName; GM_setValue('gesture',gesture); init(); } document.getElementById('revisePath').style.display='none'; }); //.新建手势 document.getElementById('addGesture').addEventListener('click',function(){ document.getElementById('gestureName').value=''; document.getElementById('pathFn').value=''; gestureName=''; document.getElementById('editGesture').style.display='block'; }); //保存手势 document.getElementById('saveGesture').addEventListener('click',function(){ if(document.getElementById('gestureName').value){ if(gestureName){ delete pathFn[gestureName]; for(Ti in gesture){ if(gesture[Ti]==gestureName){ gesture[Ti]=document.getElementById('gestureName').value; break; } } } pathFn[document.getElementById('gestureName').value]=document.getElementById('pathFn').value; GM_setValue('pathFn',pathFn); GM_setValue('gesture',gesture); init(); document.getElementById('editGesture').style.display='none'; }else{ alert('请输入手势名称!'); } }); //关闭编辑 document.getElementById('closeEdit').addEventListener('click',function(){ document.getElementById('editGesture').style.display='none'; }); } })();