diff --git a/src/video/airborne.js b/src/video/airborne.js index 69daeb1b0..3d6a54161 100644 --- a/src/video/airborne.js +++ b/src/video/airborne.js @@ -8,6 +8,29 @@ function isAirbornable(danmaku) return danmaku.innerText.search(/\d{1,}[::]\d{2}/) !== -1 && danmaku.childElementCount === 0; // 无子元素表明没有被检测并加过下划线,防止重复调用陷入死循环 } +function getArea(element) +{ + var eleLeft = element.offsetLeft; + var eleTop = element.offsetTop; + var offParent = element.offsetParent; + while (offParent !== null) + { + eleLeft += offParent.offsetLeft; + eleTop += (offParent.offsetTop + offParent.clientTop); + offParent = offParent.offsetParent; + } + styleTransform = element.style.transform; + translateXReg = styleTransform.match(/translateX\(-?[0-9]{1,}([.][0-9]{1,})?px\)/); + if (translateXReg !== null) + { + eleLeft += parseFloat(translateXReg[0].match(/-?[0-9]{1,}([.][0-9]{1,})?/)[0]); + } + return {left: eleLeft, + right: eleLeft + element.offsetWidth, + top: eleTop, + bottom: eleTop + element.offsetHeight}; +} + function danmakuContainerCallback() { // 当用户点击到视频内部时检查是否点击空降弹幕而非在检测到空降弹幕时就监听弹幕的点击从而改善性能(不然有可能点击时调用一堆函数) @@ -22,21 +45,11 @@ function danmakuContainerCallback() // 不是空降弹幕,continue return true; } - var left = danmaku.offsetLeft; - var top = danmaku.offsetTop; - var offParent = danmaku.offsetParent; - while (offParent !== null) - { - left += offParent.offsetLeft; - top += (offParent.offsetTop + offParent.clientTop); - offParent = offParent.offsetParent; - } - const right = left + danmaku.offsetWidth; - const bottom = top + danmaku.offsetHeight; - if (left <= mousePosition[0] && - mousePosition[0] <= right && - top <= mousePosition[1] && - mousePosition[1] <= bottom) + const danmakuArea = getArea(danmaku); + if (danmakuArea.left <= mousePosition[0] && + mousePosition[0] <= danmakuArea.right && + danmakuArea.top <= mousePosition[1] && + mousePosition[1] <= danmakuArea.bottom) { document.querySelector('.bilibili-player-video video').currentTime = danmaku.airborneDestination; document.querySelector('.bilibili-player-video video').play(); @@ -69,13 +82,15 @@ function markAirborne(danmaku) { SpinQuery.select(() => document.querySelector(".bilibili-player-video-danmaku")) .then(() => { - // 当点击到warp时可以正常获取鼠标位置,但是点击到视频元素时获取到的鼠标位置是(0,0),这里只好初始化时就一直记录鼠标位置,暂时没想到更好的办法(菜……) + // 当点击到 warp 时可以正常获取鼠标位置,但是点击到视频元素时获取到的鼠标位置是(0,0),这里只好初始化时就一直记录鼠标位置,暂时没想到更好的办法(菜……) document.querySelector(".bilibili-player-video-danmaku").mousePosition = [0, 0]; document.addEventListener ('mousemove', (e) => {document.querySelector(".bilibili-player-video-danmaku").mousePosition = [e.clientX, e.clientY]}, false); - // 当视频或warp被点击时检测是否点击空降弹幕 - document.querySelector('.bilibili-player-video-wrap').addEventListener('click', danmakuContainerCallback); - // document.querySelector('.bilibili-player-video video').addEventListener('click', danmakuContainerCallback); + // 当视频或 warp 被点击时检测是否点击空降弹幕 + // setTimeout 原因:B站滚动字幕是通过 transform 实现的,如果当点击时立即调用计算弹幕区域就得出的就是弹幕移出视频范围的位置而非当前的位置 + // 延后5ms让B站的代码把 translateX 的值改到弹幕当前的位置,虽然说1ms应该完全够了,而且我测试的时候1ms在av78426409里没问题 + // 不过万一遇到老掉牙的电脑跑得慢就有可能出问题,这里就改成5ms了,但是用户应该也不会察觉到(什么神仙有那反应速度…) + document.querySelector('.bilibili-player-video-wrap').addEventListener('click', ()=>{setTimeout(() => {danmakuContainerCallback();}, 5);}); // 监听每一个弹幕并检测是否为空降弹幕 Observer.childList('.bilibili-player-video-danmaku', (records) => {