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 相关文章推荐
javascript学习笔记(三)显示当时时间的代码
Apr 08 Javascript
javascript的console.log()用法小结
May 31 Javascript
node.js中的fs.unlinkSync方法使用说明
Dec 15 Javascript
JavaScript对数字的判断与处理实例分析
Feb 02 Javascript
javascript计时器详解
Feb 28 Javascript
JavaScript截断字符串的方法
Jul 15 Javascript
jQuery基础的工厂函数以及定时器的经典实例分析
May 20 Javascript
jQuery EasyUI Tab 选项卡问题小结
Aug 16 Javascript
weex slider实现滑动底部导航功能
Aug 28 Javascript
Vue 创建组件的两种方法小结(必看)
Feb 23 Javascript
vue模仿网易云音乐的单页面应用
Apr 24 Javascript
jQuery实现鼠标滑动切换图片
May 27 jQuery
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添加Xdebug扩展的方法
2014/02/12 PHP
PHP的error_reporting错误级别变量对照表
2014/07/08 PHP
PHP实现中文圆形印章特效
2015/06/19 PHP
PHP JWT初识及其简单示例
2018/10/10 PHP
PHP错误提示It is not safe to rely on the system……的解决方法
2019/03/25 PHP
js面向对象设计用{}好还是function(){}好(构造函数)
2011/10/23 Javascript
jQuery 网易相册鼠标移动显示隐藏效果实现代码
2013/03/31 Javascript
javascript中parseInt()函数的定义和用法分析
2014/12/20 Javascript
javascript 动态创建表格
2015/01/08 Javascript
JavaScript实现删除,移动和复制文件的方法
2015/08/05 Javascript
极易被忽视的javascript面试题七问七答
2016/02/15 Javascript
JavaScript实现复制内容到粘贴板代码
2016/03/31 Javascript
Bootstrap开发实战之响应式轮播图
2016/06/02 Javascript
javascript验证手机号和实现星号(*)代替实例
2016/08/16 Javascript
详解js中Json的语法与格式
2016/11/22 Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
2017/06/04 Javascript
js实现动态改变radio状态的方法
2018/02/28 Javascript
JavaScript常见事件对象与操作实例总结
2019/01/05 Javascript
在 Vue.js中优雅地使用全局事件的方法
2019/02/01 Javascript
浅谈vue的第一个commit分析
2020/06/08 Javascript
python ip正则式
2009/05/07 Python
python绘图方法实例入门
2015/05/19 Python
Python采用Django开发自己的博客系统
2020/09/29 Python
python将一个英文语句以单词为单位逆序排放的方法
2018/12/20 Python
python logging添加filter教程
2019/12/24 Python
Python标准库itertools的使用方法
2020/01/17 Python
详解HTML5中垂直上下居中的解决方案
2017/12/20 HTML / CSS
Boden澳大利亚官网:英国在线服装公司
2018/08/05 全球购物
土木工程建筑专业毕业生求职信
2013/10/21 职场文书
《恐龙》教学反思
2014/04/27 职场文书
端午节演讲稿
2014/05/23 职场文书
房地产经营管理专业自荐信
2014/09/02 职场文书
初中差生评语
2014/12/29 职场文书
前台接待岗位职责
2015/02/03 职场文书
2015企业年终工作总结范文
2015/05/27 职场文书
正确的理解和使用Django信号(Signals)
2021/04/14 Python