利用canvas畫一個實時時鐘

来源:https://www.cnblogs.com/qsdf/archive/2018/12/12/10110960.html
-Advertisement-
Play Games

先放一張效果圖: 下麵是源代碼: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> div{ text-align: center; margin-top: 150 ...


先放一張效果圖:

下麵是源代碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            div{
                text-align: center;
                margin-top: 150px;
            }
            canvas{
                border: 1px solid black;
            }
        </style>
    </head>
    <body>
        <div>
            <canvas width="500px" height="500px" id="canvas"></canvas>
        </div>
        
    </body>
    <script type="text/javascript">
        var canvas = document.getElementById("canvas");
        var ctx =canvas.getContext("2d");
        
        var width = canvas.width;
        var height = canvas.height;
        var r = width/2;
        
        var a = Math.floor(Math.random()*256);
        var b = Math.floor(Math.random()*256);
        var c = Math.floor(Math.random()*256);
        
        function fun(){
            ctx.save();
            ctx.translate(r,r);
            ctx.beginPath();
            ctx.arc(0,0,r-5,0,Math.PI*2,false);
            ctx.lineWidth = 10;
            var grd = ctx.createLinearGradient(-r,0,r,0)
            
            grd.addColorStop(0,"rgb("+a+","+b+","+c+")");
            grd.addColorStop(1,"rgb("+c+","+b+","+a+")");
            ctx.strokeStyle = grd;
            //ctx.strokeStyle = "rgb("+a+","+b+","+c+")";
            ctx.stroke();
            
            var num = [3,4,5,6,7,8,9,10,11,12,1,2];
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            
            for(var i =0; i < num.length; i++){
                var rang = Math.PI*2/12*i;
                var x = Math.cos(rang)*(r-30);
                var y = Math.sin(rang)*(r-30);            
                ctx.fillText(num[i],x,y);
                ctx.closePath();
            }
            
            for(var j =0; j < 60; j++){
                var rang1 = Math.PI*2/60*j;
                var x1 = Math.cos(rang1)*(r-20);
                var y1 = Math.sin(rang1)*(r-20);
                ctx.beginPath();
                ctx.arc(x1,y1,3,0,Math.PI*2);
                if(j%5==0){
                    ctx.fillStyle = "#000000";
                }
                else{
                    ctx.fillStyle = "#cccccc";
                }
                ctx.fill();
                ctx.closePath();
            }
        }
            
        function drawHour(hour,minu){
            ctx.save();     //保存當前的狀態
            ctx.beginPath();
            ctx.lineWidth = 6;

            var rad = Math.PI * 2 / 12 * hour;
            var rad_minu = Math.PI * 2 / 12 / 60 * minu;
            ctx.rotate(rad + rad_minu);
                    
            ctx.moveTo(0,10);
            ctx.lineTo(0,-r/2);
            ctx.lineCap="round";
            ctx.stroke();                
            ctx.restore();
        }
            
        function drawMinu(minu,seco){
            ctx.save();
            ctx.beginPath();
            ctx.lineWidth = 4;
                
            var rad = Math.PI * 2 / 60 * minu;                
            var rad_seco = Math.PI * 2 / 60 / 60 * seco;
            ctx.rotate(rad + rad_seco);            
            ctx.moveTo(0,10);
            ctx.lineTo(0,-r+50);
            ctx.lineCap="round";
            ctx.stroke();
            ctx.restore();
        }
            
        function drawSeco(seco){
            ctx.save();
            var rad = Math.PI * 2 / 60 * seco;
                
            ctx.beginPath();
            ctx.rotate(rad);
            ctx.fillStyle = "#f00";
            ctx.moveTo(-2,20);
            ctx.lineTo(2,20);
            ctx.lineTo(1,-r+20);
            ctx.lineTo(-1,-r+20);
            ctx.closePath();
            ctx.fill();
            ctx.restore();
        }
            
        function drawDot(){
            ctx.beginPath();
            ctx.fillStyle = "#fff";
            ctx.arc(0,0,3,0,Math.PI*2);
            ctx.closePath();
            ctx.fill();
        }
                    
        function draw(){
            ctx.clearRect(0,0,width,height);
            var datenow = new Date();
            var hour = datenow.getHours();
            var minu = datenow.getMinutes();
            var seco = datenow.getSeconds();
                
            fun();
            drawHour(hour,minu);
            drawMinu(minu,seco);
            drawSeco(seco);
            drawDot();    
                
            ctx.restore();            
        }
        draw();
            
        setInterval(draw,1000);
            
    </script>
</html>
View Code

————

先建一個畫布

<canvas width="500px" height="500px" id="canvas"></canvas>

然後在script中獲取到它和它的的寬度、高度,同時定義表盤的半徑

var canvas = document.getElementById("canvas");
var ctx =canvas.getContext("2d");
        
var width = canvas.width;
var height = canvas.height;
var r = width/2;

表盤的圓心在畫布中央便於我們的後續操作。可是實際上畫布的原點是畫布的左上角,所以我們可以使用translate()方法重新映射原點坐標:

ctx.translate(r,r);

然後畫一個圓,我在這加了個漸變色。(arc()中的五個參數分別是arc(圓心x坐標,圓心y坐標,半徑,起始角,結束角,Boolean值))


ctx.beginPath();
ctx.arc(0,0,r-5,0,Math.PI*2,false);
ctx.lineWidth = 10;
var grd = ctx.createLinearGradient(-r,0,r,0)            
grd.addColorStop(0,"rgb("+a+","+b+","+c+")");
grd.addColorStop(1,"rgb("+c+","+b+","+a+")");
ctx.strokeStyle = grd;
ctx.stroke();
 

定義一個數組來裝表盤上的數字,然後通過迴圈的方式將他們列印在表盤上,這裡最主要的就是要算出每個數字列印的坐標,我們可以先算出每兩個數字間的弧度,然後就可以根據相應的弧度算出每個數字的位置

var num = [3,4,5,6,7,8,9,10,11,12,1,2];
ctx.textAlign = "center";
ctx.textBaseline = "middle";
            
for(var i =0; i < num.length; i++){
    var rang = Math.PI*2/12*i;
    var x = Math.cos(rang)*(r-30);
    var y = Math.sin(rang)*(r-30);            
    ctx.fillText(num[i],x,y);
    ctx.closePath();
}

然後表盤上的刻度也是同樣的方法,整點的位置上的點我們可以用一點不同的顏色

for(var j =0; j < 60; j++){
                var rang1 = Math.PI*2/60*j;
                var x1 = Math.cos(rang1)*(r-20);
                var y1 = Math.sin(rang1)*(r-20);
                ctx.beginPath();
                ctx.arc(x1,y1,3,0,Math.PI*2);
                if(j%5==0){
                    ctx.fillStyle = "#000000";
                }
                else{
                    ctx.fillStyle = "#cccccc";
                }
                ctx.fill();
                ctx.closePath();
            }

然後是時針部分,繪製指針的時候,可以使用linecap屬性給兩端稍加一點弧度。(使用lineCap之後不能用closePath())

算出時針應該轉動的角度,然後利用rotate()方法轉動它。

        function drawHour(hour,minu){
            ctx.save();
            ctx.beginPath();
            ctx.lineWidth = 6;

            var rad = Math.PI * 2 / 12 * hour;
            var rad_minu = Math.PI * 2 / 12 / 60 * minu;
            ctx.rotate(rad + rad_minu);
                    
            ctx.moveTo(0,10);
            ctx.lineTo(0,-r/2);
            ctx.lineCap="round";
            ctx.stroke();                
            ctx.restore();
        }

然後是分針和秒針

function drawMinu(minu,seco){
            ctx.save();
            ctx.beginPath();
            ctx.lineWidth = 4;
                
            var rad = Math.PI * 2 / 60 * minu;                
            var rad_seco = Math.PI * 2 / 60 / 60 * seco;
            ctx.rotate(rad + rad_seco);            
            ctx.moveTo(0,10);
            ctx.lineTo(0,-r+50);
            ctx.lineCap="round";
            ctx.stroke();
            ctx.restore();
        }
function drawSeco(seco){
            ctx.save();
            var rad = Math.PI * 2 / 60 * seco;
                
            ctx.beginPath();
            ctx.rotate(rad);
            ctx.fillStyle = "#f00";
            ctx.moveTo(-2,20);
            ctx.lineTo(2,20);
            ctx.lineTo(1,-r+20);
            ctx.lineTo(-1,-r+20);
            ctx.closePath();
            ctx.fill();
            ctx.restore();
        }

為了使我們畫的時鐘能夠使用,我們需要獲取到當前的時間,並把時分秒分別賦給相應的變數後傳到相應的函數中,之後用定時器每隔一秒調用一次此函數,就能達到時鐘的效果

        function draw(){
            ctx.clearRect(0,0,width,height);
            var datenow = new Date();
            var hour = datenow.getHours();
            var minu = datenow.getMinutes();
            var seco = datenow.getSeconds();
                
            fun();
            drawHour(hour,minu);
            drawMinu(minu,seco);
            drawSeco(seco);
            drawDot();    
                
            ctx.restore();            
        }
        draw();
            
        setInterval(draw,1000);

 


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

-Advertisement-
Play Games
更多相關文章
  • 下麵代碼是關於android中使用afinal一行顯示網路圖片的代碼。 public class DemoActivity extends FinalActivity { @Override public void onCreate(Bundle savedInstanceState) { supe ...
  • 一,OS X和iOS自帶一些標準的C程式庫和操作系統相關的特殊性。在MAC和iOS的世界里,靜態庫採用.a擴展名(靜態對象代碼庫存檔),動態載入庫採用.dylib擴展名。如果開發人員來自於Linux世界,可能習慣於.so文件;如果開發人員過去是Windows的開發人員,可能把它們稱作DLL。 二,靜 ...
  • 一,Xcode-->Preferences >Key Bindings. 參考資料:《Xcode實戰開發》 ...
  • 1、什麼是CSS盒模型?CSS盒子模型包括元素、內邊距、邊框、外邊距,如下圖: 2、元素分類:元素可以分為塊狀元素、內聯元素、內聯塊狀元素。 常用塊狀元素:<div>、<p>、<h1>...<h6>、<ol>、<ul>、<dl>、<table>、<address>、<blockquote> 、<fo ...
  • 我們通過實現一個簡單版的和Vue中computed具有相同功能的函數來瞭解computed是如何工作的。寫的十分的全面細緻,具有一定的參考價值,對此有需要的朋友可以參考學習下。如有不足之處,歡迎批評指正。 JS屬性: JavaScript有一個特性是 Object.defineProperty ,它 ...
  • 一、window對象的屬性和方法 ①setTimeout()方法用來實現一個函數在指定毫秒之後運行,該方法返回一個值,這個值可以傳遞給clearTimeout()用於取消這個函數的執行。 ②setInterval()用來實現一個在指定毫毛數的時間里重覆調用,返回一個值,這 個值可以傳遞給clearI ...
  • 列印: 列印: 列印: break 和 continue 的區別 1.break 2.continue 練習: 對象 一、 在ECMAscript中,引用類型是一種數據結構.用於將數據和功能組織在一起.在其他語言這種數據結構一般屬於類(class)的範疇 .儘管ECMAscript是一門面向對象的語 ...
  • 先來個基礎的 需求 根據下麵需求實現如示意圖所示的郵箱輸入提示功能,註意,根據要求只需實現下麵功能 當用戶沒有任何輸入時,提示框消失 當用戶輸入字元後,顯示提示框,並且把用戶輸入的內容自動拼上郵箱尾碼進行顯示 暫時不用考慮示意圖中的紅色和藍色背景色的邏輯 註意用戶輸入中前後空格需要去除 小優化編碼 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...