js學習總結----彈性勢能動畫之拋物線運動

来源:http://www.cnblogs.com/diasa-fly/archive/2017/07/27/7244638.html
-Advertisement-
Play Games

拋物線運動就是:當拖拽結束的時候,我們讓當前的元素同時水平運動+垂直運動 在同樣的移動距離下,我們滑鼠移動的速度快,move方法觸發的次數少,相反移動的速度慢,move方法觸發的次數就多->瀏覽器對於每一次的move行為的觸發都是由一個最小時間的 通過觀察,我們發現一個事情:水平方向我們盒子在結束拖 ...


拋物線運動就是:當拖拽結束的時候,我們讓當前的元素同時水平運動+垂直運動

在同樣的移動距離下,我們滑鼠移動的速度快,move方法觸發的次數少,相反移動的速度慢,move方法觸發的次數就多->瀏覽器對於每一次的move行為的觸發都是由一個最小時間的

通過觀察,我們發現一個事情:水平方向我們盒子在結束拖拽的時候移動的速度和移動的距離沒有必然的聯繫,和開始拖拽的速度也沒有必然的聯繫,只和最後一次即將鬆開的那一瞬間滑鼠的速度是有關係的,最後瞬間滑鼠如果移動的快,我們水平運動的距離和速度也是比較大的。->獲取滑鼠最後一次即將鬆開時候的速度。

在JS盒子模型中,offsetLeft是獲取當前元素的左偏移,獲取到的值永遠不會出現小數,  他會把真實的left值按照小數點的四捨五入進行計算

具體代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        html,body{
            width:100%;
            height:100%;
        }
        #box{
            position:absolute;
            top:50%;
            left:50%;
            width:200px;
            height:200px;
            background:#ff6600;
            margin:-100px 0 0 -100px;
            cursor:move;
            /*
                不知道寬高的情況下的居中
            position:absolute;
            top:0;
            left:0;
            right:0;
            bottom:0;
            margin:auto;
            */    
        }
    </style>
</head>
<body>
    <div id='box'>
        
    </div>
    <script>
        //JS實現讓當前的元素在屏幕居中的位置
        var box = document.getElementById('box');
        // box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight)-box.offsetHeight)/2 + "px";

        // box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 + "px";
        //拖拽的原理
        /*
            當滑鼠在盒子上按下的時候,我們開始拖拽(給盒子綁定onmousemove和onmouseup),當滑鼠移動的時候,我們計算盒子的最新位置
            當滑鼠抬起的時候說明拖拽結束了,我們的move和up就沒用了,我們再把這兩個方法移除
        */
        box.onmousedown = down;
        function down(e){
            e = e || window.event;
            //記錄開始位置的信息
            this["strX"] = e.clientX;
            this["strY"] = e.clientY;
            this["strL"] = parseFloat(this.style.left);
            this["strT"] = parseFloat(this.style.top);
            //給元素綁定移動和抬起的事件
            if(this.setCapture){
                this.setCapture()//把當前的滑鼠和this綁定在一起
                this.onmousemove = move;
                this.onmouseup= up;
            }else{
                var _this = this;
                document.onmousemove = function(e){
                    // move(e)//這個裡面的this是window
                    move.call(_this,e);
                }
                    ;
                document.onmouseup= function(e){
                    up.call(_this,e);
                };
            }
            //當盒子運動中我們想要執行下一次拖拽,我們按下滑鼠,但是由於盒子還是運動著呢,導致滑鼠抓不住盒子->在按下的同時我們應該停止盒子的運動
            window.clearInterval(this.flyTimer);
            window.clearInterval(this.dropTimer);
            
        }
        function move(e){
            e = e || window.event;
            var curL = (e.clientX-this["strX"])+this["strL"];
            var curT = (e.clientY-this["strY"])+this["strT"];
            //邊界判斷
            var minL = 0,minT = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth,maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight;
            curL = curL < minL ? minL :(curL > maxL ? maxL : curL);
            curT = curT < minT ? minT :(curT > maxT ? maxT : curT)
            this.style.left = curL + "px";
            this.style.top = curT + "px";

            //計算我們水平方向移動的速度
            /*
                在瀏覽器最小反應時間內觸發一次move,我們都記錄一下當前盒子的位置,讓當前的位置-上一次記錄的位置=當前最後一次的偏移
            */
            if(!this.pre){
                this.pre = this.offsetLeft;
            }else{
                this.speedFly = this.offsetLeft - this.pre;
                this.pre = this.offsetLeft;
            }
        }
        function up(e){
            if(this.releaseCapture){
                this.releaseCapture();//把當前的滑鼠和盒子解除綁定
                this.onmousemove = null;
                this.onmouseup= null;
            }else{
                document.onmousemove = null;
                document.onmouseup= null;
                //這樣綁定的話,move和up綁定的this都是document
            }
            //當滑鼠離開結束拖拽的時候,我們開始進行水平方向的動畫運動
            fly.call(this);
            //當滑鼠離開結束拖拽的時候,我們開始進行垂直方向的動畫運動
            drop.call(this);
            
        }
        //當滑鼠移動過快的時候,我們的滑鼠會脫離盒子,導致盒子的mousemove和mouseup事件都移除不到->"滑鼠焦點丟失"
        //在IE和火狐瀏覽器中,我們用一個方法把盒子和滑鼠綁定在一起即可。
        //滑鼠再快也跑不出去文檔:我們把mousemove和mouseup綁定給document
        
        
        function fly(){
            //this->當前要操作的盒子
            var _this = this;
            _this.flyTimer = window.setInterval(function(){
                //我們運動的速度是一直在減慢的,一直到停止("指數衰減運動")
                //this->window
                //盒子停止運動,清除定時器:利用offsetLeft獲取的值不會出現小數,對小數部分進行了四捨五入,所以我們加上或者減去一個小於0.5的速度值,其實對於盒子本身的位置並沒有發生實質的改變,我們認為此階段的盒子就停止運動了。

                if(Math.abs(_this.speedFly)<0.5){
                    window.clearInterval(_this.flyTimer);
                    return;
                }
                _this.speedFly*=0.98;
                var curL = _this.offsetLeft + _this.speedFly;
                var minL = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - _this.offsetWidth;
                if(curL>=maxL){
                    _this.style.left = maxL + "px";
                    _this.speedFly*=-1;
                }else if(curL<=minL){
                    _this.style.left = minL + "px";
                    _this.speedFly*=-1;
                }else{
                    _this.style.left = curL;
                }
            },10)
            

        }

        function drop(){
            var _this = this;
            _this.dragFlag = 0;
            _this.dropTimer = window.setInterval(function(){
                if(_this.dragFlag>1){//到底的時候dragFlag就大於1了
                    window.clearInterval(_this.dropTimer);
                    return;
                }
                _this.dropSpeed = !_this.dropSpeed ? 9.8 : _this.dropSpeed + 9.8;
                //衰減
                _this.dropSpeed*=0.98;
                var curT = _this.offsetTop + _this.dropSpeed;
                var maxT = (document.documentElement.clientHeight || document.body.clientHeight) - _this.offsetHeight;
                if(curT >= maxT){// 到底了
                    _this.style.top = maxT + "px";
                    _this.dropSpeed*=-1;
                    _this.dragFlag++;
                }else{
                    _this.style.top = curT + "px";
                    _this.dragFlag = 0;
                }
            })
            
        }
    </script>
