扒皮下GitHub 404的图片层次轴动特效

今天要克隆的前端特效非常有意思,可以参见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结束-->
>
View Code

接着写脚本前先分析一下,如何做到让鼠标在屏幕上的位置,可以映射为图片在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);
  })

})
View Code

最后还是为大家提供本案例的Demo,请到GitHub上下载:https://github.com/VaJoy/BlogDemo/tree/master/140809
祝周末愉快,共勉~

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1.第一步 设置响应头 header(&#39;Access-Control-Allow-Origin:*&#39;); //支持全域名访问,不安全,部署后需要固定限制为客户端网址 header(&#39;Access-Control-Allow-Methods:POST,GET,OPTIONS,D
$.inArray()方法介绍 $.inArray()函数用于在数组中搜索指定的值,并返回其索引值。如果数组中不存在该值,则返回-1; $.inArray(value,array) --value是要查找的值,array是被查找的数组。 有如下实例: &lt;!DOCTYPE html&gt; &l
jquery.serializejson.min.js的妙用 关于这个jquery.serializejson.min.js插件来看,他是转json的一个非常简单好用的插件。 前端在处理含有大量数据提交的表单时,除了使用Form直接提交刷新页面之外,经常碰到的需求是收集表单信息成数据对象,Ajax提
JS 将form表单数据快速转化为object对象(json对象) jaymou 于 2020-03-03 11:11:05 发布 3534 收藏 3 分类专栏: 前端 文章标签: javascript jquery 版权 前端 专栏收录该内容 5 篇文章0 订阅 订阅专栏 直接上代码 /** *
jQuery的区别:$().click()和$(document).on(&#39;click&#39;,&#39;要选择的元素&#39;,function(){})的不同 文章地址:https://www.cnblogs.com/sqh17/p/7746418.html 解决:动态创建的元素的事件
jQuery插件之jquery.spinner数字智能增减插件 参考地址:http://www.helloweba.com/view-blog-282.html 左右加减数字 像京东提交订单时目前使用的是左右加减数字的效果,这个效果直接明了,操作简单。我们使用jquery.spinner.js插件实
layui标签或一般标签均可&lt;div class=&quot;layui-form-item&quot;&gt; &lt;label class=&quot;layui-form-label&quot;&gt;异地仓名称&lt;/label&gt; &lt;div class=&quot;la
网上对于select option 动态添加修改如下, $(&quot;#selectId&quot;).append(&quot;&lt;option value=&#39;&quot;+value+&quot;&#39;&gt;&quot;+text+&quot;&lt;/option&gt;&
jQuery中的 $.extend() 和 $.fn.extend() ANGWH 于 2020-05-24 06:39:59 发布 注意:$.extend是为jQuery类添加添加类方法,用$.调用(类似$.ajax),$.fn.extend则是为jQuery对象添加方法(实例方法),用DOM元素
jquery 循环数组输出显示在html页面 jquery 没有双向数据绑定,但是很多需求确实需要我们从后台接收到数组或者对象循环显示在前台页面上,这时我们可以用字符串拼接,元素添加的方法去实现 js部分如下: 复制代码 $(function(){ var a=[&quot;1aa&quot;,&q
javascript事件委托理解,jQuery .on()方法一步到位实现事件委托 Javascript-概念原理 专栏收录该内容 10 篇文章0 订阅 订阅专栏 本篇文章借鉴自:博客园文章,只为自己巩固下事件委托方面的知识 概述: 什么叫事件委托?他还有一个名字叫做事件代理,(时间代理 事件委托,
JQuery-$.when().done().fail()的使用 原文引用于&#160;Echoo华地于&#160;2022-01-06 14:07:10 发布 jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本。 每个版本都会引入一些新功能。今天我想介绍的,就是从jQuery 1
jQuery tableExport导出 excel 上篇写的是jQuery&#160;导出word,就试试导出excel。看见网上写的很乱,我这就把我写的整理下来,有部分来自网上capy 1. js文件的引用 &lt;script type=&quot;text/javascript&quot;
jQuery的遍历-prev()和next()方法 &lt;div class=&quot;box&quot; id=&quot;box&quot;&gt; &lt;a href=&#39;#&#39; class=&quot;a&quot;&gt; &lt;input type=&quot;tex
attr()和addClass()的区别 方法 addClass() attr()用途&#x9;追加样式&#x9;设置样式对同一个网页元素操作&#x9;&lt;p&gt;test&lt;/p&gt;第1次使用方法&#x9;$(&quot;p&quot;).addClass(&quot;high&quot;);&#x9;$(&quot;p&
前端——函数(匿名函数、自执行函数) FreshLemon_ 于 2019-06-11 17:11:49 发布 函数声明:function box(){} 函数表达式:var box = function(){}; 匿名函数:function(){} (属于函数表达式) 1声明了一个函数: var
js: 获取标签元素data-*属性值的方法 彭世瑜 于 2022-05-23 09:59:50 发布 2165 收藏 1 文章标签: javascript 前端 jquery 版权 标签上有两个属性data-id 和 data-user-name, 需要通过js去获取 &lt;style&gt;
JavaScript函数详解:匿名函数、具名函数、函数传参、不定参、返回值、JS预解析机制 1.具名函数 定义: 调用: 方式1:方法名(); 可以多次调用 方式2:在事件中调用,直接写函数名,不需用括号 2.匿名函数 没有名字的函数 匿名函数在使用时只有两种情况: 1.匿名函数自执行:声明后不需要
如何等待ajax完成再执行相应操作 ajax广泛应用于异步请求,对于大多数业务来说,这是十分方便的,但对于一些特殊的业务,ajax的异步性会起到相反的作用。 例如在ajax请求成功后,后续的操作需要依赖ajax执行成功后的相应操作。 // 声明一个表示状态的全局变量 status var statu
一步一步教你写一个jQuery的插件教程(Plugin) 更新时间:2009年09月03日 02:10:54 作者: 我将会在下面的例子中一个一个的说明上面这几个条件,做完这些事情后我们就会创建一个高亮显示text的简单插件。 jQuery 的plugin开发需要注意的事情, 1. 明确jQuery