深入理解BOM系列第三篇——定時器應用(時鐘、倒計時、秒錶和鬧鐘)

来源:http://www.cnblogs.com/xiaohuochai/archive/2016/08/17/5777757.html
-Advertisement-
Play Games

× 目錄 [1]時鐘 [2]倒計時 [3]秒錶[4]鬧鐘 前面的話 本文屬於定時器的應用部分,分別用於實現與時間相關的四個應用,包括時鐘、倒計時、秒錶和鬧鐘。與時間相關需要用到時間和日期對象Date,詳細情況移步至此 時鐘 最簡單的時鐘製作辦法是通過正則表達式的exec()方法,將時間對象的字元串中 ...


×
目錄
[1]時鐘 [2]倒計時 [3]秒錶[4]鬧鐘

前面的話

  本文屬於定時器的應用部分,分別用於實現與時間相關的四個應用,包括時鐘、倒計時、秒錶和鬧鐘。與時間相關需要用到時間和日期對象Date,詳細情況移步至此

 

時鐘

  最簡單的時鐘製作辦法是通過正則表達式exec()方法,將時間對象的字元串中的時間部分截取出來,使用定時器刷新即可

<div id="myDiv"></div>
<script>
myDiv.innerHTML = /\d\d:\d\d:\d\d/.exec(new Date().toString())[0];
setInterval(function(){
    myDiv.innerHTML = /\d\d:\d\d:\d\d/.exec(new Date().toString())[0];    
},500);
</script>

 

倒計時

【1】簡易倒計時

  簡易倒計時就是每1s通過setInterval將設置的時間減去1來達到要求

<div id="myDiv">
    <label for="set"><input type="number" id="set" step="1" value="0">秒</label>
    <button id="btn">確定</button>
    <button id="reset">重置</button>    
</div>
<script>
var timer;
reset.onclick = function(){
    history.go();
}
btn.onclick = function(){
    if(timer) return;
    set.setAttribute('disabled','disabled');
    timer = setInterval(function(){
        if(Number(set.value) === 0){
            clearInterval(timer);
            timer = 0;
            set.removeAttribute('disabled');
            return;
        }
        set.value = Number(set.value) - 1;
    },1000);
}    
</script>

【2】精確倒計時

  由定時器的運行機制,我們知道每間隔1000ms去改變時間的作法並不可靠。更精確地做法,應該是與系統的運行時間作為參照,倒計時的時間變化與系統的時間變化同步,達到精確倒計時的效果 

  [註意]此部分中,需要通過取模運算除法運算進行時、分、秒的計算,詳細情況移步至此

<div id="myDiv">
    <label for="hour"><input type="number" id="hour" min="0" max="23" step="1" value="0" />時</label>
    <label for="minute"><input type="number" id="minute" min="0" max="59" step="1" value="0" />分</label>
    <label for="second"><input type="number" id="second" min="0" max="23" step="1" value="0" />秒</label>
    <button id="btn">確定</button>
    <button id="reset">重置</button>
</div>
<script>
var timer;
//輸入限制
hour.onchange = function(){
    if(Number(this.value) !== Number(this.value)) this.value = 0;
    if(this.value > 23) this.value = 23;
    if(this.value < 0) this.value = 0;
}
second.onchange = minute.onchange = function(){
    if(Number(this.value) !== Number(this.value)) this.value = 0;
    if(this.value > 59) this.value = 59;
    if(this.value < 0) this.value = 0;
}
reset.onclick = function(){
    history.go();
}
btn.onclick = function(){
    if(timer) return;
    for(var i = 0; i < 3; i++){
        myDiv.getElementsByTagName('input')[i].setAttribute('disabled','disabled');
    }
    //原始儲存值
    var setOri = hour.value*3600 + minute.value*60 + second.value*1;
    //原始系統時間值
    var timeOri = (new Date()).getTime();
    //現在所剩時間值
    var setNow;
    cancelAnimationFrame(timer);
    timer = requestAnimationFrame(function fn(){
        //當前系統時間值
        var timeNow = (new Date()).getTime();
        //使系統時間的差值與設置時間的差值相等,來獲得正常的時間變化
        setNow = setOri - Math.floor((timeNow - timeOri)/1000);
        hour.value = Math.floor((setNow%86400)/3600);
        minute.value = Math.floor((setNow%3600)/60);
        second.value = Math.floor(setNow%60);
        timer = requestAnimationFrame(fn);
        if(setNow==0){
            cancelAnimationFrame(timer);
            timer = 0;
            btn.innerHTML = '計時結束';
            for(var i = 0; i < 3; i++){
                myDiv.getElementsByTagName('input')[i].removeAttribute('disabled');
            }
            setTimeout(function(){
                btn.innerHTML = '確定';
            },1000)            
        }

    })
}
</script>

 

