通过线性查找检索出现在视口内的元素,效率较低 比如 js寻找在视口内的元素-线性查找 对100个元素进行查找,需要循环100次,或者找到之后跳出循环。
通过二分查找改进,先找到一个出现在视口内的元素,再从它的上下查找。
码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style>
ul li{list-style: none;padding: 20px}
li:nth-child(even){background: green;margin: 50px}
li:nth-child(odd){background: yellowgreen}
</style>
</head>
<body>
<h2>寻找在视口内的元素 二分查找</h2>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
<li>21</li>
<li>22</li>
<li>23</li>
<li>24</li>
<li>25</li>
<li>26</li>
<li>27</li>
<li>28</li>
<li>29</li>
<li>30</li>
<li>31</li>
<li>32</li>
<li>33</li>
<li>34</li>
<li>35</li>
<li>36</li>
<li>37</li>
<li>38</li>
<li>39</li>
<li>40</li>
<li>41</li>
<li>42</li>
<li>43</li>
<li>44</li>
<li>45</li>
<li>46</li>
<li>47</li>
<li>48</li>
<li>49</li>
<li>50</li>
<li>51</li>
<li>52</li>
<li>53</li>
<li>54</li>
<li>55</li>
<li>56</li>
<li>57</li>
<li>58</li>
<li>59</li>
<li>60</li>
<li>61</li>
<li>62</li>
<li>63</li>
<li>64</li>
<li>65</li>
<li>66</li>
<li>67</li>
<li>68</li>
<li>69</li>
<li>70</li>
<li>71</li>
<li>72</li>
<li>73</li>
<li>74</li>
<li>75</li>
<li>76</li>
<li>77</li>
<li>78</li>
<li>79</li>
<li>80</li>
<li>81</li>
<li>82</li>
<li>83</li>
<li>84</li>
<li>85</li>
<li>86</li>
<li>87</li>
<li>88</li>
<li>89</li>
<li>90</li>
<li>91</li>
<li>92</li>
<li>93</li>
<li>94</li>
<li>95</li>
<li>96</li>
<li>97</li>
<li>98</li>
<li>99</li>
<li>100</li>
</ul>
</body>
<script>
window.onscroll = function () {
// 找到第一个在视口内的元素
console.log(`找到的第一个元素----${binarySearch() + 1}`)
// 然后根据页面特征从找到元素的上下位置继续查找出现在视口内的元素
}
function binarySearch () {
var listChild = document.getElementsByTagName('li')
var max = listChild.length - 1 // 最大值
var min = 0 // 最小值
while (min <= max) {
var mid = Math.floor((max + min) / 2) // 中间值
console.log('mid', mid)
console.log('isInViewport(listChild[mid])', isInViewport(listChild[mid]))
if (isInViewport(listChild[mid]) > 0) {
// 在视口下
min = mid + 1
} else if (isInViewport(listChild[mid]) < 0) {
// 在视口上
max = mid - 1
} else {
// 二分查找一个在视口内的元素
return mid
}
}
return -1
}
function isInViewport (target) {
var divH = target.offsetHeight // div高度
var windowH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight // 浏览器高度兼容写法
var obj = getRect(target)
if (obj.top >= windowH) { // 在视口之下
console.log('视口之下')
return -1
}
if (obj.top < windowH && obj.bottom >= windowH) { // 正在出现
console.log('正在出现')
return 0
}
if (obj.top > 0 && obj.top < windowH && obj.bottom > 0 && obj.bottom < windowH) { // 正在视口中
console.log('正在视口中')
return 0
}
if (obj.top <= 0 && obj.bottom <= divH && obj.bottom > 0) { // 正在离开视口
console.log('正在离开视口')
return 0
}
if (obj.bottom <= 0) { // 已经离开视口
console.log('视口之上')
return 1
}
return -1
}
function getRect (element) {
var rect = element.getBoundingClientRect() // 距离视窗的距离
var top = document.documentElement.clientTop ? document.documentElement.clientTop : 0 // html元素对象的上边框的宽度
var left = document.documentElement.clientLeft ? document.documentElement.clientLeft : 0
return {
top: rect.top - top,
bottom: rect.bottom - top,
left: rect.left - left,
right: rect.right - left
}
}
</script>
</html>
图片
tutu.gif







网友评论