你想知道的canvas在這里(小白看過來)

初識canvas


前段時間重新看了一下canvas,覺得很有意思,現(xiàn)在總結(jié)一下,只限于基礎(chǔ)的,中間有一些小的案例,說的有一些啰嗦,建議初學(xué)者參考,歡迎批評指正,共同進(jìn)步!

首先,我們來認(rèn)識一下,什么是canvas

一、Canvas定義:

通常用于繪制圖表、動畫,通過腳本(javascript)來完成,?<canvas> 元素本身并沒有繪制能力(它僅僅是圖形的容器)

不支持canvas的瀏覽器頁面為空不顯示 (ie9以下)

可在canvas標(biāo)簽內(nèi)寫p標(biāo)簽

<p>您的瀏覽器不支持canvas</p>

支持cnavas的瀏覽器將不識別此標(biāo)簽

二、Canvas使用方法:

創(chuàng)建一個畫布,在頁面中引入canvas標(biāo)簽, 默認(rèn)寬300px ?高 150px

<canvas? id="can" ></canvas>//默認(rèn)寬300px ?高 150px

設(shè)置畫布大小的方法:

1、屬性width ?height 設(shè)置寬高,畫布上每個點都是一個像素

<canvas? id="can" width="800" height="800"></canvas>

那么問題來了

是否可以在style里面修改畫布大?。?/p>

不可以 ,畫布里面的內(nèi)容也會被縮放

獲取canvas畫布:

var oC = document.getElementById('can');

繪制繪圖環(huán)境

var cte = oC.getContext('2d');

設(shè)置繪制環(huán)境?:getContext(默認(rèn)的是2d的場景)?------方法可返回一個對象,該對象提供了用于在畫布上繪圖的方法和屬性。

繪制圖形

一 、繪制方塊

fillRect(X,Y,W,H): 默認(rèn)填充顏色是黑色

參數(shù):

X/Y:距離畫布的坐標(biāo)

W/H:矩形的寬高

var can = document.getElementById('can');//獲取畫布

var canT = can.getContext('2d');//繪制繪圖環(huán)境

canT.fillRect(10,10,100,100);//畫矩形

效果圖:

設(shè)置繪圖樣式? ? (繪制填充矩形要先設(shè)置樣式,再繪制)

fillStyle: 填充繪畫的顏色、漸變或模式

