Canvas學習-時鐘繪製

Canvas學習-時鐘繪製

1. 繪製時鐘外邊框

  • 創建畫布
<div class="container">
   <canvas id="clock" height="200px" width="200px"></canvas>
</div>

備註:該容器就是繪製圖形的畫布。

  • 繪製圓環
var dom = document.getElementById('clock'); //獲取元素
var ctx = dom.getContext('2d'); //上下文
var width = ctx.canvas.width; //上下文的寬度
var height = ctx.canvas.height; //上下文的高度
var r = width / 2;  //半徑

// 繪製圓環
function drawBackground() {
    ctx.translate(r, r); //確定座標遠點
    ctx.beginPath(); //開始畫圖
    ctx.lineWidth = 10; // 設置線條粗細
    ctx.arc(0, 0, r-5, 0, 2 * Math.PI, false); //繪製圓形
    ctx.stroke(); //繪製

}
drawBackground();

2.繪製時鐘內容

    // 繪製小時數
    var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
    ctx.font = '18px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    hourNumbers.forEach(function (number, i) {
        var rad = 2 * Math.PI / 12 * i;
        var x = Math.cos(rad) * (r - 30);
        var y = Math.sin(rad) * (r - 30);
        ctx.fillText(number, x, y);
    })

備註:在繪製小時數的時候,我們應該確定數字與對應弧度的關係,建立數組,填充數字。


3. 繪製小時數對應的圓點

    // 繪製小時數對應的點
    for (var i = 0; i < 60; i++) {
        var rad = 2 * Math.PI / 60 * i;
        var x = Math.cos(rad) * (r - 18);
        var y = Math.sin(rad) * (r - 18);
        ctx.beginPath();
        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();
    }

備註:繪製圓點的時候,我們需要區分整點數與非整點數之間的區別,填充不同的背景顏色。


4.繪製是真分針秒針

// 畫時針
function drawHour(hour, minute) {
    ctx.save();
    ctx.beginPath();
    var rad = 2 * Math.PI / 12 * hour;
    var mrad = 2 * Math.PI / 12 / 60 * minute;
    ctx.rotate(rad + mrad);
    ctx.lineWidth = 6;
    ctx.lineCap = 'round';
    ctx.moveTo(0, 10);
    ctx.lineTo(0, -r / 2);
    ctx.stroke();
    ctx.restore();

}

// 畫分針
function drawMinute(minute, second) {
    ctx.save();
    ctx.beginPath();
    var rad = 2 * Math.PI / 60 * minute;
    var srad = 2 * Math.PI / 60 / 60 * second;
    ctx.rotate(rad + srad);
    ctx.lineWidth = 3;
    ctx.lineCap = 'round';
    ctx.moveTo(0, 10);
    ctx.lineTo(0, -r + 30);
    ctx.stroke();
    ctx.restore();
}

// 畫秒針
function drawSecond(second) {
    ctx.save();
    ctx.beginPath();
    ctx.fillStyle = '#c14543';
    var rad = 2 * Math.PI / 60 * second;
    ctx.rotate(rad);
    ctx.moveTo(-2, 20);
    ctx.lineTo(2, 20);
    ctx.lineTo(1, -r + 18);
    ctx.lineTo(-1, -r + 18);
    ctx.lineTo(0, -r + 30);
    ctx.fill();
    ctx.restore();
}

備註:繪製分針的時候,我們需要考慮到分針對其的影響,所以需要計算分針數引起時針的弧度改變。在繪製分針的時候,同樣需要考慮秒針對分針的影響。


4. 畫中心點

// 畫中心點
function drawDot() {
    ctx.beginPath();
    ctx.fillStyle = '#FFFFFF';
    ctx.arc(0, 0, 3, 2 * Math.PI, false)
    ctx.fill();
}

5. 最終繪製方法

function draw() {
    ctx.clearRect(0, 0, width, height);
    var now = new Date();
    var hour = now.getHours();
    var minute = now.getMinutes();
    var second = now.getSeconds();
    drawBackground();
    drawHour(hour, minute);
    drawMinute(minute, second);
    drawSecond(second);
    drawDot();
    ctx.restore();
}


