js实现的牛顿摆效果


Posted in Javascript onMarch 31, 2015

牛顿摆是一个1960年代发明的桌面演示装置,五个质量相同的球体由吊绳固定,彼此紧密排列。又叫:牛顿摆球、动量守恒摆球、永动球、物理撞球、碰碰球等。

(function(window,undefined){
  window.None || (window.None = {});
  //重力加速度
  var G=9.8;
  var PI=Math.PI;
  //帧频
  var FPS=48;
 
/*
//IE角度转换
function rorateIt(node,deg){
  //取得末变形前矩形的中点
  var rect = node.getBoundingClientRect(),
  cx1 = (rect.right - rect.left) / 2, // center x
  cy1 = (rect.bottom - rect.top) / 2, // center y
  deg2rad = Math.PI / 180,//角度转弧度
  rad = deg * deg2rad ,
  cos = Math.cos(rad),
  sin = Math.sin(rad);
  var ident = "DXImageTransform.Microsoft.Matrix";
  node.style.filter = "progid:"+ident +"(M11='1.0',sizingmethod='auto expand')";
  //http://www.satzansatz.de/cssd/onhavinglayout.html
  if(!node.currentStyle.hasLayout){//在IE7中,如果没有获得hasLayout,滤镜会失效
   node.style.writingMode = "tb-rl";
  }  
  var filter = node.filters.item(ident);
  // +-------+-------+
  // | M11 | M12 |
  // +-------+-------+
  // | M21 | M22 |
  // +-------+-------+
  filter.M11 = cos;     
  filter.M12 = -sin;     
  filter.M21 = sin;      
  filter.M22 = cos;     
  //取得当前中心
  rect = node.getBoundingClientRect();
  var cx = (rect.right - rect.left) / 2;
  var cy = (rect.bottom - rect.top) / 2;
  //调整此元素的坐标系,实现CSS3 transform-origin的功能
  node.style.marginLeft = cx1 - cx + "px";
  node.style.marginTop = cy1 - cy + "px";
}
 
 
  */
  //外部函数引用
  //是否IE
  function isIE(){
    return navigator.userAgent.indexOf("MSIE")>-1;
  }
  //获取当前样式
  function returnStyle(obj,styleName){ 
    var myObj = typeof obj == "string" ? document.getElementById(obj) : obj; 
    if(document.all){ 
      return eval("myObj.currentStyle." + styleName); 
    } else { 
      return eval("document.defaultView.getComputedStyle(myObj,null)." + styleName); 
    } 
  } 
  //外部函数引用
  //图片方法
  var img=function(src){
    var img=new Image();
    img.src=src;
    return img;
  }
  //方向类,以垂直向下为0度逆时针为正
  var face=function(deg,rad){
    //0-360
    this.unit='deg';
    if(rad)deg=180/PI*deg;
    this.deg=deg;
    this.rad=PI/180*this.deg;
  }
  //矢量类
  var vector=function(size,fx){
    var cstrct=this.constructor;
    this.size=size;
    this.face=fx||new face(0);
    fx=this.face;
    this.toHv=function(){
      var h=new cstrct(Math.sin(fx.rad)*size,90);
      var v=new cstrct(Math.cos(fx.rad)*size,0);
      return [h,v];    
    }
  }
  //继承,obj:需要从矢量继承的对象,arg:arguments
  vector.extend=function(obj,arg){
    vector.apply(obj,arg);
  }
  //矢量合并方法
  vector.merger=function(arrvector){
    if(arguments.length>1)arrvector=arguments;
    var cstrct=arrvector[0].constructor;
    var i=0,ilav=arrvector.length;
    var sum=[0,0];
    for(;i<ilav;i++){
      var hv=arrvector[i].toHv();
      sum[0]+=hv[0].size;
      sum[1]+=hv[1].size;
    }
    var size=Math.sqrt(sum[0]*sum[0]+sum[1]*sum[1]);
    var fa=new face(Math.atan(sum[0]/sum[1]),'rad');
    return new cstrct(size,fa);
  }
  //力类,参数为大小和方向
  var force=function(size,face){
    this.unit='N';
    //继承自矢量
    vector.apply(this,arguments);
  }
  //加速度类
  var a=function(size,face){
    this.unit='m/s^2';
    vector.extend(this,arguments);
  }
  //速度类
  var speed=function(size,face){
    this.unit='m/s';
    vector.extend(this,arguments);
  }
 
  //刚体类,参数(body:IMG对象,m为质量)
  var rigid=function(body,m){
    //一般情况下body为一个img对象,所以暂且只有正方形或长方形两种形式
    this.body=body; 
    this.m=m;      //质量
    this.focus=(this.body instanceof Image)?point(this.body.width/2,this.body.height/2):point(this.body.style.width/2,this.body.style.height/2);
    this.axis=point(0,0);  //轴心位置(point对象)
     
    this.force=new force(0);
    this.a=new a(this.force.size/this.m,this.force.face);
    this.speed=new speed(0);
    //设置,可重新设置上面所有参数
    this.set=function(prop,value){
      this[prop]=value;
    }
    this.addForce=function(f){
      return this.force=vector.merger(f,this.force);
    }
       
    //旋转
    this.rotate=function(face,axis){
      axis=axis||this.axis||this.focus;
      //cx1=returnStyle(this.body,"left");
      //cy1=returnStyle(this.body,"left");
      var rect=this.body.getBoundingClientRect(),
      //cx1=rect.left+axis.x,
      //cy1=rect.top+axis.y,
      cx1 = (rect.right - rect.left) / 2,
      cy1 = (rect.bottom - rect.top) / 2,
      rad=face.rad,
      cos = Math.cos(rad),
      sin = Math.sin(rad);
      if(isIE()){
        var ident = "DXImageTransform.Microsoft.Matrix";
        this.body.style.filter = "progid:"+ident +"(M11='1.0',sizingmethod='auto expand')";
        if(!returnStyle(this.body,"hasLayout")){//在IE7中,如果没有获得hasLayout,滤镜会失效
          this.body.style.writingMode = "tb-rl";
        }  
        var filter = this.body.filters.item(ident);
        filter.M11 = cos;     
        filter.M12 = -sin;     
        filter.M21 = sin;      
        filter.M22 = cos;  
      }
      rect = this.body.getBoundingClientRect();
      //var cx=rect.left+axis.x;
      //var cy=rect.top+axis.y;
      var cx = (rect.right - rect.left) / 2;
      var cy = (rect.bottom - rect.top) / 2;
      //调整此元素的坐标系,实现CSS3 transform-origin的功能
      this.body.style.left=parseInt(this.body.style.left,10) + cx1 - cx + "px";
      this.body.style.top=parseInt(this.body.style.top,10) + cy1 - cy + "px";
      //CSS3
      var sdeg="rotate("+face.deg+"deg)";
      var paxis=axis.x+"px "+axis.y+"px";
      this.body.style.transformOrigin=paxis;
      this.body.style.MozTransformOrigin=paxis;
      this.body.style.WebkitTransformOrigin=paxis;
      this.body.style.OTransformOrigin=paxis;
      this.body.style.WebkitTransform=sdeg;
      this.body.style.MozTransform=sdeg;
      this.body.style.OTransform=sdeg;
      this.body.style.transform=sdeg;
    }
  }
  //刚体组合
  rigid.merger=function(){
     
  }
  //无弹性绳子类
  var rope=function(body,length,maxForce){
    this.body=body;
    this.length=length;
    this.maxForce=maxForce || Infinity || Number.MAX_VALUE;
  }
  //组合体类
  var comb=function(arrObject){
     
  }
  //单摆类
  var pendulum=function(ripe,rigid){
     
  }
   
  //类单摆
  var likePend=function(rigid,fa,time){//刚体,初始角度,摆动频率
    var self=this;
    this.rigid=rigid;
    this.body=this.rigid.body;
    this.axis=this.rigid.axis;
    this.dom=this.rigid.dom;
    this.m=this.rigid.m;
    this.rad=fa?fa.rad:fa=new face(PI/6,'rad');
    //摆动
    //角度30
    var fx=fa.rad;
    //角度平方根
    var m=Math.sqrt(fx);
    //摆动时间1秒
    var atime=time||0.5;
    var fnum=FPS*atime;
    //单位增量
    var fm=m/fnum;
    //i:角度平方根到0
    var i=-m,tid;
    var g=new a(G);
    var t=1000/FPS;
    //o:{s:1,f:30,t:0,fun:callback}  :s:(-1,1)速度增加还是减小,f:从多少度,t:到多少度,fun:摆完后运行的函数
    this.swing=function(o,fun){
/*     var asps=g.size*Math.cos(PI/2-fx)/(24*24*self.m); 
      var fss=new force(asps,new face(fx-PI/2));
      this.rigid.force=fss;
      var a=this.rigid.a;
      //单位时间内速度的增量
      var a1=Math.acos((asps+this.rigid.speed.size)/2)
      this.rigid.speed=new speed(a1,new face(fx-PI/2));
      a2=a1*2;*/
      //{s:-1,inc:1}
      o=o||{s:1};
      var y=-o.s*i*i+fx*o.s;
      if(i>=m){
        self.rigid.rotate(new face(0),self.axis);
        clearTimeout(tid);
        i=-m;
        if(fun)fun();
        return;
      }
      var f=new face(y,'rad');
      self.rigid.rotate(f,axis=self.axis);
      i+=fm;
      tid=setTimeout(function(){self.swing.call(self,o,fun)},t);
    }
     
    this.moveTo=function(p){
      self.body.style.left=p.x+"px";
      self.body.style.top=p.y+"px";
    }
  }
   
  //世界
  None.world=function(param){
    //param:{force:[多个force对象]}
    this.param=param||{};
    this.config={
      //全局外力
      g:new a(G),
      className:'',
      width:'100%',
      height:'100%',
      left:0,
      top:-200,
      arrNav:['about','myWork','site','other','myTools'],
      imgW:60,
      imgN:5,
      sDeg:5,
      hitSound:'sounds/hit.wav',
      vol:0.1
    }
    this.init();
  };
  None.world.prototype={
    //初始化
    dom:{},
    init:function(){
      var c=this.config;
      var p=this.param;
      //dom    
      var dom=document.createElement("div");
      dom.className=c.className;
      dom.style.position="absolute";
      dom.style.width=p.width||c.width;
      dom.style.height=p.height||c.height;
      dom.style.left=(p.left||c.left) +"px";
      dom.style.top=(p.top||c.top) +"px";
      this.dom=dom;
      document.body.appendChild(this.dom);
    },
    //添加一个刚体
    addRigid:function(rigid,p){
      if(!(rigid instanceof Array)){
        rigid=[rigid];
      }
      if(!p)p=[point(0,0)];
      if(!(p instanceof Array))p=[p];
      for(var i=0,rl=rigid.length;i<rl;i++){
        p[i]=p[i] || p[0];
        rigid[i].body.style.position="absolute";
        rigid[i].body.style.left=p[i].x+"px";
        rigid[i].body.style.top=p[i].y+"px";
        this.dom.appendChild(rigid[i].body);
      }
    },
    //添加一个外作用力
    addForce:function(){
       
    },
    start:function(){
      var p=this.param,
      c=this.config;
      var shit=p.hitSound||c.hitSound;
      var sndHit=new None.sounds(shit);
      sndHit.volume=p.vol||c.vol;
      var w=document.documentElement.offsetWidth;
      var imgWidth=p.imgW||c.imgW;//图片宽度
      var imgNum=p.imgN||c.imgN; //图片数量
      var jd=p.sDeg||c.sDeg;   //最大角度
      var es=p.arrNav||c.arrNav;
      var time=p.time||c.time;
       
      var basex=w/2-imgWidth*imgNum/2;
      var jiaodu=new face(jd);
      var rig=[],ball=[],pend=[],axis=point(imgWidth/2,0);
      for(var i=0,el=es.length;i<el;i++){
        rig[i]=document.getElementById(es[i]);
        ball[i]=new rigid(rig[i],1);
        ball[i].set("axis",axis);
        pend[i]=new likePend(ball[i],jiaodu,time);
      }
      this.addRigid(pend);
      resize();
      if(!isIE())swing();
      window.onresize=resize;
       
      function hit(v){
        sndHit.play(); 
      }
      function swing(){
        var runfun=arguments.callee;
        var last=pend.length-1;
        if(p.hitSound)hit(0);
        pend[0].swing({s:1},function(){
          if(p.hitSound)hit(1);
          pend[last].swing({s:-1},runfun);
        });
      }
      function resize(){
        var w=document.documentElement.offsetWidth;
        var basex=w/2-imgWidth*imgNum/2;
        var n=pend.length;
        for(var i=0;i<n;i++){
          pend[i].moveTo(point(basex+imgWidth*i,0)); 
        }
      }  
    }
  };
   
})(window);