填充的矩形要設(shè)置lineJoin樣式(設(shè)置一個同坐標(biāo)的描邊矩形,設(shè)置描邊矩形的lineJoin樣式

var can = document.getElementById('can');

var canT = can.getContext('2d');

canT.fillStyle='#f40';//繪制填充矩形要先設(shè)置樣式,再繪制

canT.fillRect(10,10,100,100);

效果圖:

二,設(shè)置描邊矩形

strokeRect(X,Y,W,H): 帶邊框的方塊,默認(rèn)一像素黑色邊框

參數(shù):

X/Y:距離畫布的坐標(biāo)

W/H:矩形的寬高

var can = document.getElementById('can');

var canT = can.getContext('2d');

canT.fillStyle='#f40';

canT.fillRect(10,10,100,100);

canT.strokeRect(150,10,100,100);

效果圖:


設(shè)置繪圖樣式? ( 繪制填充矩形要先設(shè)置樣式,再繪制)

a 繪圖環(huán)境.strokeStyle='顏色'

b 繪圖環(huán)境.lineWidth ='數(shù)值'

a繪圖環(huán)境.strokeStyle='顏色'

var can = document.getElementById('can');

var canT = can.getContext('2d');//畫圖的方法和屬性放在了這里

canT.fillStyle='#f40';

canT.fillRect(10,10,100,100);

canT.strokeStyle='#f40';繪制填充矩形要先設(shè)置樣式,再繪制

canT.strokeRect(150,10,100,100);

效果圖:


b 繪圖環(huán)境.lineWidth ='數(shù)值'

var can = document.getElementById('can');

var canT = can.getContext('2d');

canT.fillStyle='#f40';

canT.fillRect(10,10,100,100);

canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前

canT.strokeStyle='#f40';//線條顏色,設(shè)置在繪圖前

canT.strokeRect(150,10,100,100);

三、邊界繪制

lineJoin: 邊界連接點樣式? 設(shè)置在繪圖前

----miter? [?ma?t?r]? [?ma?t?(r)] 默認(rèn),round(圓角),bevel [?bevl]? [?bevl](斜角)

? canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前

? canT.strokeStyle='#f40';

? canT.lineJoin='round';//圓角,設(shè)置在繪圖前

? canT.strokeRect(150,10,100,100);

效果圖:


canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前

canT.strokeStyle='#f40';

canT.lineJoin='bevel';//斜角角設(shè)置在繪圖前

canT.strokeRect(150,10,100,100);

效果圖:


四、繪制路徑

beginPath(): 開啟一條新路徑

closePath(): 閉合當(dāng)前路徑

moveTo(x,y): 定義線條開始坐標(biāo)

lineTo(x,y): 定義線條結(jié)束坐標(biāo)

stroke(): 畫線,默認(rèn)黑色

? canT.beginPath();//開啟一條新路徑

? canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前

? canT.moveTo(300,100);//定義線條開始坐標(biāo)

? canT.lineTo(400,200);//定義線條結(jié)束坐標(biāo)

? canT.stroke();// 畫線,默認(rèn)黑色

效果圖:


lineCap: 端點樣式

----butt(默認(rèn)), round(圓角),square

fill(): 填充,默認(rèn)黑色

rect(): 矩形區(qū)域(x,y,w,h)

clearRect(x,y,width,height) 方法清空給定矩形內(nèi)的指定像素。

lineCap: 端點樣式

----butt(默認(rèn)), round(圓角),square

? canT.beginPath();//開啟一條新路徑

? canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前

? canT.moveTo(300,100);//定義線條開始坐標(biāo)

? canT.lineTo(400,200);//定義線條結(jié)束坐標(biāo)

? canT.lineCap = 'round';//端點圓角

? canT.stroke();// 畫線,默認(rèn)黑色


canT.beginPath();//開啟一條新路徑

canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前

canT.moveTo(300,100);//定義線條開始坐標(biāo)

canT.lineTo(400,200);//定義線條結(jié)束坐標(biāo)

canT.lineCap = 'square';//增加原長度的1/2分到兩端

canT.stroke();// 畫線,默認(rèn)黑色

效果圖:


canT.beginPath();//開啟一條新路徑

canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前? ? ?

canT.moveTo(300,100);//定義線條開始坐標(biāo)

canT.lineTo(400,200);//定義線條結(jié)束坐標(biāo)

canT.lineCap = 'square';//增加元長度的1/2分到兩端

canT.strokeStyle = 'red';//設(shè)置顏色

canT.fill();//填充顏色

canT.stroke();// 畫線,默認(rèn)黑色

效果圖:


fill() 填充顏色

在用moveTo() lineTo()方法畫矩形時填充顏色使用,必須先設(shè)置顏色,fillStyle='顏色',再用fill()填充

? ? canT.beginPath();//開啟一條新路徑

? ? canT.lineWidth = '30';//線條寬度,設(shè)置在繪圖前? ? ?

? ? canT.moveTo(100,100);//定義線條開始坐標(biāo)

? ? canT.lineTo(200,100);//定義線條結(jié)束坐標(biāo)

? ? canT.lineTo(200,200);

? ? canT.lineTo(100,200);

? ? canT.closePath();

? ? canT.lineCap = 'square';

? ? canT.fillStyle = 'red';//設(shè)置要填充的顏色

? canT.fill();//填充?

? canT.stroke();// 畫線,默認(rèn)黑色

效果圖:


rect(): 矩形區(qū)域(x,y,w,h)

clearRect(x,y,width,height) 方法清空給定矩形內(nèi)的指

定像素。


canT.clearRect(0,0,150,160);

x: 要清除的矩形左上角的 x 坐標(biāo)

y:要清除的矩形左上角的 y 坐標(biāo)

width: 要清除的矩形的寬度

height: 要清除的矩形的高度


? ? ? // 畫矩形方法三:

? ? ? ? // cxt.beginPath();

? ? ? ? // cxt.rect(50,50,100,100);

? ? ? ? // cxt.fillStyle = 'red';

? ? ? ? // cxt.fill();

五.畫圓

arc(x,y,r,起始弧度,終止弧度,方向)

x/y: 圓心的坐標(biāo) 定義圓的位置

r:圓的半徑 定義圓的大小

弧度:Math.PI/180(一角度的弧度)

角度與弧度的轉(zhuǎn)換關(guān)系: 角度*Math.PI/180

方向:順時針(false 默認(rèn)值),逆時針(true)

canvas中畫圓起始位置為三點鐘方向 六點鐘方向為90度,九點鐘方向是+-180度,12點鐘方向為-90度

示意圖:


案例一:

cxt.arc(100,100,100 ,0,360*Math.PI/180,true);

cxt.stroke();

效果圖:


案例二:

90度扇形

? ? ? ? cxt.moveTo(100,100);

? ? ? ? cxt.arc(100,100,100 ,0,90*Math.PI/180,false);

? ? ? ? cxt.closePath();

? ? ? ? cxt.stroke();

效果圖


? ? ? ? cxt.moveTo(100,100);

? ? ? ? cxt.arc(100,100,100 ,0,90*Math.PI/180,true);

? ? ? ? cxt.closePath();

? ? ? ? cxt.stroke();


案例三

移動的方塊

? ? num = 0;

? style = 100;

? setInterval(function(){

? cxt.clearRect(0,0,oc.width,oc.height);

? num ++; //改變位置

? style ++; //改變大小

? cxt.fillRect(num,num,style,style);

},100)



案例四:

畫扇形

120度? 設(shè)置描邊樣式,填充顏色樣式

cxt.moveTo(15,15,);

cxt.arc(150,150,150,0,120*Math.PI/180,false);

cxt.strokeStyle = '#f40';//設(shè)置描邊樣式

cxt.fillStyle = 'red';//填充顏色樣式

cxt.fill();//填充 填充顏色樣式

cxt.closePath();

cxt.stroke();


案例五:

canvasOnload

? ? var oc = document.getElementById('c1');

? ? var cxt = oc.getContext('2d');

? ? var num = 0;//定義變量

? ? var timer = setInterval(function(){

? ? cxt.clearRect(0,0,oc.width,oc.height);

? ? num+=10;//定義變化的角度 步頻

? ? cxt.beginPath();//開始新路徑

? ? cxt.lineWidth = '6';//線寬

? ? cxt.strokeStyle ='#ccc';

? ? ? ? ? ? ? ? ? ? ? ? //起始弧度? ? ? ? ? ? //終止弧度

? ? cxt.arc(100,100,50,-90*Math.PI/180,(num+-90)*Math.PI/180,false);

? ? cxt.stroke();

? ? if(num>360){

? ? ? ? //當(dāng)圓環(huán)閉合時,清除定時器

? ? ? ? clearInterval(timer);

? ? }

? ? },50)

效果圖:


變換(平移 旋轉(zhuǎn) 縮放)

translate(x,y):

平移 可以重新定義畫布的(0,0)位置

默認(rèn)畫布(0,0)位置在畫布左上角

參數(shù):

x/y:x/y軸的偏移量

? ctx.fillRect(0,0,200,150);//未平移前

? ctx.translate(200,150);

? ctx.fillRect(0,0,200,150);


rotate(rad);

旋轉(zhuǎn)當(dāng)前圖形?

旋轉(zhuǎn)的參考角度為畫布的(0,0)位置

角度:angle

弧度:radian

參數(shù):

deg:旋轉(zhuǎn)角度 弧度計

弧度= 角度*Math.PI/180

ctx.rotate(45*Math.PI/180);//旋轉(zhuǎn) 寫在繪制圖形前面

ctx.fillRect(0,0,100,50);


? ctx.fillRect(0,0,100,50);

? ctx.translate(200,150);//圖形的起始位置平移至(200,150)位置

? ctx.fillRect(0,0,100,50);


ctx.rotate(45*Math.PI/180);

ctx.fillRect(0,0,100,50);

ctx.translate(200,150);//圖形的起始位置平移至(200,150)位置

ctx.fillRect(0,0,100,50);


以物體中心旋轉(zhuǎn)

ctx.translate(50,25);//設(shè)位移量為寬高一半

ctx.rotate(45*Math.PI/180);

ctx.fillRect(-50,-25,100,50);//設(shè)填充點為寬高的-(1/2)


案例:

方塊旋轉(zhuǎn)

save(): 保存路徑

restore(): 恢復(fù)路徑

save()和restore(): 兩個配對使用,save方法用于臨時保存畫布的坐標(biāo)系統(tǒng)的狀態(tài);restore方法用來恢復(fù)save之后保存的狀態(tài)。可以簡單的理解為,save之后的一系列的操作,比如translate和rotate等,在restore后,都會被釋放恢復(fù)到原來的狀態(tài)。

var num =0;

ctx.translate(200,200);//定義畫布的起始(0,0)位置

var timer = setInterval(function(){

ctx.clearRect(-160,-160,oc.width,oc.height);//注意清除區(qū)域值

ctx.save();//保存路徑

num+=10;

ctx.rotate(num*Math.PI/180);

ctx.fillRect(-100,-100,200,200);

ctx.restore();//恢復(fù)路徑

},1000)


scale(x,y)放大

參數(shù):

x:代表水平放大的倍數(shù)

y:代表垂直放大的倍數(shù)

scale(1,1),默認(rèn)

scale(2,2)放大一倍

scale(0.5,0.5)縮小一半

案例

畫鐘表

第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

function toDrow(){

// 第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

// cxt.moveTo(200,200);

// cxt.arc(200,200,150,0,6*Math.PI/180,false);

// 整個鐘表一共360度,需要進(jìn)行60次,用循環(huán)

? ? for(var i = 0; i < 60; i ++){

? ? cxt.moveTo(200,200);

? ? cxt.arc(200,200,150,i*6*Math.PI/180,(i+1)*6*Math.PI/180,false);

? ? cxt.stroke();

? ? //此時 將出現(xiàn)一個圓盤上出現(xiàn)60個閉合的扇形角度為6度

? ? ? ? }

? ? ? ? }

toDrow();

效果圖


function toDrow(){

// 第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

? // cxt.moveTo(200,200);

? // cxt.arc(200,200,150,0,6*Math.PI/180,false);

? // 整個鐘表一共360度,需要進(jìn)行60次,用循環(huán)

? ? cxt.beginPath();

? ? for(var i = 0; i < 60; i ++){

? ? ? cxt.moveTo(200,200);

? ? cxt.arc(200,200,150,i*6*Math.PI/180,(i+1)*6*Math.PI/180,false);

? ? cxt.stroke();

? ? cxt.closePath();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)60個閉合的扇形角度為6度

? ? }

//第二步:畫遮罩層

? // 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,

//半徑小于原刻盤,制造出時中刻度的假象

? ? ? cxt.beginPath();

? ? ? cxt.fillStyle = '#fff';

? ? ? cxt.arc(200,200,140,0,360*Math.PI/180,false);

? ? ? cxt.fill();

? ? ? cxt.closePath();

}