draw();
setInterval(draw, 1000);

備註:在繪製圖形的時候,我們需要注意一下幾點:

  • 繪製之前,我們需要清除畫布,避免圖形的疊加。
  • 主要保存畫布之前的狀態,還原狀態,避免影響。
  • 利用定時器,每隔一秒鐘,重新繪製圖片。

6. 效果圖

在這裏插入圖片描述


7. 代碼

var dom = document.getElementById('clock'); //獲取元素
var ctx = dom.getContext('2d'); //上下文
var width = ctx.canvas.width; //上下文的寬度
var height = ctx.canvas.height; //上下文的高度
var r = width / 2;  //半徑

// 繪製圓環
function drawBackground() {
    ctx.save();
    ctx.translate(r, r); //確定座標遠點
    ctx.beginPath(); //開始畫圖
    ctx.lineWidth = 10; // 設置線條粗細
    ctx.arc(0, 0, r - 5, 0, 2 * Math.PI, false); //繪製圓形
    ctx.stroke(); //繪製


    // 繪製小時數
    var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
    ctx.font = '18px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    hourNumbers.forEach(function (number, i) {
        var rad = 2 * Math.PI / 12 * i;
        var x = Math.cos(rad) * (r - 30);
        var y = Math.sin(rad) * (r - 30);
        ctx.fillText(number, x, y);
    })


    // 繪製小時數對應的點
    for (var i = 0; i < 60; i++) {
        var rad = 2 * Math.PI / 60 * i;
        var x = Math.cos(rad) * (r - 18);
        var y = Math.sin(rad) * (r - 18);
        ctx.beginPath();
        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();
    }

}




// 畫時針
function drawHour(hour, minute) {
    ctx.save();
    ctx.beginPath();
    var rad = 2 * Math.PI / 12 * hour;
    var mrad = 2 * Math.PI / 12 / 60 * minute;
    ctx.rotate(rad + mrad);
    ctx.lineWidth = 6;
    ctx.lineCap = 'round';
    ctx.moveTo(0, 10);
    ctx.lineTo(0, -r / 2);
    ctx.stroke();
    ctx.restore();

}

// 畫分針
function drawMinute(minute, second) {
    ctx.save();
    ctx.beginPath();
    var rad = 2 * Math.PI / 60 * minute;
    var srad = 2 * Math.PI / 60 / 60 * minute;
    ctx.rotate(rad + srad);
    ctx.lineWidth = 3;
    ctx.lineCap = 'round';
    ctx.moveTo(0, 10);
    ctx.lineTo(0, -r + 30);
    ctx.stroke();
    ctx.restore();
}

// 畫秒針
function drawSecond(second) {
    ctx.save();
    ctx.beginPath();
    ctx.fillStyle = '#c14543';
    var rad = 2 * Math.PI / 60 * second;
    ctx.rotate(rad);
    ctx.moveTo(-2, 20);
    ctx.lineTo(2, 20);
    ctx.lineTo(1, -r + 18);
    ctx.lineTo(-1, -r + 18);
    ctx.lineTo(0, -r + 30);
    ctx.fill();
    ctx.restore();
}

// 畫中心點
function drawDot() {
    ctx.beginPath();
    ctx.fillStyle = '#FFFFFF';
    ctx.arc(0, 0, 3, 2 * Math.PI, false)
    ctx.fill();
}

function draw() {
    ctx.clearRect(0, 0, width, height);
    var now = new Date();
    var hour = now.getHours();
    var minute = now.getMinutes();
    var second = now.getSeconds();
    drawBackground();
    drawHour(hour, minute);
    drawMinute(minute, second);
    drawSecond(second);
    drawDot();
    ctx.restore();
}


draw();
setInterval(draw, 1000);

8. 思考

如果畫布放大,那麼圖像會怎麼樣呢?顯然,因爲其中部分數據大小是固定寫死的,必然出現不協調的地方,此時我們必須考慮到,數據的比例問題。修改思路如下:在寬度、文字大小部分,我們需要採用相對大小。


9. 代碼優化

優化思路:首先確定比例,var rem = width/ 200; //比例(因爲初始樣式的數據是按照200爲基準的) ,然後在對應的數字大小部分乘上該比例即可。修改後的代碼如下:

var dom = document.getElementById('clock'); //獲取元素
var ctx = dom.getContext('2d'); //上下文
var width = ctx.canvas.width; //上下文的寬度
var height = ctx.canvas.height; //上下文的高度
var r = width / 2;  //半徑
var rem = width/ 200; //比例(因爲初始樣式的數據是按照200爲基準的)

// 繪製圓環
function drawBackground() {
    ctx.save();
    ctx.translate(r, r); //確定座標遠點
    ctx.beginPath(); //開始畫圖
    ctx.lineWidth = 10 * rem; // 設置線條粗細
    ctx.arc(0, 0, r - ctx.lineWidth/2, 0, 2 * Math.PI, false); //繪製圓形
    ctx.stroke(); //繪製


    // 繪製小時數
    var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
    ctx.font = 18* rem + 'px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    hourNumbers.forEach(function (number, i) {
        var rad = 2 * Math.PI / 12 * i;
        var x = Math.cos(rad) * (r - 30* rem);
        var y = Math.sin(rad) * (r - 30* rem);
        ctx.fillText(number, x, y);
    })


    // 繪製小時數對應的點
    for (var i = 0; i < 60; i++) {
        var rad = 2 * Math.PI / 60 * i;
        var x = Math.cos(rad) * (r - 18* rem);
        var y = Math.sin(rad) * (r - 18* rem);
        ctx.beginPath();
        if (i % 5 === 0) {
            ctx.fillStyle = "#000";
            ctx.arc(x, y, 2* rem, 0, 2 * Math.PI, false);
        } else {
            ctx.fillStyle = "#ccc";
            ctx.arc(x, y, 2* rem, 0, 2 * Math.PI, false);
        }
        ctx.fill();
    }

}




// 畫時針
function drawHour(hour, minute) {
    ctx.save();
    ctx.beginPath();
    var rad = 2 * Math.PI / 12 * hour;
    var mrad = 2 * Math.PI / 12 / 60 * minute;
    ctx.rotate(rad + mrad);
    ctx.lineWidth = 6* rem;
    ctx.lineCap = 'round';
    ctx.moveTo(0, 10* rem);
    ctx.lineTo(0, -r / 2);
    ctx.stroke();
    ctx.restore();

}

// 畫分針
function drawMinute(minute, second) {
    ctx.save();
    ctx.beginPath();
    var rad = 2 * Math.PI / 60 * minute;
    var srad = 2 * Math.PI / 60 / 60 * second;
    ctx.rotate(rad + srad);
    ctx.lineWidth = 3* rem;
    ctx.lineCap = 'round';
    ctx.moveTo(0, 10* rem);
    ctx.lineTo(0, -r + 30* rem);
    ctx.stroke();
    ctx.restore();
}

// 畫秒針
function drawSecond(second) {
    ctx.save();
    ctx.beginPath();
    ctx.fillStyle = '#c14543';
    var rad = 2 * Math.PI / 60 * second;
    ctx.rotate(rad);
    ctx.moveTo(-2* rem, 20* rem);
    ctx.lineTo(2* rem, 20* rem);
    ctx.lineTo(1, -r + 18* rem);
    ctx.lineTo(-1, -r + 18* rem);
    ctx.fill();
    ctx.restore();
}

// 畫中心點
function drawDot() {
    ctx.beginPath();
    ctx.fillStyle = '#FFFFFF';
    ctx.arc(0, 0, 3* rem, 2 * Math.PI, false)
    ctx.fill();
}

function draw() {
    ctx.clearRect(0, 0, width, height);
    var now = new Date();
    var hour = now.getHours();
    var minute = now.getMinutes();
    var second = now.getSeconds();
    drawBackground();
    drawHour(hour, minute);
    drawMinute(minute, second);
    drawSecond(second);
    drawDot();
    ctx.restore();
}


draw();
setInterval(draw, 1000);

10. 代碼下載

鏈接:canvas學習代碼下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章