今天要克隆的前端特效很是有意思,能夠參見GitHub404頁面 https://github.com/vajoy/master/index.html css
記得以前華爲在站酷發佈EMUI設計大賽的主頁也用了這種特效。說簡單點,就是鼠標在頁面移動時,banner上的圖片呈現有層次的空間軸動特效,效果圖以下:html
我們先仿造GitHub 404頁面來寫一下banner原型——前景有「魷魚」和「對話框」,遠景有倆小屋子:前端
代碼以下git
<!doctype html> <html> <head> <style> body,heml{margin:0; padding:0;} .bannerWrap{ position:relative; margin:0 auto;width:1000px; height:350px; background-color:#F0E262; overflow:hidden;} .bannerWrap img{ display:block; position:absolute;} </style> <script src="jq.js"></script> <meta charset="utf-8"> <title>層級圖片軸動效果</title> </head> <body> <div class="bannerWrap" id="bannerWrap"> <img src="house2.png" class="small_house" id="small_house" /> <img src="house1.png" class="house" id="house" /> <img src="fish.png" class="fish" id="fish" /> <img src="404.png" class="info" id="info" /> </div><!--bannerWrap結束--> </body> </html>
接着寫腳本前先分析一下,如何作到讓鼠標在屏幕上的位置,能夠映射爲圖片在banner上的位置呢?好比鼠標在屏幕最右上角的位置時,前景的圖片也在banner裏所能移動到的最右上角的位置(遠景圖片爲相反的方位,即左下角)。github
又如何讓每一個圖片移動的距離和方位都各不相同?好比遠景的兩個小屋子圖片,最遠的屋子移動的速度比近一點的屋子的速度要快。且近景和遠景圖片所移動的方位是相反的。ide
⑴ 首先第一個問題,咱們能夠聯想到數位板,一塊長方形的數位板能夠匹配各類型號的電腦屏幕,不管你的數控筆移動到數位板的哪一個位置,它都能控制鼠標移動到對應比例的屏幕位置。是的,咱們提到了「比例」這東西,它遵循:spa
鼠標x座標 / 屏幕寬度 = 數控筆在數位板上的x座標 / 數位板寬度 ;設計
鼠標y座標 / 屏幕高度 = 數控筆在數位板上的y座標 / 數位板高度 ;3d
咱們引伸到如今的例子來,不外乎是把數控筆換成banner上的圖片,把數位板換成banner罷了。咱們能夠很輕易地獲取屏幕寬度、banner寬度、鼠標移動時的x、y座標,那麼天然能夠依據上面的公式來反推出圖片所應在banner上的x、y座標,哦,不對,應該說是相對banner而言的left、top偏移。指針
⑵ 至於第二個問題,咱們能夠給每張圖片設置一個Boolean參數判斷其是否前景圖片,若是是,則依循鼠標移動位置移動,若是不是則以相反方向移動。
咱們也能夠給每張圖片設置一個scale比例參數,參數越大者則移動的位置越大,從而控制其移動速度。
⑶ 另有一個須要考慮的問題是,在頁面剛加載好(假設鼠標還沒作任何移動)的時候,各圖片所在banner的位置應當是與鼠標移動到屏幕正中點的時候所在位置一致的。這要求咱們在初始化各圖片的時候,就先模擬出鼠標指針在屏幕正中的效果。
咱們能夠寫出初步的腳本代碼:
$(function(){ var win_w, win_h,b_w, b_h, small_house, house, fish, info, pToW_w, pToW_h, $img, temp_p_l, temp_p_t; var $banner = $("#bannerWrap"); var picArray = "small_house,house,fish,info".split(","); small_house = { l: 800, t: -140, s: 0.09, isFront: false }, //smallhouse的參數 house = { l: 130, t: -130, s: 0.05, isFront: false }, //house的參數 fish = { l: -100, t: -90, s: 0.02, isFront: true }, //fish的參數 info = { l: -350, t: -110, s: 0.03, isFront: true }; //info的參數 win_w = $(window).width(); //初始化獲取屏幕寬度 win_h = $(window).height(); //初始化獲取屏幕高度 pToW_w = $banner.width()/win_w; //初始化獲取banner寬度和屏幕寬度的比例 pToW_h = $banner.height()/win_h; //初始化獲取banner高度和屏幕高度的比例 $.each( picArray, function(i ,id){ //初始化各圖片的位置(至關於鼠標移到屏幕中間時圖片的位置) $img = $("#"+ id); temp_p_l = pToW_w * eval(id+".s") * win_w/2 ; //這裏使用win_w/2是爲了模擬鼠標移到屏幕水平中點的效果 temp_p_t = pToW_h * eval(id+".s") * win_h/2 ; //這裏使用win_h/2是爲了模擬鼠標移到屏幕垂直中點的效果 if(eval(id +".isFront")){ $img.css({"left": eval(id +".l") + temp_p_l , "top": eval(id +".t") + temp_p_t }); }else{ $img.css({"left": eval(id +".l") - temp_p_l , "top": eval(id +".t") - temp_p_t }); } }) var changePst = function( pageX, pageY ){ $.each( picArray, function(i ,id){ $img = $("#"+ id); temp_p_l = pToW_w * eval(id +".s") * pageX ; temp_p_t = pToW_h * eval(id +".s") * pageY ; if(eval(id +".isFront")){ $img.css({"left": eval(id +".l") + temp_p_l , "top": eval(id +".t") + temp_p_t }); }else{ $img.css({"left": eval(id +".l") - temp_p_l , "top": eval(id +".t") - temp_p_t }); } }) } $("body,html").mousemove(function(e){ //鼠標在屏幕移動時觸發changePst事件 changePst(e.pageX, e.pageY); }) })
每一個圖片都有 l、t、s、isFront 這四個參數。
其中 l 和 t 表示圖片相對banner的初步偏移位置(後面還要再加上或減去temp_p_*來獲得最終偏移位置);s表示縮放級別,數值越大則該圖片移動的距離越大;isFront則是判斷是否前景圖片。
雖然上方腳本初步實現咱們想要的功能,卻沒考慮到一個問題,即屏幕被縮放時,圖片的位置、應偏移的距離都會出錯,由於可能banner的寬度已經再也不是原來的寬度(banner寬度爲百分比)、屏幕的寬高也再也不是原來的寬高(計算圖片偏移距離涉及到屏幕寬高)。
因此咱們把初始化事件封裝起來,供屏幕縮放時調用。同時動態獲取banner寬度,而不是生硬地寫入到各圖片初始化的l參數中:
$(function(){ var win_w, win_h,b_w, b_h, small_house, house, fish, info, pToW_w, pToW_h, $img, temp_p_l, temp_p_t; var $banner = $("#bannerWrap"); var picArray = "small_house,house,fish,info".split(","); small_house = { l: 200, t: -140, s: 0.09, isFront: false }, house = { l: 70, t: -130, s: 0.05, isFront: false }, fish = { l: -160, t: -90, s: 0.02, isFront: true }, info = { l: -410, t: -110, s: 0.03, isFront: true }; var resetImg = function(){ b_w = $banner.width(); //初始化獲取banner寬度 b_h = $banner.height(); //初始化獲取banner高度 win_w = $(window).width(); win_h = $(window).height(); pToW_w = $banner.width()/win_w; pToW_h = $banner.height()/win_h; $.each( picArray, function(i ,id){ //初始化各圖片的位置(至關於鼠標移到屏幕中間時圖片的位置) $img = $("#"+ id); temp_p_l = pToW_w * eval(id+".s") * win_w/2 ; temp_p_t = pToW_h * eval(id+".s") * win_h/2 ; if(eval(id +".isFront")){ $img.css({"left": b_w/2 + eval(id +".l") + temp_p_l , "top": b_h/2 + eval(id +".t") + temp_p_t }); //動態加上banner寬高 }else{ $img.css({"left": b_w/2 + eval(id +".l") - temp_p_l , "top": b_h/2 + eval(id +".t") - temp_p_t }); } }) } resetImg(); $(window).on("resize",resetImg); //屏幕縮放時從新初始化數據 var changePst = function( pageX, pageY ){ $.each( picArray, function(i ,id){ $img = $("#"+ id); temp_p_l = pToW_w * eval(id +".s") * pageX ; temp_p_t = pToW_h * eval(id +".s") * pageY ; if(eval(id +".isFront")){ $img.css({"left": b_w/2 + eval(id +".l") + temp_p_l , "top": b_h/2 + eval(id +".t") + temp_p_t }); }else{ $img.css({"left": b_w/2 + eval(id +".l") - temp_p_l , "top": b_h/2 + eval(id +".t") - temp_p_t }); } }) } $("body,html").mousemove(function(e){ changePst(e.pageX, e.pageY); }) })
至此咱們完成了咱們所預期的功能。
眼尖的同窗會發現,resetImg事件裏的.each方法跟changePst事件裏的很是類似。咱們能夠把它們整合起來提升複用、減小代碼量:
$(function(){ var win_w, win_h,b_w, b_h, small_house, house, fish, info, pToW_w, pToW_h, $img, temp_p_l, temp_p_t; var $banner = $("#bannerWrap"); var picArray = "small_house,house,fish,info".split(","); small_house = { l: 200, t: -140, s: 0.09, isFront: false }, //smallhouse的參數 house = { l: 70, t: -130, s: 0.05, isFront: false }, //house的參數 fish = { l: -160, t: -90, s: 0.02, isFront: true }, //fish的參數 info = { l: -410, t: -110, s: 0.03, isFront: true }; //info的參數 var setPst = function(x, y){ x = x||win_w/2; y = y||win_h/2; $.each( picArray, function(i ,id){ $img = $("#"+ id); temp_p_l = pToW_w * eval(id+".s") * x ; temp_p_t = pToW_h * eval(id+".s") * y ; if(eval(id +".isFront")){ //判斷是否前景元素 $img.css({"left": b_w/2 + eval(id +".l") + temp_p_l , "top": b_h/2 + eval(id +".t") + temp_p_t }); //這裏的b_w/2和b_h/2是爲了保證窗口縮放時還能在相對位置 }else{ $img.css({"left": b_w/2 + eval(id +".l") - temp_p_l , "top": b_h/2 + eval(id +".t") - temp_p_t }); } }) } var resetImg = function(){ b_w = $banner.width(); //初始化獲取banner寬度 b_h = $banner.height(); //初始化獲取banner高度 win_w = $(window).width(); //初始化獲取屏幕寬度 win_h = $(window).height(); //初始化獲取屏幕高度 pToW_w = $banner.width()/win_w; //初始化獲取banner寬度和屏幕寬度的比例 pToW_h = $banner.height()/win_h; //初始化獲取banner高度和屏幕高度的比例 setPst(); } resetImg(); $(window).on("resize",resetImg); //屏幕縮放時從新初始化數據 $("body,html").mousemove(function(e){ setPst(e.pageX, e.pageY); }) })
最後仍是爲你們提供本案例的Demo,請到GitHub上下載:https://github.com/VaJoy/BlogDemo/tree/master/140809祝週末愉快,共勉~