效果圖:


function toDrow(){

// 第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

? // cxt.moveTo(200,200);

? // cxt.arc(200,200,150,0,6*Math.PI/180,false);

? // 整個鐘表一共360度,需要進(jìn)行60次,用循環(huán)

? ? cxt.beginPath();

? ? for(var i = 0; i < 60; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.arc(200,200,150,i*6*Math.PI/180,(i+1)*6*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)60個閉合的扇形角度為6度

? ? }

? ? cxt.beginPath();

//第二步:畫遮罩層

? // 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,半徑小于原刻盤,

//制造出時中刻度的假象

? ? ? cxt.beginPath();

? ? ? cxt.fillStyle = '#fff';

? ? ? cxt.arc(200,200,140,0,360*Math.PI/180,false);

? ? ? cxt.fill();

? ? ? cxt.closePath();

//? ? 第三步:畫時針刻度

? ? // 同分鐘,整個表盤的分鐘刻度也是360度,分12個,每個刻度為30

? ? // 一共有12個30度

? ? cxt.beginPath();

? ? for(var i = 0; i? < 12; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.lineWidth = 3;

? ? ? cxt.arc(200,200,150,i*30*Math.PI/180,(i+1)*30*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)12個閉合的扇形角度為30度? 線寬為3

? ? ? ? }

? ? ? ? cxt.closePath();

? ? ? ? }

toDrow();