以上所述就是本文的全部内容了,希望大家能够喜欢。能够对大家学习javascript有所帮助。

Javascript 相关文章推荐
JQuery 学习笔记 element属性控制
Jul 23 Javascript
基于jquery实现发送文章到手机的代码
Dec 26 Javascript
jquery实现键盘左右翻页特效
Apr 30 Javascript
js实现的四级左侧网站分类菜单实例
May 06 Javascript
js 弹出虚拟键盘修改密码的简单实例
Oct 10 Javascript
BootStrap CSS全局样式和表格样式源码解析
Jan 20 Javascript
jQuery EasyUI 页面加载等待及页面等待层
Feb 06 Javascript
Angular 2父子组件数据传递之局部变量获取子组件其他成员
Jul 04 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
Dec 18 Javascript
koa2+vue实现登陆及登录状态判断
Aug 15 Javascript
如何实现iframe父子传参通信
Feb 05 Javascript
JS数组及对象遍历方法代码汇总
Jun 16 Javascript
JS动态显示表格上下frame的方法
Mar 31 #Javascript
JS实现控制表格只显示行边框或者只显示列边框的方法
Mar 31 #Javascript
jQuery选择器源码解读(八):addCombinator函数
Mar 31 #Javascript
JS显示表格内指定行html代码的方法
Mar 31 #Javascript
jQuery选择器源码解读(七):elementMatcher函数
Mar 31 #Javascript
jQuery选择器源码解读(六):Sizzle选择器匹配逻辑分析
Mar 31 #Javascript
jQuery选择器源码解读(五):tokenize的解析过程
Mar 31 #Javascript
You might like
php数组相加 array(“a”)+array(“b”)结果还是array(“a”)
2012/09/19 PHP
php+mysql查询优化简单实例
2015/01/13 PHP
PHP+JQuery+Ajax实现分页方法详解
2016/08/06 PHP
php-beanstalkd消息队列类实例分享
2017/07/19 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
HR vs CL BO3 第一场 2.13
2021/03/10 DOTA
ASP.NET jQuery 实例18 通过使用jQuery validation插件校验DropDownList
2012/02/03 Javascript
JavaScript避免内存泄露及内存管理技巧
2014/09/05 Javascript
js获取页面传来参数的方法
2014/09/06 Javascript
ionic 上拉菜单(ActionSheet)实例代码
2016/06/06 Javascript
JavaScript中浅讲ajax图文详解
2016/11/11 Javascript
ReactNative页面跳转Navigator实现的示例代码
2017/08/02 Javascript
webpack搭建vue 项目的步骤
2017/12/27 Javascript
Nodejs中crypto模块的安全知识讲解
2018/01/03 NodeJs
Vue弹出菜单功能的实现代码
2018/09/12 Javascript
微信小程序文章详情页跳转案例详解
2019/07/09 Javascript
深入了解Vue动态组件和异步组件
2021/01/26 Vue.js
[48:35]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 TNC vs Optic
2018/04/03 DOTA
测试、预发布后用python检测网页是否有日常链接
2014/06/03 Python
Python使用pylab库实现画线功能的方法详解
2017/06/08 Python
Python实现PS滤镜Fish lens图像扭曲效果示例
2018/01/29 Python
python 遍历目录(包括子目录)下所有文件的实例
2018/07/11 Python
对Python 内建函数和保留字详解
2018/10/15 Python
python pptx复制指定页的ppt教程
2020/02/14 Python
利用python实现汉诺塔游戏
2021/03/01 Python
阿迪达斯丹麦官网:adidas丹麦
2016/10/01 全球购物
最新的互联网创业计划书
2014/01/10 职场文书
软件毕业生个人鉴定
2014/03/03 职场文书
人力资源管理毕业生自荐信
2014/06/26 职场文书
平安工地汇报材料
2014/08/19 职场文书
个人投资合作协议书
2014/10/12 职场文书
出生证明格式
2015/06/15 职场文书
大学社团活动总结怎么写
2019/06/21 职场文书
2019年最新证婚词精选集!
2019/06/28 职场文书
Python使用海龟绘图实现贪吃蛇游戏
2021/06/18 Python
Nginx配置文件详解以及优化建议指南
2021/09/15 Servers