使用Canvas繪製簡單的時鐘控制項

来源:https://www.cnblogs.com/zhoutao825638/archive/2019/02/15/10381985.html
-Advertisement-
Play Games

Canvas是HTML5新增的組件,它就像一塊幕布,可以用JavaScript在上面繪製各種圖表、動畫等。 沒有Canvas的年代,繪圖只能藉助Flash插件實現,頁面不得不用JavaScript和Flash進行交互。有了Canvas,我們就再也不需要Flash了,直接使用JavaScript完成繪 ...


Canvas是HTML5新增的組件,它就像一塊幕布,可以用JavaScript在上面繪製各種圖表、動畫等。
沒有Canvas的年代,繪圖只能藉助Flash插件實現,頁面不得不用JavaScript和Flash進行交互。有了Canvas,我們就再也不需要Flash了,直接使用JavaScript完成繪製。

基本使用

在html源碼中只要像普通標簽那樣使用即可,比如下麵的示例,但是在一些老舊的瀏覽器在中是不支持canvas的,因此我們常在canvas標簽中提示用戶,具體代碼如下所示。

    <canvas id="myCanvas" width="300px" height="300px">
        您的瀏覽器不支持canvas,請嘗試更新瀏覽器
    </canvas>

或者使用JS腳本來進行檢測,使用JavaScript代碼檢測是否支持canvas的代碼示例如下:

    var myCanvas = document.getElementById('myCanvas');
    if (myCanvas.getContext) {
        myCanvas.log('你的瀏覽器支持Canvas!');
    } else {
        myCanvas.log('你的瀏覽器不支持Canvas!');
    }

開始繪製

由於繪製canvas通常代碼需要比較多,我們常常使用引用js的方式來繪製canvas,這裡我們也是引入js文件來操作canvas,HTML源碼如下所示

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>學習Canvas繪製始終效果</title>
        <style>
            canvas{
                border: 1px solid #cccccc;
            }
        </style>
    </head>
    <body>
    <canvas id="myCanvas" width="300px" height="300px">
        您的瀏覽器不支持Canvas,請嘗試更新瀏覽器
    </canvas>
    <script src="js/canvas.js"></script>
    </body>
    </html>

創建js文件

根據實際的需要創建js文件,這裡我引入的地址是js/canvas.js,因此需要和HTML源碼文件同級下創建js文件夾,然後再js文件夾中創建canvas.js文件。

繪製測試示例

繪製效果如下

<div style="align: center">  
<img src = "http://www.zhoutao123.com:9000/upload/2017/12/4s4ptf692qhjtq6f1pdddj1l9b.png" width="200">
</div>

動態效果

預備代碼

這裡保持一些全局變數,方便後面使用的

    //獲取canvas的上下文環境
    var myCanvas = document.getElementById('myCanvas')
    var ctx = myCanvas.getContext('2d')
    //獲取canvas的寬度和高度
    var canvasWidth = myCanvas.width
    var canvasHeight = myCanvas.height

繪製背景