秒錶

【1】簡易秒錶

  秒錶與倒計時的思路相同,相比而言,更加簡單。每間隔100ms增加100ms即可

<div id="myDiv">
    <label for="set"><input id="set" value="0"></label>
    <button id="btn">開始</button>
    <button id="reset">重置</button>    
</div>
<script>
var timer;
var con = 'off';
var num = 0;
reset.onclick = function(){
    history.go();
}
btn.onclick = function(){
    if(con === 'off'){
        set.setAttribute('disabled','disabled');
        con = 'on';
        btn.innerHTML = '暫停';
        timer = setInterval(function(){
            num+= 100;
            var minute = Math.floor(num/1000/60);
            var second = Math.floor(num/1000);
            var ms = Math.floor(num%1000)/100;
            set.value = minute + ' : ' + second + ' . ' + ms; 
        },100);
    }else{
        clearInterval(timer);
        con = 'off';
        btn.innerHTML = '開始';    
    }
}    
</script>

【2】精確秒錶

  與倒計時類似,使用計時器的時間間隔作為時間變化的參照是不准確的。更精確的做法,應該是使用系統的時間變化作為秒錶的變化的參照

<div id="myDiv">
    <label for="set"><input id="set" value="0"></label>
    <button id="btn">開始</button>
    <button id="reset">重置</button>    
</div>
<script>
var timer;
var con = 'off';
//ori表示初始的系統時間
var ori;
//dis表示當前運行時的秒數(動態)
var dis = 0;
//last儲存暫停時的秒數(靜態)
var last = 0;
reset.onclick = function(){
    history.go();
}
btn.onclick = function(){
    if(con === 'off'){
        set.setAttribute('disabled','disabled');
        con = 'on';
        btn.innerHTML = '暫停';
        //保留已經走過的秒數的系統時間
        ori = (new Date()).getTime() - last; 
        timer = requestAnimationFrame(function fn(){

            dis = (new Date()).getTime() - ori;
            cancelAnimationFrame(timer);
            timer = requestAnimationFrame(fn);
            var minute = Math.floor(dis/1000/60);
            var second = Math.floor(dis/1000);
            var ms = Math.floor(dis%1000);
            set.value = minute + ' : ' + second + ' . ' + ms; 
        });
    }else{
        cancelAnimationFrame(timer);
        btn.innerHTML = '開始';    
        con = 'off';
        last = dis;
    }
}    
</script>

 

鬧鐘

  鬧鐘其實就是在時鐘的基礎上增加一個預定時間設置,鬧鐘設置需要將設置時間轉換成距離1970年1月1日的毫秒數,然後再算出與當前時間的差值。隨著當前時間的不斷增加,當差值為0時,鬧鐘響起

<div id="myDiv"></div>
<div id="con">
    <label for="hour"><input type="number" id="hour" min="0" max="23" step="1" value="0" />時</label>
    <label for="minute"><input type="number" id="minute" min="0" max="59" step="1" value="0" />分</label>
    <label for="second"><input type="number" id="second" min="0" max="23" step="1" value="0" />秒</label>
    <button id="btn">確定</button>
    <button id="reset">重置</button>
