背景:

  今天,突然想到之前碰到过的一个场景:QQ空间中有着一些漂浮的装饰挂件,能够规律性在页面中移动(因为本人之前浏览别人空间时,确实遇到过装饰的非常好看的界面,因此印象比较深刻)。于是非常想知道这个功能是怎么实现的,于是就有了这一篇博客。

 

原理:

  其实,实现原理很简单,就是在页面中添加一些好看的元素,然后使用定时器周期性改变这些元素的位置,这实现了该功能。这个可以在你自己的QQ空间中去验证,如下图片所示:

 

 

 

 移动元素的原理

 

代码:

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>移动标签实践</title>
  6     <style>
  7         body {
  8             width: 1000px;
  9             height: 600px;
 10             margin: 0 auto;
 11             position: relative;
 12             border: black solid 1px;
 13         }
 14         #moveTag {
 15             width: 30px;
 16             height: 30px;
 17             margin: 0;
 18             position: absolute;
 19             box-sizing: border-box;
 20             border: black solid 1px;
 21         }
 22     </style>
 23 </head>
 24 <body>
 25     <div id="moveTag"></div>
 26     <script defer>
 27         // 将传入的属性(string型,单位为 px)转换为 Number
 28         const returnNumber = (num) => {
 29             let x = num.indexOf('p')
 30             return Number(num.slice(0, x))
 31         }
 32 
 33         // x 为计算过后的 margin 值,limit 表示移动的范围限制(分为横纵两轴),adjustment 表示的是移动元素的属性(分为width 和height)
 34         const dealLimit = (x, limit, adjustment) => {
 35             // console.log(x + ' ' + limit)
 36             if (x >= limit) {
 37                 // 之所以要是使用 limit - adjustment,是因为移动的元素不要移动到当前元素的外面(此时为最大值限制)
 38                 return limit - adjustment + 'px'
 39             } else if (x <= 0) {
 40                 // 此时为最小值限制
 41                 return 0 + 'px'
 42             } else {
 43                 // 如果移动的值在范围之内,则直接返回
 44                 return x + 'px'
 45             }
 46         }
 47 
 48         // 该函数是主要的变换函数
 49         const moveTagElement = () => {
 50             // 这里使用了闭包,保存了需要大量使用过的变量
 51 
 52             let ele = document.querySelector('#moveTag')
 53             // 获取<style>标签中的CSS值
 54             // 注意:ele.style.property 这种语法只能获取内联CSS的属性
 55             // 移动元素的width
 56             let moveTagwidth = returnNumber(window.getComputedStyle(ele).getPropertyValue('width'))
 57             // 移动元素的heigth
 58             let moveTagheight = returnNumber(window.getComputedStyle(ele).getPropertyValue('height'))
 59             // 由于 ele 不再使用,故释放 ele 的内存占用
 60             ele = null
 61 
 62             let box = document.querySelector('body')
 63             // 参照元素的width
 64             let boxWidth = returnNumber(window.getComputedStyle(box).getPropertyValue('width'))
 65             // 参照元素的height
 66             let boxHeight = returnNumber(window.getComputedStyle(box).getPropertyValue('height'))
 67             // 由于 box 不再使用,故释放 box 的内存占用
 68             box = null
 69 
 70             // 用来判断 marginTop 是 + 还是 - ,即移动元素在 x 方向上是右移还是左移
 71             let judgeTop = true
 72             // 用来判断 marginLeft 是 + 还是 -,即移动元素在 y 方向上是是下移还是上移
 73             let judgeLeft = true
 74 
 75             return function () {
 76                 let ele = document.querySelector('#moveTag')
 77                 let top = returnNumber(ele.style.marginTop)
 78                 let left = returnNumber(ele.style.marginLeft)
 79 
 80                 // 表示移动的量
 81                 let topChange = 10
 82                 let leftChange = 10
 83 
 84                 // 这里和前面需要保持一致
 85                 // 如果超过 box 的限制,则改变移动元素移动的方向(上下)
 86                 if (top <= 0 || top >= boxHeight - moveTagheight) {
 87                     judgeTop = !judgeTop
 88                 }
 89                 // 计算移动的值,并赋值
 90                 ele.style.marginTop = judgeTop ? dealLimit(top + topChange, boxHeight, moveTagheight) : dealLimit(top - topChange, boxHeight, moveTagheight)
 91 
 92                 // 如果超过 box 的限制,则改变移动元素移动的方向(左右)
 93                 if (left <= 0 || left >= boxWidth - moveTagwidth) {
 94                     judgeLeft = !judgeLeft
 95                 }
 96                 // 计算移动的值,并赋值
 97                 ele.style.marginLeft = judgeLeft ? dealLimit(left + leftChange, boxWidth, moveTagwidth) : dealLimit(left - leftChange, boxWidth, moveTagwidth)
 98             }
 99         }
100 
101         let func = moveTagElement()
102         // 使用定时器进行周期性控制
103         let timer = setInterval(func, 50)
104     </script>
105 </body>
106 </html>

 

运行结果:

运行结果

 

代码说明:

  代码在注释中说的非常明白了,同时原理也并非很复杂,所以这里并不打算在继续使用文字进行相关的原理的介绍,有兴趣的小伙伴可以直接复制代码进行查看。

 

个人吐槽:

  ①. 虽然运行的结果简陋了点,但是原理确实实现了,( 0.0 )如果想更加美观一点,只需要更改界面以及移动元素的背景图片即可。

  ②. 做完这个内容我发现了一个问题:那就是打砖块这个游戏其实原理就是这个(这里自己先挖一个坑)

  ③. over