Как определить, виден ли элемент DOM в текущем окне просмотра?

      try {

          boolean firstboot = getSharedPreferences("BOOT_PREF",MODE_PRIVATE)
    .getBoolean("firstboot", true);

                    if(firstboot){
                //place your code that will run single time                  
getSharedPreferences("BOOT_PREF",MODE_PRIVATE).edit().
    putBoolean("firstboot", false)
                        .commit();


                    }
849
задан thadeuszlay 11 March 2019 в 13:36
поделиться

5 ответов

Обновление: Время идет и тем самым имеют наши браузеры. Эта техника больше не рекомендуется , и необходимо использовать решение @Dan ниже ( https://stackoverflow.com/a/7557433/5628), если Вы не должны поддерживать IE< 7.

Исходное решение (теперь устаревший):

Это проверит, совершенно видим ли элемент в текущей области просмотра:

function elementInViewport(el) {
  var top = el.offsetTop;
  var left = el.offsetLeft;
  var width = el.offsetWidth;
  var height = el.offsetHeight;

  while(el.offsetParent) {
    el = el.offsetParent;
    top += el.offsetTop;
    left += el.offsetLeft;
  }

  return (
    top >= window.pageYOffset &&
    left >= window.pageXOffset &&
    (top + height) <= (window.pageYOffset + window.innerHeight) &&
    (left + width) <= (window.pageXOffset + window.innerWidth)
  );
}

Вы могли изменить это просто, чтобы определить, видима ли какая-либо часть элемента в области просмотра:

function elementInViewport2(el) {
  var top = el.offsetTop;
  var left = el.offsetLeft;
  var width = el.offsetWidth;
  var height = el.offsetHeight;

  while(el.offsetParent) {
    el = el.offsetParent;
    top += el.offsetTop;
    left += el.offsetLeft;
  }

  return (
    top < (window.pageYOffset + window.innerHeight) &&
    left < (window.pageXOffset + window.innerWidth) &&
    (top + height) > window.pageYOffset &&
    (left + width) > window.pageXOffset
  );
}
321
ответ дан Community 11 March 2019 в 13:36
поделиться

Простое решение как совместимость из Element.getBoundingClientRect () стал прекрасным:

function inView(el) {
    let box = el.getBoundingClientRect();
    return box.top < window.innerHeight && box.bottom >= 0;
}
0
ответ дан 22 November 2019 в 21:08
поделиться

Внимание все!

большинство использований, здесь переставших работать в этих точках:

- Когда любой пиксель элемента видим, но не" угол ",

- Когда элемент больше, чем область просмотра и центрировался ,

- Большинство из них проверяет только на исключительный элемент внутренний документ или окно .

Хорошо для всех этих проблем, у меня есть решение, и плюс стороны:

- можно возвратиться visible, когда только пиксель с любых сторон обнаруживается и не является углом,

- можно все еще возвратиться visible, в то время как элемент, больше, чем область просмотра,

- можно выбрать Ваш parent element, или можно автоматически позволить ему выбрать,

- Работы над [1 146] динамично добавленные элементы также.

, Если Вы проверяете, отрывки ниже Вас будут видеть, что различие в использовании overflow-scroll в контейнере элемента не будет доставлять неприятностей и видеть, что В ОТЛИЧИЕ ОТ ДРУГИХ ОТВЕТОВ ЗДЕСЬ , даже если пиксель обнаруживается от [1 148] КАКАЯ-ЛИБО СТОРОНА или когда элемент больше затем, область просмотра и мы видит ВНУТРЕННИЕ ПИКСЕЛИ ЭЛЕМЕНТА , это все еще работает.

Использование просто:

// For checking element visibility from any sides
isVisible(element)

// For checking elements visibility in a parent you would like to check
var parent = document; // Asuming you check if element inside document
isVisible(element, parent)

// For checking elements visibility even if its bigger then viewport
isVisible(element, null, true) // Without parent choise
isVisible(element, parent, true) // With parent choise

демонстрация А без [1 111], который полезен для элементов, больше, чем область просмотра, проверяет element3 внутренние пиксели для наблюдения:

function isVisible(element, parent, crossSearchAlgorithm) {
    var rect = element.getBoundingClientRect(),
    		prect = (parent != undefined) ? parent.getBoundingClientRect() : element.parentNode.getBoundingClientRect(),
        csa = (crossSearchAlgorithm != undefined) ? crossSearchAlgorithm : false,
        efp = function (x, y) { return document.elementFromPoint(x, y) };
    // Return false if it's not in the viewport
    if (rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom) {
        return false;
    }
    var flag = false;
    // Return true if left to right any border pixel reached 
    for (var x = rect.left; x < rect.right; x++) {
    	if (element.contains(efp(rect.top, x)) || element.contains(efp(rect.bottom, x))) {
        flag = true;
        break;
      }
    }
    // Return true if top to bottom any border pixel reached 
    if (flag == false) {
      for (var y = rect.top; y < rect.bottom; y++) {
        if (element.contains(efp(rect.left, y)) || element.contains(efp(rect.right, y))) {
          flag = true;
          break;
        }
      }
    }
    if(csa) {
      // Another algorithm to check if element is centered and bigger than viewport
      if (flag == false) {
        var x = rect.left;
        var y = rect.top;
        // From top left to bottom right
        while(x < rect.right || y < rect.bottom) {
          if (element.contains(efp(x,y))) {
            flag = true;
            break;
          }
          if(x < rect.right) { x++; }
          if(y < rect.bottom) { y++; }
        }
        if (flag == false) {
          x = rect.right;
          y = rect.top;
          // From top right to bottom left
          while(x > rect.left || y < rect.bottom) {
            if (element.contains(efp(x,y))) {
              flag = true;
              break;
            }
            if(x > rect.left) { x--; }
            if(y < rect.bottom) { y++; }
          }
        }
      }
    }
    return flag;
}

// Check multiple elements visibility
document.getElementById('container').addEventListener("scroll", function() {
	var elementList = document.getElementsByClassName("element");
  var console = document.getElementById('console');
	for (var i=0; i < elementList.length; i++) {
  	// I did not define parent so it will be element's parent
    if (isVisible(elementList[i])) {
  		console.innerHTML = "Element with id[" + elementList[i].id + "] is visible!";
      break;
    } else {
    	console.innerHTML = "Element with id[" + elementList[i].id + "] is hidden!";
    }
  }
});

// Dynamically added elements
for(var i=4; i <= 6; i++) {
  var newElement = document.createElement("div");
  newElement.id = "element" + i;
  newElement.classList.add("element");
  document.getElementById('container').appendChild(newElement);
}
#console { background-color: yellow; }
#container {
  width: 300px;
  height: 100px;
  background-color: lightblue;
  overflow-y: auto;
  padding-top: 150px;
  margin: 45px;
}
.element {
  margin: 400px;
  width: 400px;
  height: 320px;
  background-color: green;
}
#element3 {
  position: relative;
  margin: 40px;
  width: 720px;
  height: 520px;
  background-color: green;
}
#element3::before {
  content: "";
  position: absolute;
  top: -10px;
  left: -10px;
  margin: 0px;
  width: 740px;
  height: 540px;
  border: 5px dotted green;
  background: transparent;
}
<div id="console"></div>
<div id="container">
    <div id="element1" class="element"></div>
    <div id="element2" class="element"></div>
    <div id="element3" class="element"></div>
