運動除了直線運動和曲線運動兩種運動形式外,還有一種運動形式是滑鼠跟隨運動,而這種跟隨運動需要用到三角函數的相關內容或者需要進行比例運算。本文將以幾個小執行個體來介紹角度運動的相關內容
眼球轉動
在很多網頁中,都存在著跟隨運動,比如眼球轉動。滑鼠在網頁中移動時,眼球也會跟著朝相應方向轉動
上面是眼球轉動的示意圖,(x0,y0)是眼球的位置,而(x,y)是滑鼠的位置。設直線與垂直方向的夾角為a,假設圓心點座標為(0,0),可以得到以下公式
tan(a) = x/y = x0/y0
x0 = r*sin(a)
y0 = r*cos(a)
在mousemove事件中,可以很容易的得到滑鼠位置(x,y),由此求出夾角a,進而可以求出眼球的位置
設左眼為ball1,右眼為ball2。左眼的圓心座標是(39,72),右眼的圓心座標是(106,68),眼球可以移動的半徑是12px
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><style>#test{position: absolute;top: 100px;left: 200px;}#ball1{position: absolute;top: 62px;left: 28px;}#ball2{position: absolute;top: 58px;left: 96px;}</style></head><body><div id="test"> <img src="head.png" alt="body"> <img id="ball1" src="ball.png" alt="ball"> <img id="ball2" src="ball.png" alt="ball"> </div><script>//聲明腦袋的預設位移var offsetLeft = test.offsetLeft;var offsetTop = test.offsetTop;//聲明左眼夾角a1、右眼夾角a2var a1,a2;//聲明左眼圓心(X1,Y1)、右眼圓心(X2,Y2)var X1 = 38,Y1 = 72,X2 = 106,Y2 = 68;//聲明半徑var R = 12;document.onmousemove = function(e){ e = e || event; //擷取滑鼠座標 var x = e.clientX; var y = e.clientY; //更新夾角a1、a2 a1 = Math.atan2(x-X1-offsetLeft,y-Y1-offsetTop); a2 = Math.atan2(x-X2-offsetLeft,y-Y2-offsetTop); //更新左眼、右眼的left、top值 ball1.style.left = R*Math.sin(a1) + X1 -10 + 'px'; ball1.style.top = R*Math.cos(a1) + Y1 -10+ 'px'; ball2.style.left = R*Math.sin(a2) + X2 -10 + 'px'; ball2.style.top = R*Math.cos(a2) + Y2 -10 + 'px';}</script></body></html>
蘋果菜單
蘋果菜單中也存在著滑鼠跟隨運動,與滑鼠距離越近的功能表項目的寬高越大,越遠則寬高越小
滑鼠座標可以通過mousemove事件中的clientX和clientY獲得。功能表項目的座標其實是已知項。而滑鼠座標與功能表項目的距離就是要求的距離,而距離與功能表項目的寬高成反比
[注意]不能夠將元素的自訂屬性命名為x,因為x已經被瀏覽器使用
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><style>body{margin: 0;}#test{position: absolute;bottom:0;width: 100%;text-align: center;}img{width: 64px;height: 64px;}</style></head><body><div id="test"> <img id="img1" src="img/1.png"> <img src="img/2.png"> <img src="img/3.png"> <img src="img/4.png"> <img src="img/5.png"> </div><script>//聲明功能表項目的寬高值var offsetWidth = img1.offsetWidth;var offsetHeight = img1.offsetHeight;//聲明外層盒子的left、top值var offsetLeft = test.offsetLeft;var offsetTop = test.offsetTop;//擷取功能表項目var imgs = test.getElementsByTagName('img');document.onmousemove = function(e){ e = e || event; //更新滑鼠位置 var x = e.clientX; var y = e.clientY; for(var i = 0; i < imgs.length; i++){ //擷取功能表項目的座標 imgs[i].x0= imgs[i].offsetLeft+offsetLeft+imgs[i].offsetWidth/2; imgs[i].y0 = imgs[i].offsetTop + offsetTop + imgs[i].offsetHeight/2; //更新滑鼠與功能表項目的距離 imgs[i].len =Math.sqrt((x-imgs[i].x0)*(x-imgs[i].x0) + (y-imgs[i].y0)*(y-imgs[i].y0)); //限制範圍 if(imgs[i].len > 150){ imgs[i].len = 150; } //更新功能表項目的寬高 imgs[i].style.width = (1-imgs[i].len/300)*2*offsetWidth + 'px'; imgs[i].style.height = (1-imgs[i].len/300)*2*offsetHeight + 'px'; }}</script></body></html>
方向跟隨
有許多網頁都有方向跟隨的效果。滑鼠從哪個方向移入,元素就跟著從哪個方向移入。滑鼠從哪個方向移出,類似地,元素也跟著從哪個方向移出
移入移出的運動效果使用勻速直線運動即可,這裡主要需要判斷方向
由示意圖中所示,可以把一個正方形的元素分成(上-右、上-左、左-上、左-下、下-右、下-左、右-上、右-下)這8個部分,每個部分是一個等腰直角三角形,當元素進入某個地區時,橫線前面的方向就表示元素的方向
假設正方形的中心座標為(x0,y0),動態元素(move)進入時的座標為(x,y),以這兩個座標組成的直線與水平正方向的直線的夾角作為基準角,假設為a,則通過確定夾角a的範圍,可以確定動態元素(move)進入的方向
-45<a<45時,進入方向為右
45<a<135時,進入方向為上
a>135或a<-135時,進入方向為左
-135<a<-45時,進入方向為下
確定好動態元素(move)進入的方向後,需要根據方向,將動態元素(move)瞬間變換到對應的位置。然後,動態元素(move)進行勻速直線運動,最終停止在與靜態元素(test)重合的位置
動態元素(move)移出靜態元素(test)的範圍時,要注意的是,並不會觸發靜態元素(test)的mouseout事件。因為,此時滑鼠一直處於動態元素(move)上。所以,觸發的是動態元素(move)的mouseout事件
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><style>#box{overflow: hidden;position: relative;left: 100px;top: 100px;height: 100px;width: 300px;}.test{width: 100px;height: 100px;position: absolute;font:20px/100px '宋體';text-align: center;} </style></head><body><div id="box"> <div class="test" style="top: 0px;left: 0px;background-color: pink;">1</div> <div class="test" style="top: 0px;left: 100px;background-color: lightcoral;">2</div> <div class="test" style="top: 0px;left: 200px;background-color: lightgreen;">3</div> <div id="move" style="width: 100px;height: 100px;background-color: lightblue;position: absolute;top: -100px;left: -100px;"></div> </div><script>var tests = box.getElementsByTagName('div');for(var i = 0; i < tests.length; i++){ tests[i].onmouseover = fn;}//滑鼠移出動態元素(move)時,再將fn()函數置於所有靜態元素上move.onmouseout = fn;function fn(e){ e = e || event; //阻止冒泡 if(e.stopPropagation){ e.stopPropagation(); }else{ e.cancelBubble = true; } for(var i = 0; i < tests.length; i++){ tests[i].onmouseover = fn; } var _this = this; //滑鼠移入動態元素(move)時,將靜態元素上的mouseover事件置空 move.onmouseover = function(){ move.innerHTML = _this.innerHTML; _this.onmouseover = null; } //聲明座標 var x = e.clientX; var y = e.clientY; //聲明靜態元素(test)左上方座標(相對於父級) var x11 = this.offsetLeft; var y11 = this.offsetTop; //聲明靜態元素(test)中心點座標(相對於父級) var x10 = x11 + this.offsetWidth/2; var y10 = y11 + this.offsetHeight/2; //聲明靜態元素(test)左上方座標(相對於文檔) var x21 = this.parentNode.offsetLeft + x11; var y21 = this.parentNode.offsetTop + y11; //聲明靜態元素(test)中心點座標(相對於文檔) var x20 = x21 + this.offsetWidth/2; var y20 = y21 + this.offsetHeight/2; //聲明靜態元素寬高 var height = this.offsetHeight; var width = this.offsetWidth; //聲明並計算夾角 var a = Math.atan2(y20-y,x-x20)*180/Math.PI; //聲明並計算方向 var dir; if(a > -45 && a < 45){ dir = 'right'; }else if(a > 45 && a < 135){ dir = 'top'; }else if(a > -135 && a < 45){ dir = 'bottom'; }else{ dir = 'left'; } //滑鼠移入時 if(e.type == 'mouseover'){ //更新動態元素(move)的初始位置 //移動動態元素(move)直到完全覆蓋靜態元素(test) if(dir == 'right'){ move.style.left = x10 + width/2 + 'px'; move.style.top = y10 - height/2 + 'px'; fnMove(move,'left',x11) }else if(dir == 'top'){ move.style.left = x10 - width/2 + 'px'; move.style.top = y10 - height/2 - height + 'px'; fnMove(move,'top',y11) }else if(dir == 'left'){ move.style.left = x10 - width/2 - width + 'px'; move.style.top = y10 - height/2 + 'px'; fnMove(move,'left',x11) }else{ move.style.left = x10 - width/2 + 'px'; move.style.top = y10 - height/2 + height + 'px'; fnMove(move,'top',y11) } } if(e.type == 'mouseout'){ //滑鼠移出時 if(dir == 'right'){ fnMove(move,'left',x11 + width); }else if(dir == 'top'){ fnMove(move,'top',y11 - height); }else if(dir == 'left'){ fnMove(move,'left',x11 - width); }else{ fnMove(move,'top',y11 + height); } }}function getCSS(obj,style){ if(window.getComputedStyle){ return getComputedStyle(obj)[style]; } return obj.currentStyle[style];}function fnMove(obj,attr,target){ var H = obj.offsetHeight; if(obj.timer) return; var cur = parseFloat(getCSS(obj,attr)); if(target > cur){ var step = H/4; }else{ var step = -H/4; } obj.timer = setInterval(function(){ cur = parseFloat(getCSS(obj,attr)); cur = cur + step; if((cur -target) * step >= 0){ cur = target; } obj.style[attr] = cur + 'px'; if(cur == target){ clearInterval(obj.timer); obj.timer = 0; } },20);} </script> </body></html>
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。