</div>
<div id="show"></div>
<script>
var timer;
//所剩時間
var dis;
myDiv.innerHTML = /\d\d:\d\d:\d\d/.exec(new Date().toString())[0];
setInterval(function(){
    myDiv.innerHTML = /\d\d:\d\d:\d\d/.exec(new Date().toString())[0];    
},100);
reset.onclick = function(){
    history.go();
}
btn.onclick = function(){
    //原始儲存值
    var setOri = hour.value*3600 + minute.value*60 + second.value*1;
    //原始值轉換為1970年的毫秒數
    var setMs = +new Date(new Date().toDateString()) + setOri*1000;
    //如果設置的時間早於當前時間,則設置無效
    if(setMs < +new Date()){
        return;
    }
    for(var i = 0; i < 3; i++){
        con.getElementsByTagName('input')[i].setAttribute('disabled','disabled');
    }
    cancelAnimationFrame(timer);
    timer = requestAnimationFrame(function fn(){
        //算出設置時間與當前時間的差值
        dis = Math.ceil((setMs - (new Date()).getTime())/1000);
        var showHour = Math.floor((dis%86400)/3600);
        var showMinute = Math.floor((dis%3600)/60);
        var showSecond = Math.floor(dis%60);
        timer = requestAnimationFrame(fn);
        show.innerHTML = '距離預定時間還有 ' + showHour + '小時 ' + showMinute + '分 ' + showSecond + '秒';
        //當差值為0時,時間到
        if(dis==0){
            cancelAnimationFrame(timer);
            btn.innerHTML = '時間到了';
            for(var i = 0; i < 3; i++){
                con.getElementsByTagName('input')[i].removeAttribute('disabled');
            }
            timer = setTimeout(function(){
                btn.innerHTML = '確定';
            },1000)            
        }

    });
}
</script>

 

最後

  作為定時器來說,最麻煩的地方是定時器管理。如果,定時器只開啟不關閉,則會造成定時器疊加效果,使得運行越來越快。所以,先關閉再啟用定時器是一個好習慣

  上面四個應用加上之前的日曆效果,基本囊括了關於日期和時間的應用。基本原理都類似,剩下的就是CSS美化和js代碼優化問題

  歡迎交流


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

-Advertisement-
Play Games
更多相關文章
  • 變數是用於存儲數據的容器,與代數相似,可以給變數賦予某個確定的值(例如:$x=3)或者是賦予其它的變數(例如:$x=$y+$z)。變數的定義主要有以下規則: 變數以$開始,後面跟著變數的名稱; 變數名稱有數字、字母、下劃線構成,且第一個字元不能為數字; 變數名稱不能包含空格; 變數名稱區分大小寫。 ... ...
  • 一、Python安裝 在Mac系統下,系統自帶python開發環境,打開終端,輸入python,我們就可以看到當前python版本號,例如我的系統是OS X EI Caption 10.11.1,自帶的python版本是2.7。 目前python已經更新到3.6,因為python3和python2做 ...
  • Java中的GOF23(23中設計模式) 單例模式(Singleton) 在Java這這門語言裡面,它的優點在於它本身的可移植性上面,而要做到可移植的話,本身就需要一個中介作為翻譯工作,以達到本地和Java的統一,但是就這點而言就相當的消耗資源,所以就Java程式員需要不斷的去優化自己的代碼。今天所 ...
  • Python有這麼幾種數據類型: 1. 數字【整型int/long,浮點型float/complex】 int 整型一般32bit機器32位寬,64bit機器64bit寬。 long Python3已經把int和long整合了, 相互轉化會自動進行 float Python的浮點數就是數學中的小數, ...
  • Atitit.事件機制 與 消息機制的聯繫與區別 1. 消息/事件機制是幾乎所有開發語言都有的機制,在某些語言稱之為消息(Event),有些地方稱之為(Message).1 2. 發佈/訂閱模式1 3. 事件是侵入式設計,霸占你的主迴圈;消息是非侵入式設計,將主迴圈該怎樣設計的自由留給用戶。1 3. ...
  • Atitit.atiRI 與 遠程調用的理論and 設計 1. 怎麼做到透明化遠程服務調用?1 2. 2 怎麼對消息進行編碼和解碼1 2.1. 確定消息數據結構dsl1 2.1.1. 消息里為什麼要帶有requestID?2 2.2. 序列化與反序列化 json2 3. 通信 http2 4. 發佈 ...
  • Atitit.js javascript的rpc框架選型 1. Dwr1 2. 使用AJAXRPC1 2.2. 數據類型映射表1 3. json-rpc輕量級遠程調用協議介紹及使用2 3.1. 2.3、JavaScript客戶端調用示例2 3.2. 2.4、直接GET請求進行調用2 4. atiri ...
  • Flickerplate 是個輕量級 jQuery 插件,大小僅為 12 kb。它允許用戶點擊滑鼠然後轉換內容,非常容易使用,響應式,支持觸摸設備 線上實例 使用方法 複製 複製 參數詳解 flick_position inner_width 下載 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...