javascript鼠標(biāo)跟隨運(yùn)動(dòng)3種效果(眼球效果,蘋果菜單,方向跟隨)
運(yùn)動(dòng)除了直線運(yùn)動(dòng)和曲線運(yùn)動(dòng)兩種運(yùn)動(dòng)形式外,還有一種運(yùn)動(dòng)形式是鼠標(biāo)跟隨運(yùn)動(dòng),而這種跟隨運(yùn)動(dòng)需要用到三角函數(shù)的相關(guān)內(nèi)容或者需要進(jìn)行比例運(yùn)算。本文將以幾個(gè)小實(shí)例來(lái)介紹角度運(yùn)動(dòng)的相關(guān)內(nèi)容
眼球轉(zhuǎn)動(dòng)
在很多網(wǎng)頁(yè)中,都存在著跟隨運(yùn)動(dòng),比如眼球轉(zhuǎn)動(dòng)。鼠標(biāo)在網(wǎng)頁(yè)中移動(dòng)時(shí),眼球也會(huì)跟著朝相應(yīng)方向轉(zhuǎn)動(dòng)
上面是眼球轉(zhuǎn)動(dòng)的示意圖,(x0,y0)是眼球的位置,而(x,y)是鼠標(biāo)的位置。設(shè)直線與垂直方向的夾角為a,假設(shè)圓心點(diǎn)坐標(biāo)為(0,0),可以得到以下公式
tan(a) = x/y = x0/y0
x0 = r*sin(a)
y0 = r*cos(a)
在mousemove事件中,可以很容易的得到鼠標(biāo)位置(x,y),由此求出夾角a,進(jìn)而可以求出眼球的位置
設(shè)左眼為ball1,右眼為ball2。左眼的圓心坐標(biāo)是(39,72),右眼的圓心坐標(biāo)是(106,68),眼球可以移動(dòng)的半徑是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> //聲明腦袋的默認(rèn)偏移 var offsetLeft = test.offsetLeft; var offsetTop = test.offsetTop; //聲明左眼夾角a1、右眼夾角a2 var 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; //獲取鼠標(biāo)坐標(biāo) 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>
蘋果菜單
蘋果菜單中也存在著鼠標(biāo)跟隨運(yùn)動(dòng),與鼠標(biāo)距離越近的菜單項(xiàng)的寬高越大,越遠(yuǎn)則寬高越小
鼠標(biāo)坐標(biāo)可以通過(guò)mousemove事件中的clientX和clientY獲得。菜單項(xiàng)的坐標(biāo)其實(shí)是已知項(xiàng)。而鼠標(biāo)坐標(biāo)與菜單項(xiàng)的距離就是要求的距離,而距離與菜單項(xiàng)的寬高成反比
[注意]不能夠?qū)⒃氐淖远x屬性命名為x,因?yàn)閤已經(jīng)被瀏覽器使用
<!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> //聲明菜單項(xiàng)的寬高值 var offsetWidth = img1.offsetWidth; var offsetHeight = img1.offsetHeight; //聲明外層盒子的left、top值 var offsetLeft = test.offsetLeft; var offsetTop = test.offsetTop; //獲取菜單項(xiàng) var imgs = test.getElementsByTagName('img'); document.onmousemove = function(e){ e = e || event; //更新鼠標(biāo)位置 var x = e.clientX; var y = e.clientY; for(var i = 0; i < imgs.length; i++){ //獲取菜單項(xiàng)的坐標(biāo) imgs[i].x0= imgs[i].offsetLeft+offsetLeft+imgs[i].offsetWidth/2; imgs[i].y0 = imgs[i].offsetTop + offsetTop + imgs[i].offsetHeight/2; //更新鼠標(biāo)與菜單項(xiàng)的距離 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; } //更新菜單項(xiàng)的寬高 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>
方向跟隨
有許多網(wǎng)頁(yè)都有方向跟隨的效果。鼠標(biāo)從哪個(gè)方向移入,元素就跟著從哪個(gè)方向移入。鼠標(biāo)從哪個(gè)方向移出,類似地,元素也跟著從哪個(gè)方向移出
移入移出的運(yùn)動(dòng)效果使用勻速直線運(yùn)動(dòng)即可,這里主要需要判斷方向
由示意圖中所示,可以把一個(gè)正方形的元素分成(上-右、上-左、左-上、左-下、下-右、下-左、右-上、右-下)這8個(gè)部分,每個(gè)部分是一個(gè)等腰直角三角形,當(dāng)元素進(jìn)入某個(gè)區(qū)域時(shí),橫線前面的方向就表示元素的方向
假設(shè)正方形的中心坐標(biāo)為(x0,y0),動(dòng)態(tài)元素(move)進(jìn)入時(shí)的坐標(biāo)為(x,y),以這兩個(gè)坐標(biāo)組成的直線與水平正方向的直線的夾角作為基準(zhǔn)角,假設(shè)為a,則通過(guò)確定夾角a的范圍,可以確定動(dòng)態(tài)元素(move)進(jìn)入的方向
-45<a<45時(shí),進(jìn)入方向?yàn)橛?br /> 45<a<135時(shí),進(jìn)入方向?yàn)樯?br /> a>135或a<-135時(shí),進(jìn)入方向?yàn)樽?br /> -135<a<-45時(shí),進(jìn)入方向?yàn)橄?br />
確定好動(dòng)態(tài)元素(move)進(jìn)入的方向后,需要根據(jù)方向,將動(dòng)態(tài)元素(move)瞬間變換到對(duì)應(yīng)的位置。然后,動(dòng)態(tài)元素(move)進(jìn)行勻速直線運(yùn)動(dòng),最終停止在與靜態(tài)元素(test)重合的位置
動(dòng)態(tài)元素(move)移出靜態(tài)元素(test)的范圍時(shí),要注意的是,并不會(huì)觸發(fā)靜態(tài)元素(test)的mouseout事件。因?yàn)椋藭r(shí)鼠標(biāo)一直處于動(dòng)態(tài)元素(move)上。所以,觸發(fā)的是動(dòng)態(tài)元素(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; } //鼠標(biāo)移出動(dòng)態(tài)元素(move)時(shí),再將fn()函數(shù)置于所有靜態(tài)元素上 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; //鼠標(biāo)移入動(dòng)態(tài)元素(move)時(shí),將靜態(tài)元素上的mouseover事件置空 move.onmouseover = function(){ move.innerHTML = _this.innerHTML; _this.onmouseover = null; } //聲明坐標(biāo) var x = e.clientX; var y = e.clientY; //聲明靜態(tài)元素(test)左上角坐標(biāo)(相對(duì)于父級(jí)) var x11 = this.offsetLeft; var y11 = this.offsetTop; //聲明靜態(tài)元素(test)中心點(diǎn)坐標(biāo)(相對(duì)于父級(jí)) var x10 = x11 + this.offsetWidth/2; var y10 = y11 + this.offsetHeight/2; //聲明靜態(tài)元素(test)左上角坐標(biāo)(相對(duì)于文檔) var x21 = this.parentNode.offsetLeft + x11; var y21 = this.parentNode.offsetTop + y11; //聲明靜態(tài)元素(test)中心點(diǎn)坐標(biāo)(相對(duì)于文檔) var x20 = x21 + this.offsetWidth/2; var y20 = y21 + this.offsetHeight/2; //聲明靜態(tài)元素寬高 var height = this.offsetHeight; var width = this.offsetWidth; //聲明并計(jì)算夾角 var a = Math.atan2(y20-y,x-x20)*180/Math.PI; //聲明并計(jì)算方向 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'; } //鼠標(biāo)移入時(shí) if(e.type == 'mouseover'){ //更新動(dòng)態(tài)元素(move)的初始位置 //移動(dòng)動(dòng)態(tài)元素(move)直到完全覆蓋靜態(tài)元素(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'){ //鼠標(biāo)移出時(shí) 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>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- js實(shí)現(xiàn)簡(jiǎn)單鼠標(biāo)跟隨效果的方法
- 簡(jiǎn)單實(shí)現(xiàn)js鼠標(biāo)跟隨效果
- js鼠標(biāo)跟隨運(yùn)動(dòng)效果
- Js鼠標(biāo)跟隨代碼小手點(diǎn)擊實(shí)例方法
- JS實(shí)現(xiàn)的簡(jiǎn)單鼠標(biāo)跟隨DiV層效果完整實(shí)例
- JS實(shí)現(xiàn)的鼠標(biāo)跟隨代碼(卡通手型點(diǎn)擊效果)
- js實(shí)現(xiàn)鼠標(biāo)跟隨運(yùn)動(dòng)效果
- 原生js實(shí)現(xiàn)鼠標(biāo)跟隨效果
- JavaScript實(shí)現(xiàn)的鼠標(biāo)跟隨特效示例【2則實(shí)例】
- js實(shí)現(xiàn)鼠標(biāo)跟隨小游戲
相關(guān)文章
Javascript調(diào)試之console對(duì)象——你不知道的一些小技巧
這篇文章主要總結(jié)了console對(duì)象的一些有用的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-07-07es6函數(shù)之箭頭函數(shù)用法實(shí)例詳解
這篇文章主要介紹了es6函數(shù)之箭頭函數(shù)用法,結(jié)合實(shí)例形式詳細(xì)分析了es6箭頭函數(shù)基本功能、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04document.compatMode的CSS1compat使用介紹
這篇文章主要介紹了document.compatMode的CSS1compat使用,需要的朋友可以參考下2014-04-04JavaScript兩種axios取消請(qǐng)求方式小結(jié)
本文主要介紹了JavaScript兩種axios取消請(qǐng)求方式小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03js print打印網(wǎng)頁(yè)指定區(qū)域內(nèi)容的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇js print打印網(wǎng)頁(yè)指定區(qū)域內(nèi)容的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11JavaScript 對(duì)象模型 執(zhí)行模型
簡(jiǎn)單數(shù)值類型: 有Undefined, Null, Boolean, Number和String。注意,描述中的英文單詞在這里僅指數(shù)據(jù)類型的名稱,并不特指JS的全局對(duì)象N an, Boolean, Number, String等,它們?cè)诟拍钌系膮^(qū)別是比較大的。2010-10-10JS遍歷數(shù)組及打印數(shù)組實(shí)例分析
這篇文章主要介紹了JS遍歷數(shù)組及打印數(shù)組的方法,結(jié)合實(shí)例形式分析JavaScript數(shù)組的遍歷與打印輸出相關(guān)技巧,需要的朋友可以參考下2016-01-01微信小程序控制臺(tái)提示warning:Now you can provide attr "wx:key" for a "w
這篇文章主要介紹了微信小程序控制臺(tái)提示warning:Now you can provide attr "wx:key" for a "wx:for" to improve performance解決方法,簡(jiǎn)單分析了wx:for警告提示相關(guān)解決方法,需要的朋友可以參考下2019-02-02ES6 javascript中class類的get與set用法實(shí)例分析
這篇文章主要介紹了ES6 javascript中class類的get與set用法,結(jié)合具體實(shí)例形式分析了ES6中類的get與set關(guān)鍵字使用方法,需要的朋友可以參考下2017-10-10javascript實(shí)現(xiàn)字符串反轉(zhuǎn)的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)字符串反轉(zhuǎn)的方法,實(shí)例分析了javascript實(shí)現(xiàn)字符串反轉(zhuǎn)的技巧,需要的朋友可以參考下2015-02-02