如何获取滚动后HTML元素的精确位置

问题描述 投票:0回答:2

我正在编写一个 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

我附上了两张图片,展示了按钮在开始时的样子以及在页面上滚动几下后它们的样子

javascript tampermonkey userscripts
2个回答
0
投票

修改现有代码以包含 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 函数。这可确保您的速度按钮在新视频加载到页面上时添加到其中。


0
投票

在这种情况下,我怀疑问题出在您添加按钮的位置。

不要将它们添加到距页面顶部一定距离的地方,而是尝试识别一个限制该组元素的父容器并将其添加到其中。然后,当父容器改变屏幕上的位置时,您的按钮也会随之改变。

否则,您将需要循环更新所有按钮的屏幕位置。更多的工作和更多的困难。然而,如果您选择这样的路线,那么 OOKWUDILI 对突变观察者的参考可能会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.