我正在编写一个 tampermonkey 脚本,用于在 Facebook 视频旁边添加速度按钮。该脚本获取页面中的所有视频元素,获取它们的位置,并根据该位置将按钮放置在它们旁边。该脚本一开始运行良好。但是当我滚动并且页面加载更多视频时,按钮位置不再与他们的视频匹配。因此,视频旁边不会有速度按钮。我怀疑通过加载更多视频,代码在某个地方搞砸了,从页面顶部计算出的视频位置错误,从而导致按钮放置错误。有人可以建议一种方法来解决这个问题吗?我的代码如下:
function addButton(){
function getOffset( el ) {//get the position of the element respective to the top and the left of the page
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
function setButton(video){//add buttons next to the videos
var elDistanceToTop = window.pageYOffset + video.getBoundingClientRect().top
var y=elDistanceToTop;//get the distance from the element to the TOP of the page
//var y = getOffset( video ).top;
var x=getOffset( video ).left;//get the distance from the element to the LEFT of the page
var button1 = document.createElement('button');
button1.textContent = '1x';
// Set button position
button1.style.position = 'absolute';
button1.style.left = x+video.getBoundingClientRect().width+ 'px';//place button to the left of video
button1.style.top = y+ 'px';//position from the top of the page to place the button
button1.style.width='58px';
button1.style.height=video.getBoundingClientRect().height/3+'px';
button1.addEventListener('click', function () {
// Increase speed by 1, maximum speed is 4.0
video.playbackRate = 1;
});
// Add button to the document body
document.body.appendChild(button1);
var button2 = document.createElement('button');
button2.textContent = '1.5x';
// Set button position
button2.style.position = 'absolute';
button2.style.left = x+video.getBoundingClientRect().width+ 'px';
button2.style.top = y+video.getBoundingClientRect().height/3+ 'px';
button2.style.width='58px';
button2.style.height=video.getBoundingClientRect().height/3+'px';
button2.addEventListener('click', function () {
// Increase speed by 1.5, maximum speed is 4.0
video.playbackRate = 1.5;
});
// Add button to the document body
document.body.appendChild(button2);
var button3 = document.createElement('button');
button3.textContent = '2x';
// Set button position
button3.style.position = 'absolute';
button3.style.left = x+video.getBoundingClientRect().width+ 'px';
button3.style.top = y+video.getBoundingClientRect().height*2/3+ 'px';
button3.style.width='58px';
button3.style.height=video.getBoundingClientRect().height/3+'px';
button3.addEventListener('click', function () {
// Increase speed by 2, maximum speed is 4.0
video.playbackRate = 2;
});
// Add button to the document body
document.body.appendChild(button3);
}
const videoElement = document.querySelectorAll('video');
videoElement.forEach((video, index) => {
//check to see if the video had had buttons
const loadedBefore = video.getAttribute('data-loaded') === 'true';
if (loadedBefore) {//if it has, do nothing
} else {//if it doesn't have buttons, add them
setButton(video);
}
});
videoElement.forEach((video, index) => {//mark all exsisting video on the page as button-having,
//so as not to add button to them again
video.setAttribute('data-loaded', 'true');
});
}
setInterval(addButton, 3000);//the loop to check and add button again and again
修改现有代码以包含 MutationObserver:
function addButton() {
// Your existing code...
}
// Create a new observer
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
// If new nodes are added, run the addButton function
addButton();
}
});
});
// Start observing the document with the configured parameters
observer.observe(document, { childList: true, subtree: true });
// Your existing setInterval call...
setInterval(addButton, 3000);
在代码的修改版本中,创建了一个 MutationObserver 来监视 DOM 中的更改。如果将新节点添加到 DOM,则会调用 addButton 函数。这可确保您的速度按钮在新视频加载到页面上时添加到其中。
在这种情况下,我怀疑问题出在您添加按钮的位置。
不要将它们添加到距页面顶部一定距离的地方,而是尝试识别一个限制该组元素的父容器并将其添加到其中。然后,当父容器改变屏幕上的位置时,您的按钮也会随之改变。
否则,您将需要循环更新所有按钮的屏幕位置。更多的工作和更多的困难。然而,如果您选择这样的路线,那么 OOKWUDILI 对突变观察者的参考可能会有所帮助。