</body>
</html>

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • datepicker插件預設為英文,而且格式為:mm/dd/yyyy這種情況,看起來不怎麼直觀。 修改目標: 1、預設顯示為中文 2、格式為:yyyy年mm月dd日 需要修改兩個地方: 1、更改datas對象, 增加zh-cn語言選項;參見源代碼的1419行 2、修改預設參數,即defaults對象 ...
  • " class="easyui-form" data-options="required:true,novalidate:true"> //提交的時候 function sumbformm(t) { var hisform = $(t).parents("form").eq(0); hisform.... ...
  • push():在數組後面加入元素,並返回數組的長度; unshift():在數組前面就如元素,並返回數組的長度; pop():刪除最後一個元素; var arr =[1,2,3,4,5] ; arr.push(6,7,8); console.log(arr);// push:在數組後面加入元素 結果 ...
  • http-equiv="X-UA-Compatible" 這是一個文檔相容模式的定義 Edge模式告訴IE以最高級 模式渲染文檔,也就是任何IE版本都以當前版本所支持的最高級標準模式渲染,避免版本升級造成的影響。 之前在開發項目的過程中,遇到過因為IE版本產生的相容問題。自己寫完項目在各個瀏覽器檢查 ...
  • 我以前一直以為只能用jquery的data()來獲取 哈哈 是我太弱了 直接用dataset就可以獲取到DOM元素的data屬性 好吧,還可以 用js的獲取屬性的方法getAttribute() ...
  • 1、父級div定義偽類:after和zoom 原理:IE8以上和非IE瀏覽器才支持:after,原理和方法2有點類似,zoom(IE轉有屬性)可解決ie6,ie7浮動問題 優點:瀏覽器支持好,不容易出現怪問題(目前:大型網站都有使用,如:騰迅,網易,新浪等等) 缺點:代碼多,不少初學者不理解原理,要 ...
  • 前言:一直想著整理一下關於前端的知識體系和資料,工作忙了些,擠擠總會有的,資料很多,就看你能不能耐下心堅持去學了,要多學多敲多想,祝你進步~學習之前首先要大概瞭解什麼是HTML ,CSS , JS:一句話概括:HTML 是骨骼, CSS是皮膚, JS只是夾在中間的神經組織!細說的話:HTML是由多種 ...
  • 首先我來介紹一下我遇到的問題 1.當有一個table表包含了<tr>標簽,<td>標簽,大致可以認為是這樣的: <tr> <td> @scene.ID </td> <td> @scene.SceneName </td> <td> @scene.QRUrl </td> <td> @scene.Loca ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...