function toDrow(){

// 第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

? // cxt.moveTo(200,200);

? // cxt.arc(200,200,150,0,6*Math.PI/180,false);

? // 整個鐘表一共360度,需要進(jìn)行60次,用循環(huán)

? ? cxt.beginPath();

? ? for(var i = 0; i < 60; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.arc(200,200,150,i*6*Math.PI/180,(i+1)*6*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)60個閉合的扇形角度為6度

? ? }

? ? cxt.beginPath();

//第二步:畫遮罩層

? // 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,半徑小于原刻盤,

//制造出時中刻度的假象

? ? ? cxt.beginPath();

? ? ? cxt.fillStyle = '#fff';

? ? ? cxt.arc(200,200,140,0,360*Math.PI/180,false);

? ? ? cxt.fill();

? ? ? cxt.closePath();

//? ? 第三步:畫時針刻度

? ? // 同分鐘,整個表盤的分鐘刻度也是360度,分12個,每個刻度為30

? ? // 一共有12個30度

? ? cxt.beginPath();

? ? for(var i = 0; i? < 12; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.lineWidth = 3;

? ? ? cxt.arc(200,200,150,i*30*Math.PI/180,(i+1)*30*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)12個閉合的扇形角度為30度? 線寬為3

? ? ? ? }

? ? ? ? cxt.closePath();

? ? ? ? }

// 第四步:畫遮罩層

? ? //? 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,

? ? //? 半徑小于分鐘/秒鐘(原)遮罩層,制造出時中刻度的假象


? ? ? ? ? ? cxt.beginPath();

? ? ? ? ? ? cxt.fillStyle = '#fff';

? ? ? ? ? ? cxt.arc(200,200,130,0,360*Math.PI/180,false);

? ? ? ? ? ? cxt.fill();

? ? ? ? ? ? cxt.closePath();

? ? ? ? }

? ? ? ? toDrow();

效果圖:


? 第五步:畫時針分針秒針(行動軌跡)

? 圓心相同 半徑不同 ,起始弧度和終止弧度相等

起始弧度與終止弧度的值有時間軸來決定

function toDrow(){

// 第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

? // cxt.moveTo(200,200);

? // cxt.arc(200,200,150,0,6*Math.PI/180,false);

? // 整個鐘表一共360度,需要進(jìn)行60次,用循環(huán)

? ? cxt.beginPath();

? ? for(var i = 0; i < 60; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.arc(200,200,150,i*6*Math.PI/180,(i+1)*6*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)60個閉合的扇形角度為6度

? ? }

? ? cxt.beginPath();

//第二步:畫遮罩層

? // 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,半徑小于原刻盤,

//制造出時中刻度的假象

? ? ? cxt.beginPath();

? ? ? cxt.fillStyle = '#fff';

? ? ? cxt.arc(200,200,140,0,360*Math.PI/180,false);

? ? ? cxt.fill();

? ? ? cxt.closePath();

//? ? 第三步:畫時針刻度

? ? // 同分鐘,整個表盤的分鐘刻度也是360度,分12個,每個刻度為30

? ? // 一共有12個30度

? ? cxt.beginPath();

? ? for(var i = 0; i? < 12; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.lineWidth = 3;

? ? ? cxt.arc(200,200,150,i*30*Math.PI/180,(i+1)*30*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)12個閉合的扇形角度為30度? 線寬為3

? ? ? ? }

? ? ? ? cxt.closePath();

? ? ? ? }

// 第四步:畫遮罩層

? ? //? 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,

? ? //? 半徑小于分鐘/秒鐘(原)遮罩層,制造出時中刻度的假象


? ? ? ? ? ? cxt.beginPath();

? ? ? ? ? ? cxt.fillStyle = '#fff';

? ? ? ? ? ? cxt.arc(200,200,130,0,360*Math.PI/180,false);

? ? ? ? ? ? cxt.fill();

? ? ? ? ? ? cxt.closePath();

? ? ? ? ? ? // 第五步:畫時針分針秒針(行動軌跡)

? ? ? ? // 圓心相同 半徑不同 ,起始弧度和終止弧度相等

? ? ? ? // 起始弧度與終止弧度的值有時間軸來決定

? ? ? ? ? ? // cxt.moveTo(200,200);

? ? ? ? ? ? // cxt.arc(200,200,150*0.5,起始弧度,終止弧度,false);

? ? ? ? ? ? // cxt.stroke();

? ? ? ? ? ? // 時針:最短最粗,

? ? ? ? cxt.beginPath();

? ? ? ? cxt.moveTo(200,200);

? ? ? ? cxt.lineWidth =4;

? ? ? ? cxt.arc(200,200,150*0.5,1,1,false);

? ? ? ? cxt.stroke();

? ? ? ? cxt.closePath();

? ? ? ? //? ? 畫分針

? ? cxt.beginPath();

? ? cxt.moveTo(200,200);

? ? cxt.lineWidth =3;

? ? cxt.arc(200,200,150*0.7,3,3,false);

? ? cxt.stroke();

? ? cxt.closePath();

? ? ? ? }

? ? ? ? toDrow();

效果圖:


// 第六步:

設(shè)置在前邊

// 想要讓時分秒的顯示和真實時間一致

// a:分別時間的時分秒

// B:讓時分秒針的位置同一

// c:將函數(shù)放入定時器,每1000ms執(zhí)行一次

// 當(dāng)時間不為整點時,時針在兩個數(shù)之間,此時需要將時針的位置加上偏移量

var timer = new Date();

ar tH = timer.getHours();//獲取小時

var tM = timer.getMinutes();//獲取分鐘

var tS = timer.getSeconds();//獲取秒

// 時針轉(zhuǎn)弧度

// a: 每一個格代表30度,時鐘和canvas的起始弧度相差90度,

// b: 當(dāng)時間不為整點時需將偏移量加上

// eg:10:30分,時針在10-11正中間,一個格式2,判斷分鐘里有幾個2

var tHVal = (30*tH-90+tM/2)*Math.PI/180;