</div>

Вы видите, когда Вы внутренняя часть element3, этому не удается сказать, видим ли его видимое или не потому что мы только проверяем, если элемент от [1 153] стороны или углы .

И этот включает crossSearchAlgorithm, который позволяет Вам все еще возвращаться visible, когда элемент больше, чем область просмотра:

function isVisible(element, parent, crossSearchAlgorithm) {
    var rect = element.getBoundingClientRect(),
    		prect = (parent != undefined) ? parent.getBoundingClientRect() : element.parentNode.getBoundingClientRect(),
        csa = (crossSearchAlgorithm != undefined) ? crossSearchAlgorithm : false,
        efp = function (x, y) { return document.elementFromPoint(x, y) };
    // Return false if it's not in the viewport
    if (rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom) {
        return false;
    }
    var flag = false;
    // Return true if left to right any border pixel reached 
    for (var x = rect.left; x < rect.right; x++) {
    	if (element.contains(efp(rect.top, x)) || element.contains(efp(rect.bottom, x))) {
        flag = true;
        break;
      }
    }
    // Return true if top to bottom any border pixel reached 
    if (flag == false) {
      for (var y = rect.top; y < rect.bottom; y++) {
        if (element.contains(efp(rect.left, y)) || element.contains(efp(rect.right, y))) {
          flag = true;
          break;
        }
      }
    }
    if(csa) {
      // Another algorithm to check if element is centered and bigger than viewport
      if (flag == false) {
        var x = rect.left;
        var y = rect.top;
        // From top left to bottom right
        while(x < rect.right || y < rect.bottom) {
          if (element.contains(efp(x,y))) {
            flag = true;
            break;
          }
          if(x < rect.right) { x++; }
          if(y < rect.bottom) { y++; }
        }
        if (flag == false) {
          x = rect.right;
          y = rect.top;
          // From top right to bottom left
          while(x > rect.left || y < rect.bottom) {
            if (element.contains(efp(x,y))) {
              flag = true;
              break;
            }
            if(x > rect.left) { x--; }
            if(y < rect.bottom) { y++; }
          }
        }
      }
    }
    return flag;
}

