今天要克隆的前端特效非常有意思,可以参见GitHub404页面 https://github.com/vajoy/master/index.html
记得之前华为在站酷发布EMUI设计大赛的主页也用了这种特效。说简单点,就是鼠标在页面移动时,banner上的图片呈现有层次的空间轴动特效,效果图如下:
咱们先仿造GitHub 404页面来写一下banner原型——前景有“鱿鱼”和“对话框”,远景有俩小屋子:
代码如下
<!doctype html> <htmlheadstyle> body,heml{margin:0; padding} .bannerWrap positionrelative margin0 autowidth1000px height350px background-color#F0E262 overflowhidden .bannerWrap img displayblockabsolute} </script src="jq.js"></scriptmeta charset="utf-8"title>层级图片轴动效果> bodydiv class="bannerWrap" id="bannerWrap"> img ="house2.png" class="small_house"="small_house" /> ="house1.png"="house"="house" ="fish.png"="fish"="fish" ="404.png"="info"="info" /> div><!--bannerWrap结束--> >
接着写脚本前先分析一下,如何做到让鼠标在屏幕上的位置,可以映射为图片在banner上的位置呢?比如鼠标在屏幕最右上角的位置时,前景的图片也在banner里所能移动到的最右上角的位置(远景图片为相反的方位,即左下角)。
又如何让每个图片移动的距离和方位都各不相同?比如远景的两个小屋子图片,最远的屋子移动的速度比近一点的屋子的速度要快。且近景和远景图片所移动的方位是相反的。
⑴ 首先第一个问题,我们可以联想到数位板,一块长方形的数位板可以匹配各种型号的电脑屏幕,无论你的数控笔移动到数位板的哪个位置,它都能控制鼠标移动到对应比例的屏幕位置。是的,我们提到了“比例”这东西,它遵循:
鼠标x坐标 / 屏幕宽度 = 数控笔在数位板上的x坐标 / 数位板宽度 ;
鼠标y坐标 / 屏幕高度 = 数控笔在数位板上的y坐标 / 数位板高度 ;
我们引申到现在的例子来,不外乎是把数控笔换成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,info".split(","); small_house = { l: 800,t: -140,s: 0.09,isFront: false },//smallhouse的参数 house = { l: 130,t: -130,s: 0.05,1)">house的参数 fish = { l: -100,t: -90,s: 0.02,1)">true },1)">fish的参数 info = { l: -350,t: -110,s: 0.03,1)">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 = ( pageX,pageY ){ $.each( picArray,1)">(i,id){ $img = $("#"+ id); temp_p_l = pToW_w * eval(id +".s") * pageX ; temp_p_t = pToW_h * eval(id +".s") * pageY ; )){ $img.css({"left": eval(id +".l") + temp_p_l,1)"> temp_p_t }); }{ $img.css({"left": eval(id +".l") - temp_p_l,1)"> 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参数中:
$(); small_house = { l: 200,1)">false },house = { l: 70,fish = { l: -160,1)">true }; var resetImg = (){ 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,1)">初始化各图片的位置(相当于鼠标移到屏幕中间时图片的位置) $img = $("#"+ id); temp_p_l = pToW_w * eval(id+".s") * win_w/2 ; temp_p_t = pToW_h * eval(id+".s") * win_h/2 ; )){ $img.css({"left": b_w/2 + eval(id +".l") + temp_p_l,"top": b_h/2 + eval(id +".t") + temp_p_t }); 动态加上banner宽高 }{ $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); 屏幕缩放时重新初始化数据 (e){ changePst(e.pageX,e.pageY); }) })
至此我们完成了我们所预期的功能。
眼尖的同学会发现,resetImg事件里的.each方法跟changePst事件里的非常相似。我们可以把它们整合起来提高复用、减少代码量:
$(smallhouse的参数 house = { l: 70,1)">house的参数 fish = { l: -160,1)">fish的参数 info = { l: -410,1)">info的参数 var setPst = (x,y){ x = x||win_w/2; y = y||win_h/2; $.each( picArray,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是为了保证窗口缩放时还能在相对位置 } temp_p_t }); } }) } 初始化获取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",1)">屏幕缩放时重新初始化数据 $("body,1)">(e){ setPst(e.pageX,e.pageY); }) })
最后还是为大家提供本案例的Demo,请到GitHub上下载:https://github.com/VaJoy/BlogDemo/tree/master/140809
祝周末愉快,共勉~
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。