// 分針轉(zhuǎn)弧度

// 每一個格代表6度,時鐘和canvas的起始弧度相差90度,

var tMVal =(6*tM-90)*Math.PI/180;

// 秒針轉(zhuǎn)弧度

//? 每一個格代表6度,時鐘和canvas的起始弧度相差90度,

var tSVal =(6*tS-90)*Math.PI/180;

//? 第七步:

// 將時分秒的弧度值替換

function toDrow(){

// 第六步:

// 想要讓時分秒的顯示和真實時間一致

// a:分別時間的時分秒

// B:讓時分秒針的位置同一

// c:將函數(shù)放入定時器,每1000ms執(zhí)行一次

// 當(dāng)時間不為整點時,時針在兩個數(shù)之間,此時需要將時針的位置加上偏移量

? var timer = new Date();

? var tH = timer.getHours();//獲取小時

? var tM = timer.getMinutes();//獲取分鐘

? var tS = timer.getSeconds();//獲取秒

// 將時分秒轉(zhuǎn)換為弧度

// 時針轉(zhuǎn)弧度

// a: 每一個格代表30度,時鐘和canvas的起始弧度相差90度,

// b: 當(dāng)時間不為整點時需將偏移量加上

// eg:10:30分,時針在10-11正中間,一個格式2,判斷分鐘里有幾個2

? var tHVal = (30*tH-90+tM/2)*Math.PI/180;

// 分針轉(zhuǎn)弧度

? // 每一個格代表6度,時鐘和canvas的起始弧度相差90度,

? ? var tMVal =(6*tM-90)*Math.PI/180;

// 秒針轉(zhuǎn)弧度

//? 每一個格代表6度,時鐘和canvas的起始弧度相差90度,

? ? var tSVal =(6*tS-90)*Math.PI/180;

//? 第七步:

? // 將時分秒的弧度值替換

// 第一步:畫出60個小格子代表分針/秒針刻度,每個刻度之間是6度

? // cxt.moveTo(200,200);

? // cxt.arc(200,200,150,0,6*Math.PI/180,false);

? // 整個鐘表一共360度,需要進(jìn)行60次,用循環(huán)

? ? cxt.beginPath();

? ? for(var i = 0; i < 60; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.arc(200,200,150,i*6*Math.PI/180,(i+1)*6*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)60個閉合的扇形角度為6度

? ? }

? ? cxt.beginPath();

//第二步:畫遮罩層

? // 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,半徑小于原刻盤,

//制造出時中刻度的假象

? ? ? cxt.beginPath();

? ? ? cxt.fillStyle = '#fff';

? ? ? cxt.arc(200,200,140,0,360*Math.PI/180,false);

? ? ? cxt.fill();

? ? ? cxt.closePath();

//? ? 第三步:畫時針刻度

? ? // 同分鐘,整個表盤的分鐘刻度也是360度,分12個,每個刻度為30

? ? // 一共有12個30度

? ? cxt.beginPath();

? ? for(var i = 0; i? < 12; i ++){

? ? ? cxt.moveTo(200,200);

? ? ? cxt.lineWidth = 3;

? ? ? cxt.arc(200,200,150,i*30*Math.PI/180,(i+1)*30*Math.PI/180,false);

? ? ? cxt.stroke();

//此時 將出現(xiàn)一個圓盤上出現(xiàn)12個閉合的扇形角度為30度? 線寬為3

? ? ? ? }

? ? ? ? cxt.closePath();

? ? ? ? }

// 第四步:畫遮罩層

? ? //? 用一個圓覆蓋到之前畫出分鐘/秒鐘刻度盤上,圓心相同,

? ? //? 半徑小于分鐘/秒鐘(原)遮罩層,制造出時中刻度的假象


? ? ? ? ? ? cxt.beginPath();

? ? ? ? ? ? cxt.fillStyle = '#fff';

? ? ? ? ? ? cxt.arc(200,200,130,0,360*Math.PI/180,false);

? ? ? ? ? ? cxt.fill();

? ? ? ? ? ? cxt.closePath();

? ? ? ? ? ? // 第五步:畫時針分針秒針(行動軌跡)

? ? ? ? // 圓心相同 半徑不同 ,起始弧度和終止弧度相等

? ? ? ? // 起始弧度與終止弧度的值有時間軸來決定

? ? ? ? ? ? // cxt.moveTo(200,200);

? ? ? ? ? ? // cxt.arc(200,200,150*0.5,起始弧度,終止弧度,false);

? ? ? ? ? ? // cxt.stroke();

? ? ? ? ? ? // 時針:最短最粗,

? ? ? ? cxt.beginPath();

? ? ? ? cxt.moveTo(200,200);

? ? ? ? cxt.lineWidth =4;

? ? ? ? cxt.arc(200,200,150*0.5,tHVal,tHVal,false);

? ? ? ? cxt.stroke();

? ? ? ? cxt.closePath();

? ? ? ? //? ? 畫分針

? ? cxt.beginPath();

? ? cxt.moveTo(200,200);

? ? cxt.lineWidth =3;

? ? cxt.arc(200,200,150*0.7,tMVal,tMVal,false);

? ? cxt.stroke();

? ? cxt.closePath();

? ? //? ? 畫秒針

? ? cxt.beginPath();

? ? cxt.moveTo(200,200);

? ? cxt.lineWidth =2;

? ? cxt.arc(200,200,150*0.7,tSVal,tSVal,false);

? ? cxt.stroke();

? ? cxt.closePath();

? ? ? ? }

? ? ? ? toDrow();

? ? ? ? //定時器

etInterval(toDrow,1000);

插入圖片

cxt.drawImage(obj,x,y)

參數(shù):