// Check multiple elements visibility
document.getElementById('container').addEventListener("scroll", function() {
	var elementList = document.getElementsByClassName("element");
  var console = document.getElementById('console');
	for (var i=0; i < elementList.length; i++) {
  	// I did not define parent so it will be element's parent
    // and It will do crossSearchAlgorithm
    if (isVisible(elementList[i],null,true)) {
  		console.innerHTML = "Element with id[" + elementList[i].id + "] is visible!";
      break;
    } else {
    	console.innerHTML = "Element with id[" + elementList[i].id + "] is hidden!";
    }
  }
});
// Dynamically added elements
for(var i=4; i <= 6; i++) {
  var newElement = document.createElement("div");
  newElement.id = "element" + i;
  newElement.classList.add("element");
  document.getElementById('container').appendChild(newElement);
}
#console { background-color: yellow; }
#container {
  width: 300px;
  height: 100px;
  background-color: lightblue;
  overflow-y: auto;
  padding-top: 150px;
  margin: 45px;
}
.element {
  margin: 400px;
  width: 400px;
  height: 320px;
  background-color: green;
}
#element3 {
  position: relative;
  margin: 40px;
  width: 720px;
  height: 520px;
  background-color: green;
}
#element3::before {
  content: "";
  position: absolute;
  top: -10px;
  left: -10px;
  margin: 0px;
  width: 740px;
  height: 540px;
  border: 5px dotted green;
  background: transparent;
}
<div id="console"></div>
<div id="container">
    <div id="element1" class="element"></div>
    <div id="element2" class="element"></div>
    <div id="element3" class="element"></div>
</div>

JSFiddle для проигрывания с: http://jsfiddle.net/BerkerYuceer/grk5az2c/

, Если у меня было больше времени, это могло бы быть улучшено еще больше для создания новой библиотеки для нуждающихся.

Особая благодарность [1 156] @Andy E для обеспечения этой перспективы мне.

Важное Редактирование: Этот код сделан для более точной информации если любая часть элемента, показанного в представлении или нет. Для параметров быстродействия или только вертикальные слайды не используют это! Этот код является более эффективным при рисовании случаев.

1
ответ дан 22 November 2019 в 21:08
поделиться

Принятые ответы не работают при увеличивании хрома на Android. В сочетании с ответ даН , для составления хрома на андроиде должен использоваться visualViewport. Следующий пример только принимает вертикальную проверку во внимание и использует jQuery для высоты окна:

var Rect=YOUR_ELEMENT.getBoundingClientRect();
var ElTop=Rect.top, ElBottom=Rect.bottom;
var WindowHeight=$(window).height();
if(window.visualViewport) {
    ElTop-=window.visualViewport.offsetTop;
    ElBottom-=window.visualViewport.offsetTop;
    WindowHeight=window.visualViewport.height;
}
var WithinScreen=(ElTop>=0 && ElBottom<=WindowHeight);
0
ответ дан 22 November 2019 в 21:08
поделиться

Есть плагин jQuery под названием inview, который делает эту работу

25
ответ дан 22 November 2019 в 21:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: