前言
最近公司做專案用到了統計圖一些東西,我當然用的是第三方類庫,週末在家沒事想起了canvas繪圖,就熟悉了一下並做了一個鐘錶的小例子,如圖:
雖然樣子醜點,但是該有的功能一點都不少,接下來就說下怎樣實現的。
介紹canvas
現在大部分瀏覽器都支援canvas,使用canvas前要新建個畫布,就是這樣
<canvas id="myCanvas" width="200" height="100"></canvas>
複製程式碼
然後再說一些常用的屬性和方法:
顏色和樣式
- fillStyle 設定或返回用於填充繪畫的顏色、漸變或模式
- strokeStyle 設定或返回用於筆觸的顏色、漸變或模式
- shadowColor 設定或返回用於陰影的顏色
矩形
- rect() 建立矩形
- fillRect() 繪製“被填充”的矩形
- strokeRect() 繪製矩形(無填充)
- clearRect() 在給定的矩形內清除指定的畫素
路徑
- fill() 填充當前繪圖(路徑)
- stroke() 繪製已定義的路徑
- beginPath() 起始一條路徑,或重置當前路徑
- moveTo() 把路徑移動到畫布中的指定點,不建立線條
- closePath() 建立從當前點回到起始點的路徑
- lineTo() 新增一個新點,然後在畫布中建立從該點到最後指定點的線條
- clip() 從原始畫布剪下任意形狀和尺寸的區域
- quadraticCurveTo() 建立二次貝塞爾曲線
- bezierCurveTo() 建立三次方貝塞爾曲線
- arc() 建立弧/曲線(用於建立圓形或部分圓)
- arcTo() 建立兩切線之間的弧/曲線
- isPointInPath() 如果指定的點位於當前路徑中,則返回 true,否則返回 false
文字
- font 設定或返回文字內容的當前字型屬性
- textAlign 設定或返回文字內容的當前對齊方式
- textBaseline 設定或返回在繪製文字時使用的當前文字基線
- fillText() 在畫布上繪製“被填充的”文字
- strokeText() 在畫布上繪製文字(無填充)
- measureText() 返回包含指定文字寬度的物件
影像繪製
- drawImage() 向畫布上繪製影像、畫布或視訊
今天用到的暫時就這麼多。
繪製鐘錶
首先新建一個html檔案,新建畫板並且給畫板增加些樣式,就像這樣
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鐘錶</title>
<style>
#canvas {
border: 1px solid #000;
margin: 0 auto;
display: block;
}
</style>
</head>
<body>
<!-- 新建畫板 -->
<canvas id="canvas" width="400" height="400"></canvas>
</body>
</html>
複製程式碼
然後開始操作canvas,
//獲取canvas標籤,並且建立 context 物件
var canvas = document.getElementById(`canvas`),
context = canvas.getContext(`2d`),
deg = Math.PI/180;
context.translate(200,200); 複製程式碼
說明:getContext(“2d”) 物件是內建的 HTML5 物件,擁有多種繪製路徑、矩形、圓形、字元以及新增影像的方法,deg計算圓周率,translate() 畫布的位置
建立錶盤、數字、刻度、中心點
建立錶盤
context.beginPath();
context.arc(0, 0, 150, 0, 360 * deg);
context.lineWidth = 3;
context.stroke();
context.closePath();
複製程式碼
建立數字
//建立數字
for (var i = 1; i <= 12; i++) {
context.beginPath();
context.save();
context.rotate(30 * i * deg);
context.textAlign = `center`;
if (i % 3 == 0) {
context.fillStyle = `red`;
context.font = "normal 28px arial";
context.fillText(i, 0, -110);
} else {
context.font = "normal 20px arial";
context.fillText(i, 0, -120);
}
context.restore();
context.closePath();
}
複製程式碼
建立刻度
for (var i = 1; i <= 60; i++) {
context.beginPath();
context.save();
context.rotate(6 * i * deg);
context.moveTo(0, -150);
//判斷刻度顯示顏色
if (i % 15 == 0) {
context.strokeStyle = `red`;
context.lineWidth = 3;
context.lineTo(0, -135);
context.stroke();
} else if (i % 5 == 0) {
context.strokeStyle = `orange`;
context.lineWidth = 2;
context.lineTo(0, -140);
context.stroke();
} else {
context.strokeStyle = `#000`;
context.lineWidth = 1;
context.lineTo(0, -145);
context.stroke();
}
context.restore();
context.closePath();
}
複製程式碼
建立中心點
context.beginPath();
context.arc(0, 0, 5, 0, 360 * deg);
context.fill();
context.closePath();
複製程式碼
如圖:
建立指標
var nowdate = new Date(),
hour = nowdate.getHours() % 12,
minu = nowdate.getMinutes(),
second = nowdate.getSeconds();
var ms = nowdate.getMilliseconds(); //毫秒
//秒針
context.beginPath();
context.save();
context.lineWidth = 1;
context.strokeStyle = `red`;
//context.rotate(6*second*deg);
context.rotate((ms / 1000 + second) * 6 * deg);
context.moveTo(0, 20);
context.lineTo(0, -130);
context.stroke();
context.restore();
context.closePath();
//分針
context.beginPath();
context.save();
context.lineWidth = 2;
context.strokeStyle = `orange`;
//context.rotate((second/60+minu)*6*deg);
context.rotate((ms / 1000 / 60 + second / 60 + minu) * 6 * deg);
context.moveTo(0, 10);
context.lineTo(0, -120);
context.stroke();
context.restore();
context.closePath();
//時針
context.beginPath();
context.save();
context.lineWidth = 3;
context.strokeStyle = `#000`;
//context.rotate((second/3600+minu/60+hour)*30*deg);
context.rotate((ms / 1000 / 60 / 60 + second / 60 / 60 + minu / 60 + hour) * 30 * deg);
context.moveTo(0, 0);
context.lineTo(0, -110);
context.stroke();
context.restore();
context.closePath();
複製程式碼
如圖:
是不是以為到現在就結束了,我大聲的告訴大家沒有,現在才是剛剛開始,接下來就是見證奇蹟的時刻。。。
最後完成
我們需要把上邊的繪製封裝成方法,然後不停的繪製不停的清除這樣鐘錶就動起來了
function dialPlate() { //建立錶盤
//context.clearRect(-150,-150,400,400);//清除畫布
context.beginPath();
context.arc(0, 0, 150, 0, 360 * deg);
context.lineWidth = 3;
context.stroke();
context.closePath();
//建立刻度
for (var i = 1; i <= 60; i++) {
context.beginPath();
context.save();
context.rotate(6 * i * deg);
context.moveTo(0, -150);
if (i % 15 == 0) {
context.strokeStyle = `red`;
context.lineWidth = 3;
context.lineTo(0, -135);
context.stroke();
} else if (i % 5 == 0) {
context.strokeStyle = `orange`;
context.lineWidth = 2;
context.lineTo(0, -140);
context.stroke();
} else {
context.strokeStyle = `#000`;
context.lineWidth = 1;
context.lineTo(0, -145);
context.stroke();
}
context.restore();
context.closePath();
}
//建立數字
for (var i = 1; i <= 12; i++) {
context.beginPath();
context.save();
context.rotate(30 * i * deg);
context.textAlign = `center`;
if (i % 3 == 0) {
context.fillStyle = `red`;
context.font = "normal 28px arial";
context.fillText(i, 0, -110);
} else {
context.font = "normal 20px arial";
context.fillText(i, 0, -120);
}
context.restore();
context.closePath();
}
//中心點
context.beginPath();
context.arc(0, 0, 5, 0, 360 * deg);
context.fill();
context.closePath();
}
function Pointer() { //建立指標
var nowdate = new Date(),
hour = nowdate.getHours() % 12,
minu = nowdate.getMinutes(),
second = nowdate.getSeconds();
var ms = nowdate.getMilliseconds(); //毫秒
//秒針
context.beginPath();
context.save();
context.lineWidth = 1;
context.strokeStyle = `red`;
//context.rotate(6*second*deg);
context.rotate((ms / 1000 + second) * 6 * deg);
context.moveTo(0, 20);
context.lineTo(0, -130);
context.stroke();
context.restore();
context.closePath();
//分針
context.beginPath();
context.save();
context.lineWidth = 2;
context.strokeStyle = `orange`;
//context.rotate((second/60+minu)*6*deg);
context.rotate((ms / 1000 / 60 + second / 60 + minu) * 6 * deg);
context.moveTo(0, 10);
context.lineTo(0, -120);
context.stroke();
context.restore();
context.closePath();
//時針
context.beginPath();
context.save();
context.lineWidth = 3;
context.strokeStyle = `#000`;
//context.rotate((second/3600+minu/60+hour)*30*deg);
context.rotate((ms / 1000 / 60 / 60 + second / 60 / 60 + minu / 60 + hour) * 30 * deg);
context.moveTo(0, 0);
context.lineTo(0, -110);
context.stroke();
context.restore();
context.closePath();
}
dialPlate();
Pointer();
setInterval(function(){
dialPlate();
Pointer();
},1000/60)
複製程式碼
說明:動畫每秒執行60次是最好的,所以定時器才讓他沒秒執行60次。
到現在是真結束了,一個簡單的canvas繪製鐘錶就完成了。希望可以到 專案上點一個 star 作為你對這個專案的認可與支援,謝謝。 聽說長的帥的小哥哥和長的漂亮的小姐姐都會點讚的。