三個參數(shù)

1.obj:要插入的圖片對象

2.x/y:代表插入圖片在畫布上的位置(x,y)

語法:

cxt.drawImage(obj,x,y)

五個參數(shù)的是時候

cxt.drawImage(obj,x,y,w,h)

w/h:代表在畫布上定位圖片并設(shè)置照片的大小

不設(shè)置寬高,默認(rèn)為圖片自身寬高

九個參數(shù)代表

? ? ? cxt.drawImage(obj,sx,sy,sw,sh,x,y,w,h)

sx/sy: 要剪切圖片的位置

sw/sh:剪切的大小

x/y:在畫布的位置

w/h:圖片的大小

createPattern(obj,是否重復(fù)):設(shè)置背景

? repeat:默認(rèn)重復(fù)

? repeat-x:x軸重復(fù)

? repeat-y:y軸重復(fù)

? no-repeat:不重復(fù)

window.onload = function(){

? ? ? ? ? ? var oC = document.getElementById('c1');

? ? ? ? ? ? var cxt = oC.getContext('2d');

? ? ? ? ? ? //創(chuàng)建圖片對象

? ? ? ? ? ? var oImg = new Image();

? ? ? ? ? ? //圖片路徑

? ? ? ? ? ? oImg .src = 'img/life.jpg';

? ? ? ? ? ? //當(dāng)圖片加載完成以后執(zhí)行操作

? ? ? ? ? ? oImg.onload = function(){

? ? ? ? ? ? ? ? //圖片插入canvas畫布中

? ? ? ? ? ? ? ? cxt.drawImage(oImg,50,80)

? ? ? ? ? ? }

? ? ? ? }

效果


平鋪:

window.onload = function(){

? ? ? ? ? ? var oC = document.getElementById('c1');

? ? ? ? ? ? var cxt = oC.getContext('2d');

? ? ? ? ? ? //創(chuàng)建圖片對象

? ? ? ? ? ? var oImg = new Image();

? ? ? ? ? ? //圖片路徑

? ? ? ? ? ? oImg .src = 'img/life.jpg';

? ? ? ? ? ? //當(dāng)圖片加載完成以后執(zhí)行操作

? ? ? ? ? ? oImg.onload = function(){

? ? ? ? ? ? ? ? //圖片插入canvas畫布中

? ? ? ? ? ? ? ? cxt.drawImage(oImg,0,0);

? ? ? ? ? ? ? ? var bg = cxt.createPattern(oImg,'repeat');

? ? ? ? ? ? ? ? //createPattern(obj,是否重復(fù)):設(shè)置背景

? ? ? ? ? ? ? ? ? //repeat:默認(rèn)重復(fù)

? ? ? ? ? ? ? ? ? //repeat-x:x軸重復(fù)

? ? ? ? ? ? ? ? ? // repeat-y:y軸重復(fù)

? ? ? ? ? ? ? ? ? // no-repeat:不重復(fù)

? ? ? ? ? ? ? cxt.fillStyle = bg;

? ? ? ? ? ? ? cxt.fillRect(0,0,oC.width,oC.height);

? ? ? ? ? ? }

? ? ? ? }

效果:


剪裁:(剪裁圖片不能設(shè)置平鋪效果

window.onload = function(){

? ? ? ? ? ? var oC = document.getElementById('c1');

? ? ? ? ? ? var cxt = oC.getContext('2d');

? ? ? ? ? ? //創(chuàng)建圖片對象

? ? ? ? ? ? var oImg = new Image();

? ? ? ? ? ? //圖片路徑

? ? ? ? ? ? oImg .src = 'img/life.jpg';

? ? ? ? ? ? //當(dāng)圖片加載完成以后執(zhí)行操作

? ? ? ? ? ? oImg.onload = function(){

? ? ? ? ? ? ? ? //圖片插入canvas畫布中

? ? ? ? ? ? ? ? //cxt.drawImage(obj,sx,sy,sw,sh,x,y,w,h)

? ? ? ? ? ? ? ? //sx/sy: 要剪切圖片的位置

? ? ? ? ? ? ? ? //sw/sh:剪切的大小,這個區(qū)域的圖片舍棄

? ? ? ? ? ? ? ? //x/y:在畫布的位置

? ? ? ? ? ? ? ? // w/h:圖片的大小

? ? ? ? ? ? ? ? cxt.drawImage(oImg,30,50,100,200,200,100,200,200);


? ? ? ? ? ? }

? ? ? ? }

效果:


案例:

圖片旋轉(zhuǎn):

分析:

第一步:

向畫布插入圖片

var oImg = new Image();//調(diào)用方法

oImg.src = "img/life.jpg";//圖片路徑

//設(shè)置canvas畫布與圖片大小一致

? oImg.onload = function() {//圖片預(yù)加載,當(dāng)圖片加載完成再執(zhí)行canvas

? ? ? ? ? ? cxt.drawImage(oImg,0,0,500,300);

? ? ? ? }

第二步:

設(shè)置旋轉(zhuǎn)角度

window.onload = function(){

????????var aInput = document.getElementsByTagName

? ? ? ? ("input");

? ? ? ? var oC = document.getElementById("c1");

? ? ? ? var cxt = oC.getContext("2d");

????????var? i = 0;

? ? ? ? var iNow = 0;

? ? ? ? // 向畫布插入圖片

? ? ? ? var oImg = new Image();

? ? ? ? oImg.src = "img/life.jpg";

? ? ? ? oImg.onload = function() {

? ? ? ? ? ? cxt.drawImage(oImg,0,0,500,300);

? ? ? ? }

????????// switch? 語句開始

? ? ? ? aInput[0].onclick = function() {

? ? ? ? ? ? if(iNow==0) {

? ? ? ? ? ? ? ? iNow = 3;

? ? ? ? ? ? }

? ? ? ? ? ? else {

? ? ? ? ? ? ? ? iNow--;

? ? ? ? ? ? }

? ? ? ? ? toRotate();

? ? ? ? }

? ? ? ? aInput[1].onclick = function() {

? ? ? ? ? ? // 執(zhí)行順時針旋轉(zhuǎn)圖片

? ? ? ? ? ? // 當(dāng)i= 1 第一次旋轉(zhuǎn) 旋轉(zhuǎn)90度

? ? ? ? ? ? if(iNow==3) {

? ? ? ? ? ? ? ? iNow = 0;

? ? ? ? ? ? }

? ? ? ? ? ? else {

? ? ? ? ? ? ? ? iNow++;

? ? ? ? ? ? }

? ? ? ? ? toRotate();

? ? ? ? }

? ? ? ? function toRotate() {

? ? ? ? ? ? switch(iNow) {

? ? ? ? ? ? ? ? case 1:

? ? ? ? ? ? ? ? ? ? oC.width = oImg.height;

? ? ? ? ? ? ? ? ? ? oC.height = oImg.width;

? ? ? ? ? ? ? ? ? ? cxt.rotate(90*Math.PI/180);

? ? ? ? ? ? ? ? ? ? cxt.drawImage(oImg,0,-oImg.height);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? case 2:

? ? ? ? ? ? ? ? ? ? oC.width = oImg.width;

? ? ? ? ? ? ? ? ? ? oC.height = oImg.height;

? ? ? ? ? ? ? ? ? ? cxt.rotate(180*Math.PI/180);

? ? ? ? ? ? ? ? ? ? cxt.drawImage(oImg,-oImg.width,-oImg.height);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? case 3:

? ? ? ? ? ? ? ? ? ? oC.width = oImg.height;

? ? ? ? ? ? ? ? ? ? oC.height = oImg.width;

? ? ? ? ? ? ? ? ? ? cxt.rotate(270*Math.PI/180);

? ? ? ? ? ? ? ? ? ? cxt.drawImage(oImg,-oImg.width,0);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? case 0:

? ? ? ? ? ? ? ? ? ? oC.width = oImg.width;

? ? ? ? ? ? ? ? ? ? oC.height = oImg.height;

? ? ? ? ? ? ? ? ? ? cxt.rotate(0*Math.PI/180);

? ? ? ? ? ? ? ? ? ? cxt.drawImage(oImg,0,0);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }


? ? ? ? }

漸變

A: 創(chuàng)建線性漸變

creatLinearGradient(x1,y1,x2,y2)

? 參數(shù)

? x1:起始坐標(biāo)x軸

? y1:起始坐標(biāo)y軸

? x2: 終止坐標(biāo)x軸

? y2:終止坐標(biāo)y軸

? 給漸變對象添加顏色 addColorStop()

? ? 接收兩個參數(shù)

? ? 第一個參數(shù) 規(guī)定漸變的位置

? ? 第二個參數(shù) 漸變的顏色

? ? 語法: addColorStop(0,'red');

// A實例

? ? ? ? //創(chuàng)建漸變對象

? ? ? ? var grad = cxt.createLinearGradient(100,100,300,300);

? ? ? ? // 給漸變對象添加顏色

? ? ? ? grad.addColorStop(0,'#f00');

? ? ? ? grad.addColorStop(0.3,'#e12');

? ? ? ? grad.addColorStop(1,'#f1e');

? ? ? ? // 將漸變對象賦值給fillStyle并創(chuàng)建一圖形

? ? ? ? cxt.fillStyle = grad;

? ? ? ? cxt.fillRect(0,0,oC.width,oC.height);

效果:


B:創(chuàng)建徑向漸變? createRadialGradient(x1,y1,r1,x2,y2,r2) x1/y1:起始位置坐標(biāo)

x2/y2:結(jié)束位置坐標(biāo)

r1/r2: 開始結(jié)束的半徑

? ? // 創(chuàng)建一個徑向漸變

? ? var? grad = cxt.createRadialGradient(200,200,50,200,200,100) ;

? ? // 給徑向漸變對象添加顏色

? ? grad.addColorStop(0,'purple');

? ? grad.addColorStop(1,'blue');

? ? // 把樣式賦值給fillStyle

? ? cxt.fillStyle = grad;

? ? // 創(chuàng)建一個圖形

? ? cxt.fillRect(0,0,oC.width,oC.height);


文本

cxt.strokeText('文本內(nèi)容',x,y);

參數(shù):

x,y:文本位置坐標(biāo)

cxt.fillText('明天',200,300);

var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.fillText('明天',200,300);

效果;


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.fillStyle ='yellow';//字體顏色

cxt.fillText('明天',200,300);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.fillStyle ='yellow';

cxt.font = 'italic bold 100px? impact';//字體 傾斜加粗字號100px

cxt.fillText('明天',200,300);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.strokeText('你好',200,300);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.strokeStyle=‘orange';

cxt.strokeText('你好',200,300);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.strokeStyle=‘orange';

cxt.font = 'italic bold 100px? impact';//字體 傾斜加粗字號100px

cxt.strokeText('你好',200,300);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.strokeStyle='orange';

cxt.font = 'italic bold 100px? impact';//字體 傾斜加粗字號100px

cxt.strokeText('你好',100,100);

cxt.fillStyle ='yellow';

cxt.fillText('明天',200,300);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

var? grad = cxt.createLinearGradient(250,300,400,500);

grad.addColorStop(0,'#fc3');

? ? ? ? ? ? grad.addColorStop(0.3,'#12fc');

? ? ? ? ? ? grad.addColorStop(1,'#10fc');

? ? ? ? ? ? cxt.font = 'italic bold 100px? impact';

? ? ? ? ? ? cxt.fillStyle = grad;

? ? ? ? ? ? cxt.fillText('明天',200,300)

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.strokeStyle='orange';

cxt.font = 'italic bold 100px? impact';//字體 傾斜加粗字號100px

var? grad = cxt.createRadialGradient(100,100,100,150,150,200);

// 給徑向漸變對象添加顏色

grad.addColorStop(0,'#fc3');

grad.addColorStop(0.3,'#12fc');

grad.addColorStop(1,'#10fc');

cxt.strokeText('你好',100,100);

cxt.fillText('明天',200,300);

var? grad = cxt.createRadialGradient(100,100,100,150,150,200);

// 給徑向漸變對象添加顏色

grad.addColorStop(0,'#fc3');

grad.addColorStop(0.3,'#12fc');

grad.addColorStop(1,'#10fc');

// 把樣式賦值給fillStyle

cxt.strokeStyle = grad;

cxt.strokeText('你好',100,100);

效果:


陰影

創(chuàng)建陰影

cxt.shadowOffsetX:陰影x軸偏移量 ,

可以為負(fù)值,正值向右,負(fù)值向左偏移

cxt.shadowOffsetY:陰影x軸偏移量 ,

可以為負(fù)值,正值向下,負(fù)值向上偏移

cxt.shadowBlur:陰影的模糊值,值越大,

模糊度越強(qiáng)

cxt.shadowColor:陰影的顏色

var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

cxt.shadowOffsetX ='20';//陰影x軸偏移量

cxt.shadowOffsetY = '10'//陰影x軸偏移量

cxt.shadowBlur = '10';//陰影的模糊值

cxt.shadowColor ='red';//陰影的顏色

cxt.fillRect(100,100,100,100);

效果:


var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

var? grad = cxt.createRadialGradient(100,100,100,150,150,200);

// 給徑向漸變對象添加顏色

grad.addColorStop(0,'#fc3');

grad.addColorStop(0.3,'#12fc');

grad.addColorStop(1,'#10fc');

cxt.shadowOffsetX ='20';

cxt.shadowOffsetY = '10'

cxt.shadowBlur = '10';

cxt.shadowColor ='red'

// 把樣式賦值給fillStyle

cxt.strokeStyle = grad;

cxt.strokeText('你好',100,100);


像素:

oCxt.getImageData(x,y,w,h);

返回一個圖像對象,這個對象包含了這個圖像的像素信息

參數(shù):

x/y:獲取像素點的坐標(biāo)位置

w/h:獲取圖像的寬高

createImageData(w,h)創(chuàng)建圖像

參數(shù):

w:創(chuàng)建圖像的寬

h:創(chuàng)建圖像的高?

putImageData(imgData,x,y,w,h)將像素放入畫布中、

參數(shù):創(chuàng)建的像素

x/y:像素坐標(biāo)

w/h:像素大小

練習(xí):創(chuàng)建一個100*100的圖像 ,紅色,255,0,,0,255

? var oC = document.getElementById('c1');

? var oCxt = oC.getContext('2d');

? var imgData = oCxt.createImageData(100,100);

? for(var? i =0; i<imgData.data.length;i++){

// 把每個像素的四個值都要賦值成紅色對應(yīng)的rgba

? ? ? ? //rgba? 紅綠藍(lán)透明度 每4個值代表一個像素

? ? ? ? imgData.data[4*i]='255';

? ? ? ? imgData.data[4*i+1]='0';

? ? ? ? imgData.data[4*i+2]='0';

? ? ? ? imgData.data[4*i+3]='255';


? ? ? ? }

? ? ? ? //放入畫布

? oCxt.putImageData(imgData,200,200)

效果:


measure:

? measureText();

? 語法:mearsureText('測量的文本').wdith;

? ? ? ? 測量文本的寬度/密度

? ? ? ? 把文字水平居中的方式

? ? ? ? x軸坐標(biāo)(畫布的寬- 字體的寬)/2

練習(xí):將‘往后余生’水平居中

var oC = document.getElementById('c1');

var cxt = oC.getContext('2d');

var str? = '往后余生';

cxt.font ='bold 100px impact';

var cX = (oC.width - cxt.measureText(str).width)/2;

cxt.fillText(str,cX,100);

效果:


至此,canvas的一些知識也介紹的差不多了,中間有一些案例供大家參考,說的有些啰嗦,適合初學(xué)者,希望對大家有一些幫助吧!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 【Python基礎(chǔ)】條件語句 Python條件語句是通過一條或多條語句的執(zhí)行結(jié)果(True或者False)來決定執(zhí)...
  • 辯:買了百萬醫(yī)療保險,就可以不買重大疾病保險? 近兩年,隨著百萬醫(yī)療類保險的盛行,市場上開始出現(xiàn)這樣一種聲音,很多...
    侃爺說保險閱讀 228評論 0 1
  • 【日精進(jìn)打卡967天】 姓名:孫玉生 沈陽盛和商學(xué)院 六項精進(jìn)第177期學(xué)員(隊長),271期284期288期29...
    _玉_生_閱讀 305評論 0 2
  • 曾經(jīng)天人合一,知道萬物相依,何時失去天真,凡事總講道理。 原創(chuàng)作品 (Original Article)
    一詩一境界閱讀 312評論 0 0
  • 周星馳捧紅了一大批的女星,可以說香港的半個娛樂圈,都是周星馳撐起來的,像張柏芝、朱茵等,都是著名的“星女郎”。 周...
    漫娛小簡閱讀 381評論 0 0

友情鏈接更多精彩內(nèi)容