我們首先繪製背景,分析背景可以看到,他是由一個大的黑色與圓圈包裹,裡面有一個灰色的略小的圓圈,在灰色圓圈的周圍均勻分佈著時鐘點,這些時鐘點每逢5的倍數的時候突出顯示,否則就是灰色顯示,這就是我們的需求,具體註釋在代碼中可以詳細看到。

    //開始繪製背景
    function drawBackground() {
        //未防止當前畫布環境被破壞,因此我們保存當前的繪製環境
        ctx.save()
        //開始繪製路徑
        ctx.beginPath()
        //配置繪製顏色,我們首先繪製的是黑色圓圈,因此我們配置為黑色
        ctx.strokeStyle = '#000000'
        //繪製寬度為6個像素
        ctx.lineWidth = 6
        //開始繪製圓,圓心未知是寬和高的一半,半徑是寬度的一半減去圓圈的寬度
        //這裡最後的兩個參數需要註意
        //指的是繪製圓圈的起點和繪製的弧度
        //我們從0點開始繪製然後繪製2*PI個弧度,也就是一個正圓
        //這裡的點是從x軸正方向開始的
        ctx.arc(canvasWidth/2,canvasHeight/2,canvasHeight/2-3,0,2*Math.PI)
        //配置完成,開始繪製
        ctx.stroke()

        //同樣的需求開始繪製灰色的圓圈
        ctx.beginPath()
        ctx.strokeStyle = '#CCCCCC'
        ctx.lineWidth = 1
        ctx.arc(canvasWidth/2,canvasHeight/2,(canvasWidth/2-15),0,2*Math.PI)
        ctx.stroke()

        //將原點從左上角0,0移動到中心位置
        ctx.translate(canvasWidth/2,canvasHeight/2)

        //需要現實的數字
        //這是可以看到,數字是從3開始的,也驗證了我們的之前說的繪製從x軸正方向開始
        //在時鐘界面x軸正方向就是3點鐘
        var colorNumber = [3,4,5,6,7,8,9,10,11,12,1,2]
        //配置字體和對齊方向
        ctx.font="25px Arial";
        ctx.textAlign = "center"
        ctx.textBaseline = "middle"
        //迴圈遍歷,開始繪製數字
        for(var i = 0;i<colorNumber.length;i++){
            var dep = 2 * Math.PI /12 * i;
            ctx.fillText(colorNumber[i],(canvasWidth/2-30) * Math.cos(dep),(canvasHeight/2-30)* Math.sin(dep))
        }

        //繪製時鐘點
        for(var i = 0;i<60;i++){
            var  rad =  2 * Math.PI /60 * i;
            var x = Math.cos(rad) * (canvasHeight/2-16)
            var y = Math.sin(rad) * (canvasHeight/2-16)
            ctx.beginPath();
            //如果是5的倍數,使用黑色填充,否則使用灰色填充
            if (i % 5 === 0){
                ctx.fillStyle = "#000"
                ctx.arc(x,y,2,0,2*Math.PI,false)
            }else{
                ctx.fillStyle = "#CCC"
                ctx.arc(x,y,2,0,2*Math.PI,false)
            }
            ctx.fill()
        }
    }

繪製時針

繪製時針、分針以及秒針的理念是先繪製0時刻的樣子,然後旋轉畫布一定的弧度,從而達到轉動的效果。

    //繪製時針
    function drawHours(hours,minte) {
        //保存環境
        ctx.save()
        //計算時鐘角度和偏離的角度
        var rad = 2 * Math.PI / 12 * hours;
        var rad2 = 2 * Math.PI / 12 /60 * minte;
        //旋轉畫布
        ctx.rotate(rad+rad2)
        ctx.beginPath();
        //配置繪製效果
        ctx.lineWidth = 6
        ctx.strokeStyle = "#000"
        //線的兩端保持圓角
        ctx.lineCap = "round"
        //將繪製點移動到中心原點以下10個像素點
        ctx.moveTo(0,10);
        //繪製一個線
        ctx.lineTo(0,-(canvasWidth-150)/2)
        ctx.stroke()
        //恢復之前保存的環境
        ctx.restore()
    }

繪製分針和秒針

繪製分針和秒針的方法和時針一樣,僅僅是繪製的顏色和寬度不一樣,這裡不再詳細贅述.

    //繪製分針
    function drawMinute(minute) {
        ctx.save()
        var rad = 2 * Math.PI / 60 * minute;
        ctx.rotate(rad)
        ctx.beginPath();
        ctx.lineWidth = 3
        ctx.strokeStyle = "#000"
        ctx.lineCap = "round"
        ctx.moveTo(0,10);
        ctx.lineTo(0,-(canvasWidth-100)/2)
        ctx.stroke()
        ctx.restore()
    }
    //繪製秒針
    function drawSecond(second) {
        ctx.save()
        var rad = 2 * Math.PI / 60 * second;
        ctx.rotate(rad)
        ctx.beginPath();
        ctx.lineWidth = 3
        ctx.strokeStyle = "#f00"
        ctx.lineCap = "round"
        ctx.moveTo(0,20);
        ctx.lineTo(0,-(canvasWidth-40)/2)
        ctx.stroke()
        ctx.restore()
    }

