搖一搖撒金幣效果

公司要做個活動蛙卤,然后要做撒金幣效果炒考,網(wǎng)上找了好多資料效果不是很好拂蝎,這個是網(wǎng)上找的一個比較滿意的效果把代碼分享出來穴墅,僅做個人代碼分享。

<!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){
        //默認參數(shù)
        this.defaults={
            coinSrc:"http://ohpg7uygp.bkt.clouddn.com/jinbi.png",     //金幣圖片地址
            audioSrc:"http://ohpg7uygp.bkt.clouddn.com/shake.mp3", //金幣音頻地址
            coinWidth:20,           //金幣寬度
            coinHeight:20,          //金幣高度
            density:30
        };
        this.settings=this._extendDeep(this.defaults,opts);   //深拷貝
        this.density=this.settings.density;                   //密度温自,即金幣個數(shù)
        this.timeLag=1000;                                    //金幣散落的事件間隔玄货,數(shù)字越大表示間隔越大
        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);
                };
            }
        },
        /**
         * 創(chuàng)建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();
            };
        },
        /**
         * 執(zhí)行金幣繪制動畫
         * @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=[];  //存儲金幣下落過程中的一些屬性參數(shù)
            for(var i=0;i<_self.density;i++){
                coinAttrArr[i]={
                    rndX:Math.random(),                                    //存儲金幣開始降落x軸隨機值
                    rndOrder:Math.round(Math.random()*_self.timeLag/17),   //存儲金幣撒落順序的一個數(shù)組
                    time:0,                                                //存儲金幣繪制的具體時間
                    top:0,                                                 //存儲金幣繪制距離頂部的距離
                    left:0,                                                //存儲金幣彈起后距離左邊的距離
                    endSpeed:0,                                            //存儲金幣第一次接觸地面的速度
                    bEnd:false,                                            //存儲金幣是否觸碰到地面
                    reDownSpeed:0,                                         //存儲金幣彈起后重新降落的速度
                    reDownHDelta:Math.random()*100+250,                    //存儲金幣彈起的高度參數(shù),隨機值250~350之間
                    rndOffsetX:Math.random()*0.06+0.97                     //存儲金幣x軸的偏移量悼泌,隨機值0.97~1.03之間
                };
            }
            var startTime =  Date.now();  //開始繪制前的時間
            function draw(){
                var drawStart = Date.now();  //記錄重繪的結(jié)束事件
                var diff = (drawStart - startTime)/1000;  //計算每次重繪所需要的事件松捉,單位為秒
                startTime = drawStart;   //結(jié)束事件傳給開始事件
                _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();
                //根據(jù)金幣個數(shù)循環(huán)繪制金幣
                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以舒,表示已經(jīng)在下落過程中,則每次的初始時間遞增
                        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;
                        }
                        //金幣第一次降落超過地面時卵贱,將其高度設(shè)置和地面齊平
                        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);  //重繪兰绣,遞回調(diào)用繪制方法
                }else{
                    console.log("金幣都撒完了");
                    _self._destory();
                }
            }
            window.requestAnimationFrame(draw);  //第一次繪制
        },
        /**
         * 求最小值
         * @method _minNum
         * @param   {arr}    arr  屬性數(shù)組
                    {string} attr 數(shù)組下的屬性名稱
         * @return  {number}      返回數(shù)組下屬性值最小的值
        **/
        _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  屬性數(shù)組
                    {string} attr 數(shù)組下的屬性名稱
         * @return  {number}      返回數(shù)組下屬性值最大的值
        **/
        _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];
        },
        /**
         * 創(chuàng)建音頻對象
         * @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();
        initClick();
        function initClick(){
            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>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末世分,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缀辩,更是在濱河造成了極大的恐慌臭埋,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臀玄,死亡現(xiàn)場離奇詭異瓢阴,居然都是意外死亡,警方通過查閱死者的電腦和手機健无,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門荣恐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人累贤,你說我怎么就攤上這事叠穆。” “怎么了臼膏?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵痹束,是天一觀的道長。 經(jīng)常有香客問我讶请,道長祷嘶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任夺溢,我火速辦了婚禮论巍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘风响。我一直安慰自己嘉汰,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布状勤。 她就那樣靜靜地躺著鞋怀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪持搜。 梳的紋絲不亂的頭發(fā)上密似,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音葫盼,去河邊找鬼残腌。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抛猫。 我是一名探鬼主播蟆盹,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闺金!你這毒婦竟也來了逾滥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤败匹,失蹤者是張志新(化名)和其女友劉穎寨昙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哎壳,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年尚卫,在試婚紗的時候發(fā)現(xiàn)自己被綠了归榕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吱涉,死狀恐怖刹泄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怎爵,我是刑警寧澤特石,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鳖链,受9級特大地震影響姆蘸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芙委,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一逞敷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧灌侣,春花似錦推捐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痊乾,卻和暖如春皮壁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哪审。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工闪彼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓畏腕,卻偏偏與公主長得像缴川,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子描馅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,152評論 25 707
  • 一年把夸,不長也不短。借著發(fā)達的通訊铭污,無線信號慢慢變成顆顆愛心恋日。我的心沒有浮躁時,遇見需要面對很多很多事情的他嘹狞,我只認...
    有他真好閱讀 189評論 0 1
  • 天空的湛藍 在云的縫隙中掙扎 指尖妄圖撕裂 厚厚的云層 觸摸明亮的柔滑 暮色下 我在星上鐫刻你的身影 抹去天涯
    月影007閱讀 166評論 0 1
  • 1 《聊齋志異 豬婆龍》在青柯亭版是放在第二卷第4篇岂膳。 據(jù)說原稿分八卷,豬婆龍在第一卷的最后磅网,與卷二中第24篇的“...
    覺史氏閱讀 1,750評論 0 0