|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
模仿淘宝移动端撒金币效果
可在手机上摇一摇试试,不过目前手机上金币多的话渲染就会很卡
- <!doctype html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>摇一摇撒金币</title>
- <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui" />
- <style>
- body{margin:0;padding:0;}
- input{position:absolute;z-index:1000}
- canvas{position:absolute;top:0;left:0;}
- </style>
- <script>
- function Coin(opts){
- //默认参数
- this.defaults={
- coinSrc:"http://gw.alicdn.com/tps/i3/TB1QJ5DGpXXXXaBXXXXuv2kGFXX-39-39.png_40x40Q50s150.jpg", //金币图片地址
- audioSrc:"http://download.taobaocdn.com/freedom/26370/media/shake.mp3", //金币音频地址
- coinWidth:20, //金币宽度
- coinHeight:20, //金币高度
- density:30
- };
- this.settings=this._extendDeep(this.defaults,opts); //深拷贝
- this.density=this.settings.density; //密度,即金币个数
- this.timeLag=1000; //金币散落的事件间隔,数字越大表示间隔越大
- this.coinWidth=this.settings.coinWidth; //金币宽度
- this.coinHeight=this.settings.coinHeight; //金币高度
- this.wrapWidth=0;
- this.wrapHeight=0;
- this._init();
- }
- Coin.prototype={
- constructor:Coin,
-
- /**
- * 动画初始化方法
- * @method _init
- **/
- _init:function(){
- //初始化包括尺寸大小
- this.wrapWidth=document.documentElement.clientWidth;
- this.wrapHeight=document.documentElement.clientHeight;
-
- this._requestAnimationFrame();
- this._createCanvas();
- this._createAudio();
-
- },
-
- /**
- * 对象深拷贝方法
- * @method _extendDeep
- * @param {object} parent 父对象
- {object} child 子对象
- @return {object} child 父对象继承给子对象
- **/
- _extendDeep:function(child,parent){
- var i,
- toStr = Object.prototype.toString,
- astr = "[object Array]";
- child = child || {};
- for (i in parent) {
- if (parent.hasOwnProperty(i)) {
- if (typeof parent[i] === "object") {
- child[i] = (toStr.call(parent[i]) === astr) ? [] : {};
- extendDeep(parent[i], child[i]);
- } else {
- child[i] = parent[i];
- }
- }
- }
- return child;
- },
-
- /**
- * requestAnimationFrame做兼容
- * @method _requestAnimationFrame
- **/
- _requestAnimationFrame:function(){
- var lastTime = 0;
- var vendors = ['webkit', 'moz'];
- for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
- window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
- window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // name has changed in Webkit
- window[vendors[x] + 'CancelRequestAnimationFrame'];
- }
-
- if (!window.requestAnimationFrame) {
- window.requestAnimationFrame = function(callback, element) {
- var currTime = new Date().getTime();
- var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
- var id = window.setTimeout(function() {
- callback(currTime + timeToCall);
- }, timeToCall);
- lastTime = currTime + timeToCall;
- return id;
- };
- }
- if (!window.cancelAnimationFrame) {
- window.cancelAnimationFrame = function(id) {
- clearTimeout(id);
- };
- }
- },
-
- /**
- * 创建canvas画布
- * @method _createCanvas
- **/
- _createCanvas:function(){
- var _self=this;
- this.canvas=document.createElement('canvas');
- this.canvas.setAttribute("data-id",Date.now());
- if(!this.canvas.getContext){
- alert("您的浏览器不支持canvas");
- return;
- }
- this.context=this.canvas.getContext('2d');
- this.canvas.width=this.wrapWidth;
- this.canvas.height=this.wrapHeight;
- var oBody=document.getElementsByTagName('body')[0];
- oBody.appendChild(this.canvas);
- this._createCacheCanvas();
- },
-
- _createCacheCanvas:function(){
- var _self=this;
- this.cacheCanvas=document.createElement('canvas');
- this.cacheContext=this.cacheCanvas.getContext('2d');
- this.cacheCanvas.width=this.wrapWidth;
- this.cacheCanvas.height=this.wrapHeight;
- this.coinImg=new Image();
- this.coinImg.src=this.settings.coinSrc;
- this.coinImg.onload=function(){
- _self._startCacheCanvasAnim();
- }
- },
-
-
- /**
- * 执行金币绘制动画
- * @method _startCanvasAnim
- **/
- _startCacheCanvasAnim:function(){
- var _self=this;
- var availWidth=this.cacheCanvas.width-this.coinWidth;
- var availHeight=this.cacheCanvas.height-this.coinHeight;
- //var disX=availWidth/this.density; //每个硬币X轴的间距
- var coinRange=availWidth*this.density/(this.density+15);
- var rangeStart=(availWidth-coinRange)/2;
- var g=9.8*280; //重力加速度
- var bPlayAudio=false;
-
- var coinAttrArr=[]; //存储金币下落过程中的一些属性参数
- for(var i=0;i<_self.density;i++){
- coinAttrArr[i]={
- rndX:Math.random(), //存储金币开始降落x轴随机值
- rndOrder:Math.round(Math.random()*_self.timeLag/17), //存储金币撒落顺序的一个数组
- time:0, //存储金币绘制的具体时间
- top:0, //存储金币绘制距离顶部的距离
- left:0, //存储金币弹起后距离左边的距离
- endSpeed:0, //存储金币第一次接触地面的速度
- bEnd:false, //存储金币是否触碰到地面
- reDownSpeed:0, //存储金币弹起后重新降落的速度
- reDownHDelta:Math.random()*100+250, //存储金币弹起的高度参数,随机值250~350之间
- rndOffsetX:Math.random()*0.06+0.97 //存储金币x轴的偏移量,随机值0.97~1.03之间
- }
- }
-
- var startTime = Date.now(); //开始绘制前的时间
- function draw(){
-
- var drawStart = Date.now(); //记录重绘的结束事件
- var diff = (drawStart - startTime)/1000; //计算每次重绘所需要的事件,单位为秒
- startTime = drawStart; //结束事件传给开始事件
- _self.context.clearRect(0,0,_self.canvas.width,_self.canvas.height); //清除画布,方便重绘
- _self.cacheContext.clearRect(0,0,_self.cacheCanvas.width,_self.cacheCanvas.height); //清除画布,方便重绘
- _self.cacheContext.save();
-
- //根据金币个数循环绘制金币
- for(var i=0;i<_self.density;i++){
- if((coinAttrArr[i].rndOrder==0&&coinAttrArr[i].time==0)){ //如果顺序为0,表示开始下落,同时下落的初始时间为0时,赋值初始时间
- coinAttrArr[i].time=diff;
- }
- if(coinAttrArr[i].time>0){ //如果初始事件大于0,表示已经在下落过程中,则每次的初始时间递增
- coinAttrArr[i].time=coinAttrArr[i].time+diff;
- }
- if(coinAttrArr[i].rndOrder==0){ //如果顺序为0,开始下落,则开始绘制金币
- if(!coinAttrArr[i].bEnd){ //金币下落(过程一),自由落体运动
- coinAttrArr[i].top=g*Math.pow(coinAttrArr[i].time,2)/2-_self.coinHeight; //自由落体加速度运动,求下落的高度
- //coinAttrArr[i].left=disX*coinAttrArr[i].rndX+i*disX;
- coinAttrArr[i].left=coinRange*coinAttrArr[i].rndX+rangeStart;
- }else if(coinAttrArr[i].endSpeed==0){ //金币弹起后在空中重新下落(过程三)
- coinAttrArr[i].reDownSpeed=coinAttrArr[i].reDownSpeed*1.1;
- coinAttrArr[i].top=coinAttrArr[i].top+coinAttrArr[i].reDownSpeed;
- coinAttrArr[i].left=coinAttrArr[i].left*coinAttrArr[i].rndOffsetX;
- }else{ //金币弹起(过程二)
- coinAttrArr[i].endSpeed=-Math.abs(coinAttrArr[i].endSpeed*0.96);
- if(Math.abs(coinAttrArr[i].endSpeed)<1) coinAttrArr[i].endSpeed=0;
- coinAttrArr[i].top=coinAttrArr[i].top+coinAttrArr[i].endSpeed;
- coinAttrArr[i].left=coinAttrArr[i].left*coinAttrArr[i].rndOffsetX;
- }
-
- //金币第一次降落超过地面时,将其高度设置和地面齐平
- if(coinAttrArr[i].top>_self.cacheCanvas.height-_self.coinHeight&&!coinAttrArr[i].bEnd){
- coinAttrArr[i].top=_self.cacheCanvas.height-_self.coinHeight;
- }
-
- //金币落地时,计算落地的速度
- if(coinAttrArr[i].top==_self.cacheCanvas.height-_self.coinHeight){
- coinAttrArr[i].endSpeed=g*coinAttrArr[i].time/coinAttrArr[i].reDownHDelta;
- coinAttrArr[i].reDownSpeed=coinAttrArr[i].endSpeed/10;
- coinAttrArr[i].bEnd=true;
- }
-
- //绘制金币
- _self.cacheContext.drawImage(_self.coinImg,coinAttrArr[i].left,coinAttrArr[i].top,_self.coinWidth,_self.coinHeight);
- }
- coinAttrArr[i].rndOrder=coinAttrArr[i].rndOrder==0?0:coinAttrArr[i].rndOrder-1;//顺序每一次重绘则递减一次,直到为0时,代表开始下落
- }
- _self.cacheContext.restore();
-
- _self.context.drawImage(_self.cacheCanvas,0,0,_self.canvas.width,_self.canvas.height);
-
- var firstH=_self._maxNum(coinAttrArr,"top");//求降落过程中高度最大的金币高度
- if(firstH>=_self.cacheCanvas.height-_self.coinHeight&&!bPlayAudio){
- _self._playAudio();
- bPlayAudio=true;
- }
-
- var lastH=_self._minNum(coinAttrArr,"top");//求降落过程中高度最小的金币高度
- if(lastH<=_self.cacheCanvas.height+_self.coinHeight){ //最后一个金币高度超出canvas的高度停止重绘
- window.requestAnimationFrame(draw); //重绘,递回调用绘制方法
- }else{
- console.log("金币都撒完了");
- _self._destory();
- }
-
-
- }
-
- window.requestAnimationFrame(draw); //第一次绘制
- },
-
-
- /**
- * 求最小值
- * @method _minNum
- * @param {arr} arr 属性数组
- {string} attr 数组下的属性名称
- * @return {number} 返回数组下属性值最小的值
- **/
- _minNum:function(arr,attr){
- var tempArr=[];
- for(var i=0;i<arr.length;i++){
- tempArr.push(arr[i][attr]);
- }
- return tempArr.sort(function(a,b){return a-b})[0];
- },
-
- /**
- * 求最大值
- * @method _minNum
- * @param {arr} arr 属性数组
- {string} attr 数组下的属性名称
- * @return {number} 返回数组下属性值最大的值
- **/
- _maxNum:function(arr,attr){
- var tempArr=[];
- for(var i=0;i<arr.length;i++){
- tempArr.push(arr[i][attr]);
- }
- return tempArr.sort(function(a,b){return b-a})[0];
- },
-
- /**
- * 创建音频对象
- * @method _createAudio
- **/
- _createAudio:function(){
- this.audio=document.createElement('audio');
- this.audio.setAttribute("preload","load");
- var oSource=document.createElement('source');
- oSource.setAttribute("src",this.settings.audioSrc);
- oSource.setAttribute("type","audio/mp3");
- this.audio.appendChild(oSource);
- var oBody=document.getElementsByTagName('body')[0];
- oBody.appendChild(this.audio);
- },
-
- /**
- * 播放音频
- * @method _playAudio
- **/
- _playAudio:function(){
- this.audio.play();
- },
-
- /**
- * 销毁canvas和audio
- * @method _destory
- **/
- _destory:function(){
- var oBody=document.getElementsByTagName('body')[0];
- oBody.removeChild(this.canvas);
- oBody.removeChild(this.audio);
- }
- }
- </script>
- <script>
- window.onload=function(){
- var oBtn=document.getElementById('btn1');
- init();
- oBtn.onclick=function(){
- var coin=new Coin();
- }
-
- var SHAKE_THRESHOLD = 400;
- var last_update = 0;
- var index=0;
- var x = y = z = last_x = last_y = last_z = 0;
- var w_curTime=0;
- function init() {
- if (window.DeviceMotionEvent) {
- window.addEventListener('devicemotion', deviceMotionHandler, false);
- } else {
- alert('not support mobile event');
- }
- }
- function deviceMotionHandler(eventData) {
- var acceleration = eventData.accelerationIncludingGravity;
- var curTime = new Date().getTime();
- if ((curTime - last_update) > 100) {
- var diffTime = curTime - last_update;
- last_update = curTime;
- x = acceleration.x;
- y = acceleration.y;
- z = acceleration.z;
- var speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;
- var delta=Math.abs(x + y + z - last_x - last_y - last_z);
-
- if (speed > SHAKE_THRESHOLD) {
- if((curTime-w_curTime)>2000){
- w_curTime!=0 && new Coin({density:Math.round(delta)});
- w_curTime=curTime;
- }
- }
- last_x = x;
- last_y = y;
- last_z = z;
- }
- }
-
- }
- </script>
- </head>
- <body>
- <input type="button" value="撒金币" id="btn1" />
- </body>
- </html>
复制代码
仿手机支付宝撒金币.zip
(36.9 KB, 下载次数: 540)
|
|