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 相关文章推荐
对联广告js flash激活
Oct 19 Javascript
js 走马灯简单实例
Nov 21 Javascript
用jquery的方法制作一个简单的导航栏
Jun 23 Javascript
基于jQuery实现网页打印功能
Dec 01 Javascript
AngularJS基础 ng-readonly 指令简单示例
Aug 02 Javascript
JS实现自动阅读单词(有道单词本添加功能)
Nov 14 Javascript
Javascript中 带名 匿名 箭头函数的重要区别(推荐)
Jan 29 Javascript
jQuery加密密码到cookie的实现代码
Apr 18 jQuery
vue 2.1.3 实时显示当前时间,每秒更新的方法
Sep 16 Javascript
使用koa2创建web项目的方法步骤
Mar 12 Javascript
layer.js之回调销毁对话框的例子
Sep 11 Javascript
JS pushlet XMLAdapter适配器用法案例解析
Oct 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实现parent调用父类的构造方法与被覆写的方法
2015/02/11 PHP
php 流程控制switch的简单实例
2016/06/07 PHP
thinkPHP线上自动加载异常与修复方法实例分析
2016/12/01 PHP
PHP通过get方法获得form表单数据方法总结
2018/09/12 PHP
JavaScript 快捷键设置实现代码
2009/03/13 Javascript
Javascript事件实例详解
2013/11/06 Javascript
jquery插件lazyload.js延迟加载图片的使用方法
2014/02/19 Javascript
node.js中的fs.writeSync方法使用说明
2014/12/15 Javascript
JS控制表格实现一条光线流动分割行的方法
2015/03/09 Javascript
JavaScript获得当前网页来源页面(即上一页)的方法
2015/04/03 Javascript
js实现不提交表单获取单选按钮值的方法
2015/08/21 Javascript
Javascript动画效果(1)
2016/10/11 Javascript
JS动态遍历json中所有键值对的方法(不知道属性名的情况)
2016/12/28 Javascript
Vue.js父与子组件之间传参示例
2017/02/28 Javascript
简述ES6新增关键字let与var的区别
2019/08/23 Javascript
基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能
2019/11/12 Javascript
javascript设计模式 ? 适配器模式原理与应用实例分析
2020/04/13 Javascript
解决Antd 里面的select 选择框联动触发的问题
2020/10/24 Javascript
原生js 实现表单验证功能
2021/02/08 Javascript
[43:47]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#2 MVP.Phx VS Fnatic第一局
2016/03/05 DOTA
Python实现二分法算法实例
2015/02/02 Python
Python pickle模块用法实例
2015/04/14 Python
python中pylint使用方法(pylint代码检查)
2018/04/06 Python
djang常用查询SQL语句的使用代码
2019/02/15 Python
Python生成一个迭代器的实操方法
2019/06/18 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
TensorFlow中如何确定张量的形状实例
2020/06/23 Python
如何在 Matplotlib 中更改绘图背景的实现
2020/11/26 Python
Lookfantastic日本官网:英国知名护肤、化妆品和头发护理购物网站
2018/04/21 全球购物
如何写出好的Java代码
2014/04/25 面试题
策划助理岗位职责
2013/11/18 职场文书
教师演讲稿大全
2014/05/16 职场文书
学校学雷锋活动总结
2014/06/26 职场文书
护理学院专科毕业生求职信
2014/06/28 职场文书
优秀党员事迹材料
2014/12/18 职场文书
MySql如何将查询的出来的字段进行转换
2022/06/14 MySQL