繪製中心白點

時針、分針和秒針的中心集合點出有白點,類似某個機械元件,將三個針鎖住,我們只要繪製原點即可。

    //繪製原點
    function drawPoint() {
        ctx.beginPath()
        ctx.fillStyle ="#FFF"
        ctx.arc(0,0,3,0,2*Math.PI)
        ctx.fill()
    }

開始時鐘

我們將當前時間繪製到始終上面即可,需要註意的是,在繪製之前需要將之前繪製的東西清除掉。

    //開始啟動時針
    function startColor() {
        //清除畫布內容
        ctx.clearRect(0,0,canvasWidth,canvasHeight)
        var date = new Date()
        var hour = date.getHours()
        var minute = date.getMinutes()
        var second = date.getSeconds()
        drawBackground()
        drawHours(hour,minute)
        drawMinute(minute)
        drawSecond(second)
        drawPoint()
        ctx.restore()
    }

設置定時重新繪製

要想動態的讓時鐘跑起來,我們需要設置一個定時執行器,每秒更新一次,這樣始終就完全動起來了

    setInterval(startColor,1000)

總結

這個時鐘的寬度和高度已經寫死了,在動態調節的過程中,會出現錯位等問題,下一篇將修正這個問題,敬請期待。


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

-Advertisement-
Play Games
更多相關文章
  • 在 GearCase 開源項目構建 Table 組件的過程中。遇到了各式各樣的問題,最後嘗試了各種方法去解決這些問題。 遇到的部分問題 checkbox 的全選和半選問題 table 組件的排序請求方法 table 組件固定表頭問題 固定表頭時寬度計算的問題 點擊 icon 排序事件無法觸發的問題 ...
  • wxml文件 wxss文件 js文件 效果圖: ...
  • 在for迴圈中使用let時,結果如下 for內部定義的i在迴圈結束後不會覆蓋外部的i 在for迴圈中使用var,且不控制i的作用域時,結果如下 第一個for迴圈內部定義的i並不會創建,而是直接使用外部中的i,故在迴圈結束時外部的i變為了5。 第二個for迴圈直接使用了外部的i 把第一個for迴圈存於 ...
  • 這兩天擺弄webpack,躺過很多坑,直到今天看了一位博主的文章才得以解決。他對配置中的各個部分做說明。 下麵的配置99.9%抄自博主: https://www.cnblogs.com/nianyifenzhizuo/p/10271001.html 安裝package.json中的node-sass ...
  • 本篇博客主要是介紹如何使用css在盒子四個邊框顯示四個藍色邊角 ...
  • 有時我們看見js函數後面跟著多個小括弧是什麼意思?f( )( )( )... f()執行f函數,返回子函數 f()()執行子函數,返回孫函數 f()()()執行孫函數,返回重孫函數 ... ... 但註意,如果想這樣執行,函數結構必須是這樣,f的函數體里要return 子函數,子函數里要return ...
  • JSON詳解 JSON詳解 閱讀目錄 JSON的兩種結構 認識JSON字元串 在JS中如何使用JSON 在.NET中如何使用JSON 總結 JSON的全稱是”JavaScript Object Notation”,意思是JavaScript對象表示法,它是一種基於文本,獨立於語言的輕量級數據交換格式 ...
  • 應用:ActionSheet("","修改IP鏈接後會 有可能 導致 無法登錄 ,是否進行修改?"); 其他參數就不寫了,自己看情況加上去 結果: // 以下內容為代碼中附帶的代碼 // 附上請求數據的 GetData 方法 的代碼(這個方法可換成你們自己的請求數據的方法,不唯一): 附上 Load ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...