Greasy Fork is available in English.
为手机浏览器添加触摸手势,即装即用,无需配置😎。拥有超多通用手势满足你的需求,还设计有对📝文字、🖼️图片、🎥视频交互的特殊手势💪。还想要更多😱?支持添加属于你的个性化手势,更有隐藏功能等待你的发现😏!推荐使用狐猴浏览器、Edge浏览器和Yandex浏览器。
链接:https://pan.baidu.com/s/1vsLkeyp7wvTaiZMjtS373g 提取码:1591
上面链接的脚本有错误,上传错了。。
大声说声大佬辛苦了,开发不易,大佬辛苦!!!!感谢感谢感谢感谢感谢🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹
可以的,我稍微看了一下你的脚本,就给你提几点建议好啦😬
以下以未修改的基础上说明:
1.振动反馈可以不用在每个手势内部写,可以直接在gestureData.runCode方法里面加入'try{navigator.vibrate&&navigator.vibrate(40)}catch(e){}'。
2.视频全屏时屏蔽原生操控,这个我考虑采纳,暂时在touchMove方法里面加入'if(fullsState>0){e.stopImmediatePropagation();}'来屏蔽,但网站适配性未充分测试。
3.新的容器查找逻辑,我还不清楚你想要什么样的效果,所以暂时不给建议。
4.关于画中画,目前我还没遇到有限制画中画功能的网站,如果你有遇到,可以提供我测试。
5.关于meta,理论上现在的网页都自带。如果该代码对你的使用确实有帮助,建议不要放在resize方法中,这会导致每次全屏都会生成一个。你可以写在注册事件里面,用load事件来触发它。
v10.2.1上线2个测试功能:
1.拦截自动跳转,防止恶意网站多次重定向,可自定义恶意转跳检测阈值。
----是否有不小心点击到恶意网站的烦恼,多次跳转,无法退回原网页😭。
2.视频全屏时屏蔽原容器滑动操作。
----将上面第二条建议,合并进了新版本,但没有充分测试哦😋。
欢迎帮忙测试反馈,更新需要重置手势数据。
1.感谢大佬指教
2.新上线的拦截功能太好了,解决恶心网站暴力跳转的痛点
3.禁止画中画的网站YouTube
4.新的视频查找逻辑,ai写的脚本就是搞了两种方法,支持手动切换两种逻辑,来处理修罗影视和注视影视双击后视频容器画面下移的问题。
5.meta和振动反馈感谢大佬的指导嘿嘿🤤🤤🤤
6.再有问题,我会改继续反馈的🌹🌹🌹
7.再次感谢🌹🌹🌹
下面的反馈可能比较分散也有可能会修改:
1.新的版本屏蔽已经生效了,后续适配情况我再反馈
2.新版本的视频容器逻辑已经解决了修罗影视的问题,但是注视影视的还没有解决,双击全屏后顶部有网页标头的残留。
YouTube网页中新版本有以下情况:
1.多发性双击进入全屏黑屏,原生按钮进入也会黑屏。偶发性画面正常
2.针对原生容器支持长按倍速的情况也要屏蔽,比如YouTube网页原生支持长按倍速,所以在使用脚本的长按功能时会触发两种状态存在,脚本的调节状态和原生容器的长按倍速。
1.关于画中画,我会考虑合并解除限制功能。
2.注视影视网址是什么?网上搜出来的网址,我这边无法播放,不知是何原因。
3.YouTube全屏黑屏,我目前没测试出来,不清楚你那边什么情况。
4.长按屏蔽,目前我没想到特别好的方式,如果在'touchstart'中屏蔽,可能会导致视频全屏时很多功能受影响。
关于YouTube全屏黑屏,我遇到全屏时画面会有一层毛玻璃效果,不知是不是你说的情况,但是这个前进后退一下进度就可以恢复。
这个暂时先克服一下,如果你知道什么原因引起的,也可以直接告诉我。
1.YouTube确实是这样的,调整一下进度就可以恢复,我在chatgpt中大量测试了,视频容器查找算法是可以解决的,但是也会带来副作用,比如YouTube正常显示但不能满屏了,有时修罗影视不能满屏了。我分享给你我的测试链接,里面有几个算法可以解决修罗影视注视影视的问题,但YouTube正常亮屏横屏但不能满屏状态。希望大佬解决!
这是chatgpt的结论,我感觉它说的是对的但是遗憾它不能解决这个问题!!
chatgpt推测:
我们上次为了解决 xlys 的“放大/下移”问题,对候选容器做了过强的排除(任何含 transform 的祖先都会被强烈惩罚或直接排除),以及更严格的 overlap/scale 检查。
结果:对于 xlys 那类页面,这样的排除能避免选到会产生放大/位移的容器(问题解决)。但在 某些 YouTube 情形(或其他站点)里,播放器周边或父容器可能带有轻量的 transform(例如 translateZ(0)、轻微的 matrix(...)),这并不会破坏 fullscreen 的行为 — 但我们的老逻辑把任何 transform 一律排除,从而把合适的容器屏蔽掉,导致后续回退逻辑选择了不合适的祖先或者未能及时 short-circuit,从而表现为“不能正确满屏 / 显示慢 / 需要手动切换”。
简单说:我们之前的排除规则太绝对,把一些“可接受的轻微 transform”也排掉了;同时 quick-parent 的阈值也可能设置得太紧,导致对 YouTube 的快速路径无法命中,从而进入更重的扫描或回退路径,增加延迟或误判。
https://chatgpt.com/share/691d34f1-ace8-800b-b699-7044ecbcbe26
2.注视影视地址https://gaze.run/?ref=yinghezhinan.com
注视影视有时会抽风,kiwi加载视频比较稳定,quetta和狐猴抽风率比较高。
3.针对长按屏蔽我添加了脚本视频手势开启和关闭的功能,我用chatgpt修改添加了视频手势开启关闭联动,默认为开启脚本视频手势,开启视频手势时屏蔽原生容器的所有触发同时显示新添加进度条,在关闭脚本视频手势时完全会恢复原生容器的动作。
4.ai实现的进度条和脚本视频开启关闭手势和视频容器查找都比较繁琐或不准确,希望大佬指导一下。
5.我给你最后一版的小样,希望大佬解决。 链接:https://pan.baidu.com/s/1S6kGXOIURfdkz37mzQm29g 提取码:p9l4
6.使用ai都要把脑子搞坏,可想而知大佬开发多不容易。😘
大佬辛苦了
// findVideoBox(保留原回退逻辑,仅在其上做小幅增强:快速父容器优先判断 + 限深特征扫描 + transform/scale 过滤)
gestureData.findVideoBox = (player = gestureData.videoPlayer) => {
try{
if(!document.contains(player)) return null;
// 缓存容器判断(与原逻辑一致)
if(player._videoBox_?.contains(player) && (document.fullscreen || player._boxHeight_ === player._videoBox_.clientHeight)){
return player._videoBox_;
}
// ---------------- 快速父容器优先判断(轻量、减少阻塞,提升 YouTube 场景速度) ----------------
try{
const pr = player.getBoundingClientRect();
const immediate = player.parentNode;
if(immediate && immediate.contains(player)){
try{
const stI = getComputedStyle(immediate);
// 过滤明显不可见/广告/带 transform 的父容器
if(stI.display!=='none' && stI.visibility!=='hidden' && Number(stI.opacity||1)!==0
&& stI.transform==='none' && !immediate.querySelector('[data-ad],.ad-container,iframe[src*="ads"],.advert')){
const rI = immediate.getBoundingClientRect();
const wDiffI = Math.abs(rI.width - pr.width), hDiffI = Math.abs(rI.height - pr.height);
const overlapX = Math.max(0,Math.min(rI.right,pr.right)-Math.max(rI.left,pr.left));
const overlapY = Math.max(0,Math.min(rI.bottom,pr.bottom)-Math.max(rI.top,pr.top));
const interArea = overlapX*overlapY, vidArea = Math.max(1,pr.width*pr.height);
const overlapRatio = interArea/vidArea;
const scale = (pr.width>0)?(rI.width/pr.width):1;
// 快速接受条件:尺寸接近、重叠高、无 transform、scale 接近 1
if(wDiffI + hDiffI < 40 && overlapRatio > 0.85 && Math.abs(scale-1) < 0.06){
player._videoBox_ = immediate; player._boxHeight_ = immediate.clientHeight;
immediate.setAttribute('_videobox_','fast-parent'); return immediate;
}
}
}catch(e){}
}
}catch(e){}
// ---------------- 增强扫描(仅在触发时短时执行,限制深度,避免阻塞) ----------------
try{
const isTriggered = document.fullscreen || (performance.now() - (gestureData.lastGestureTime||0) < 480);
if(isTriggered){
const pr = player.getBoundingClientRect();
let p = player.parentNode;
let best=null, bestScore=-Infinity, baseScore=-Infinity;
let depth=0; const MAX_DEPTH=6; // 深度限制,减少计算开销
while(p && p !== document.body && depth < MAX_DEPTH){
try{
if(!p.contains(player)){ p = p.parentNode; depth++; continue; }
const st = getComputedStyle(p);
// 跳过不可见/明显广告容器或带明显 transform 的容器(transform 往往导致缩放等副作用)
if(st.display==='none' || st.visibility==='hidden' || Number(st.opacity||1)===0){ p = p.parentNode; depth++; continue; }
if(p.querySelector('[data-ad],.ad-container,iframe[src*="ads"],.advert')){ p = p.parentNode; depth++; continue; }
const rect = p.getBoundingClientRect();
// 计算 overlapRatio 与尺寸差
const ix = Math.max(0,Math.min(rect.right,pr.right)-Math.max(rect.left,pr.left));
const iy = Math.max(0,Math.min(rect.bottom,pr.bottom)-Math.max(rect.top,pr.top));
const interArea = ix*iy; const vidArea = Math.max(1,pr.width*pr.height);
const overlapRatio = interArea/vidArea;
const wDiff = Math.abs(rect.width - pr.width), hDiff = Math.abs(rect.height - pr.height);
let score = 200 - (wDiff + hDiff) + Math.round(Math.max(0,Math.min(1,overlapRatio))*180);
// top位置接近加分(避免选到页面 header)
const topDelta = Math.abs(rect.top - pr.top);
if(topDelta < 6) score += 28; else if(topDelta < 24) score += 8;
// 变换/缩放惩罚:若容器有 transform(非 none),大幅惩罚(避免放大/下移)
if(st.transform && st.transform!=='none') score -= 200;
// scale 惩罚:若容器尺寸明显比 video 大(可能被全屏放大),惩罚
const scale = pr.width>0 ? (rect.width/pr.width) : 1;
if(scale > 1.06 || scale < 0.92) score -= Math.round((Math.abs(scale-1))*100);
// 定位样式、zIndex、控件类名加分
if(['fixed','absolute','relative'].includes(st.position)) score += 18;
const z = parseInt(st.zIndex)||0; score += Math.min(20,Math.floor(z/2));
if(p.querySelector('.controls,.player-controls,.vjs-control,.vjs-tech,.plyr__controls')) score += 26;
if(p.matches('.video-container,.video-wrapper,.player-wrapper,.media-wrapper')) score += 12;
// 深度惩罚:越接近 video 越优先
score -= depth * 10;
if(depth===0) baseScore = score;
if(score > bestScore){ best = p; bestScore = score; }
}catch(e){}
p = p.parentNode; depth++;
}
// 接受条件:best 明显优于基线或得分绝对高(阈值)且非 transform/异常容器
if(best && (bestScore - (baseScore||0) > 30 || bestScore > 180)){
player._videoBox_ = best; player._boxHeight_ = best.clientHeight;
best.setAttribute('_videobox_','feature'); return best;
}
}
}catch(e){}
// ---------------- 回退:原有逐级上溯逻辑(完整保留,未改动) ----------------
player._videoBox_ = player.parentNode;
player.setAttribute('_videobox_', '');
let parentEle = player._videoBox_.parentNode;
let videoStyle = getComputedStyle(player);
let childStyle = getComputedStyle(player._videoBox_);
let childWidth = 0, childHeight = 0, _childWidth = 0, _childHeight = 0;
if (player._videoBox_.offsetParent === parentEle) {
childWidth = Math.round(player.offsetWidth + (+videoStyle.marginLeft.slice(0, -2)) + (+videoStyle.marginRight.slice(0, -2)));
childHeight = Math.round(player.offsetHeight + (+videoStyle.marginTop.slice(0, -2)) + (+videoStyle.marginBottom.slice(0, -2)));
_childWidth = Math.round(player._videoBox_.offsetWidth + (+childStyle.marginLeft.slice(0, -2)) + (+childStyle.marginRight.slice(0, -2)));
_childHeight = Math.round(player._videoBox_.offsetHeight + (+childStyle.marginTop.slice(0, -2)) + (+childStyle.marginBottom.slice(0, -2)));
} else {
childWidth = Math.round(player.offsetWidth + (+videoStyle.left.slice(0, -2) || 0) + (+videoStyle.marginLeft.slice(0, -2)) + (+videoStyle.marginRight.slice(0, -2)) + (+videoStyle.right.slice(0, -2) || 0));
childHeight = Math.round(player.offsetHeight + (+videoStyle.top.slice(0, -2) || 0) + (+videoStyle.marginTop.slice(0, -2)) + (+videoStyle.marginBottom.slice(0, -2)) + (+videoStyle.bottom.slice(0, -2) || 0));
_childWidth = Math.round(player._videoBox_.offsetWidth + (+childStyle.left.slice(0, -2) || 0) + (+childStyle.marginLeft.slice(0, -2)) + (+childStyle.marginRight.slice(0, -2)) + (+childStyle.right.slice(0, -2) || 0));
_childHeight = Math.round(player._videoBox_.offsetHeight + (+childStyle.top.slice(0, -2) || 0) + (+childStyle.marginTop.slice(0, -2)) + (+childStyle.marginBottom.slice(0, -2)) + (+childStyle.bottom.slice(0, -2) || 0));
}
childWidth = (childWidth > _childWidth) ? childWidth : _childWidth;
childHeight = (childHeight > _childHeight) ? childHeight : _childHeight;
while (
childWidth >= parentEle.clientWidth &&
(childWidth < 1.2 * parentEle.clientWidth || !parentEle.clientWidth) &&
(childHeight < 1.2 * parentEle.clientHeight || !parentEle.clientHeight) &&
parentEle.nodeName !== 'BODY'
) {
if (childHeight < parentEle.clientHeight) {
let isBreak = 1;
for (let childEle of parentEle.children) {
childStyle = getComputedStyle(childEle);
childHeight = Math.round(childEle.offsetHeight + (+childStyle.top.slice(0, -2) || 0) + (+childStyle.marginTop.slice(0, -2)) + (+childStyle.marginBottom.slice(0, -2)) + (+childStyle.bottom.slice(0, -2) || 0));
if (childHeight >= parentEle.clientHeight && player.clientHeight * 1.2 > parentEle.clientHeight) {
isBreak = 0;
break;
}
}
if (isBreak) break;
}
if (parentEle.clientHeight) {
player._videoBox_.setAttribute('_videobox_', '');
player._videoBox_ = parentEle;
player._boxHeight_ = parentEle.clientHeight;
childStyle = getComputedStyle(parentEle);
if (parentEle.offsetParent === parentEle.parentNode) {
_childWidth = Math.round(parentEle.offsetWidth + (+childStyle.marginLeft.slice(0, -2)) + (+childStyle.marginRight.slice(0, -2)));
_childHeight = Math.round(parentEle.offsetHeight + (+childStyle.marginTop.slice(0, -2)) + (+childStyle.marginBottom.slice(0, -2)));
} else {
_childWidth = Math.round(parentEle.offsetWidth + (+childStyle.left.slice(0, -2) || 0) + (+childStyle.marginLeft.slice(0, -2)) + (+childStyle.marginRight.slice(0, -2)) + (+childStyle.right.slice(0, -2) || 0));
_childHeight = Math.round(parentEle.offsetHeight + (+childStyle.top.slice(0, -2) || 0) + (+childStyle.marginTop.slice(0, -2)) + (+childStyle.marginBottom.slice(0, -2)) + (+childStyle.bottom.slice(0, -2) || 0));
}
childWidth = (childWidth > _childWidth) ? childWidth : _childWidth;
childHeight = (childHeight > _childHeight) ? childHeight : _childHeight;
}
parentEle = parentEle.parentNode;
}
player._videoBox_.setAttribute('_videobox_', 'outer');
return player._videoBox_;
}catch(e){
try{console.error('findVideoBox error',e);}catch(e){};return null;
}
};
//全屏检测事件
function regRESIZE(){
let videoCss=gestureData.addStyle(''),allowResize=()=>{resizeTimer=0;},findImportant=null;
window.addEventListener('resize',()=>{
if(document.fullscreen && !fullsState){
resizeTimer=setTimeout(allowResize,400);
fullsState=document.fullscreenElement;
if(fullsState.nodeName==='IFRAME'){fullsState=-1;return;}
let srcFindVideo=fullsState.getElementsByTagName('video'),srcVideo=(fullsState.nodeName==='VIDEO') ? fullsState : srcFindVideo[0];
if(!fullsState.hasAttribute('_videobox_') && (!srcVideo || srcFindVideo.length>1 || srcVideo._videoBox_.offsetWidth*srcVideo._videoBox_.offsetHeight*1.2{ele.style.cssText=ele._fullscreenCSS_;});
}else if(fullsState && !document.fullscreen){
resizeTimer=setTimeout(allowResize,400);
fullsState=0;videoCss.textContent='';
findImportant.forEach((ele)=>{ele.style.cssText=ele._cssText_;});
}
},true);
}
我暂时采用上面两个代码块了,上面视频容器查找算法在修罗影视不能满屏,我又想起了之前你让让我修改的meta写法,我又改回去了每次写出meta这样解决修罗影视的问题,YouTube和注视影视也都正常了,暂停先这样用着了,等着大佬最终版解决版方案😁😁😁😁😁
感谢感谢感谢大佬付出!
v10.2.3已更新,需要重置手势数据。
1.已更新解除画中画限制功能。
2.已修复注视影视问题。原因为最外层容器被后加载内容撑大,只需要触发下容器重找,即可恢复正常。
另外:
1.关于长按屏蔽,我看了你之前的修改,实际生效的也是通过屏蔽touchstart实现的。但这会带来额外的问题,比如一些视频互动效果可能是绑定在touchstart上的,导致你无法点击互动。所以考虑更多网页适配性的话,这并不是一个好主意😵。
2.关于YouTube黑屏,暂时只能先这样了,你可以先用旧的方法,或者新旧并行检测是YouTube就用旧方法😬。也许下次更新就修复了😜
哈哈,好的好的,大佬威武!!!!😁😘😘😘😘😘
链接:https://pan.baidu.com/s/1lyuFNa-qJy6rfIvbuR0b7Q 提取码:5v98
大佬你好,我又来,想死你了😸😸。
1.我用大佬的脚本通过ai添加几个功能,但是不完美可以提交给你润色一下吗?🐶
2.脚本添加了震动反馈
3.添加了屏蔽手势,视频全屏时可以屏蔽原生的视频容器操控。
4.针对修罗影视和注释影视添加了一个新的视频容器查找逻辑,设置了开关来切换两个视频容器逻辑的切换。这逻辑写的太乱了,只是将就用,希望大佬搞一下🐶🐶🐯
5.添加了解除画中画限制和写入meta全屏
6.由于都是用ai写的所以整个代码看起来很乱,用的很不舒服,根本没有作者大佬代码的丝滑,没大佬代码的美如画,没大佬代码的精简高效,所以希望大佬翻牌看的上的优化进新的脚本中。🙈🙈🙈🙈我知道别人不一定需要但是我真的需要😹😹😹😹😻😻😻。