HTML5學習之Canvas基礎知識

  • canvas元素自己是沒有繪圖能力的,全部的繪製工做必須在 JavaScript 內部完成。
    var cv = document.getElementById("myCanvas");
    var context = cv.getContext("2d"); //申請一個繪製2d動畫的環境

  • 檢測瀏覽器是否支持:也能夠用js腳本檢查if(canvas.getContext)
    在不支持時能夠在canvas標籤文本中插入提示不支持信息。
    <canvas>hey!你如今的瀏覽器不支持canvas畫布哦!請更新瀏覽器。</canvas> 
    複製代碼

  • 常規繪製例子
  1. 用canvas繪製直線
    (a) context.moveTo(起點x,起點y)
    (b) context.lineTo(終點x,終點y):從moveTo提供的起點開始,到lineTo的座標繪製一條直線;若沒有moveTo,則lineTo至關於moveTo。若在一個lineTo後再增設lineTo,即從上一lineTo的座標開始向下一lineTo座標延伸直線。
    (c) context.stroke():延給定的座標畫一條直線,也能夠指定繪製直線的樣式,顏色粗細等。javascript

  2. 用canvas繪製矩形
    (a) context.fillStyle = "color":填充顏色
    (b) context.fillRect(起點x,起點y,寬,高):矩形起點和大小,或者繪製一個沒有填充顏色只有邊框的矩形 (a) context.strokeStyle = "color" :邊框顏色
    (b) context.strokeRect(起點x,起點y,寬,高) :只描邊不填充
    php

  3. 用canvas繪製圓形
    (a) context.fillStyle = "color";
    (b) context.beginPath():表示開始繪製
    (c) context.arc(圓心座標x,圓心座標y,半徑,開始角度,結束角度,是否爲按照給定的開始角度和結束角度的按順時針方向繪製)
    其中:開始角度爲0,結束角度爲0.5 PI(正下方),1 PI和1.5 PI(正上方),爲畫餅圖提供了扇形範圍的依據.第五個參數是弧長Math.PI*2就是整個圓,Math.PI是半圓
    (d) context.closePath():表示結束繪製,會將結束點和開始點經過一點直線連在一塊兒, 即將起點和終點封閉起來,有時能夠不要
    (e) context.fill():表示填充圖形,有時能夠用context.stroke()代替
    html

例子:html5

canvas-圓形.png
for(var i = 0;i<=15;i++){
		context.beginPath();
		context.arc(150,150,i*10,0,Math.PI*0.5,true); //在0開始,順時針Math.PI*0.5結束,即圓正下方結束
		context.stroke(); //不填充而只畫邊框
	}
複製代碼



canvas-圓形2.png
for(var i = 0;i<=15;i++){
		context.beginPath();
		context.arc(150,150,i*10,0,Math.PI*1,true);//在0開始,順時針Math.PI結束,即圓正下方半圓結束
		context.stroke(); //不填充而只畫邊框
	}
複製代碼



canvas-圓形3.png
for(var i = 0;i<=15;i++){
		context.beginPath();
		context.arc(150,150,i*10,0,Math.PI*1.5,true);//在0開始,順時針Math.PI*1.5結束,即圓正上方結束
		context.stroke(); //不填充而只畫邊框
	    }
複製代碼



canvas-圓形4.png
for(var i = 0;i<=15;i++){
		context.strokeStyle = "red"; //設置邊框顏色
		context.beginPath();
		context.arc(150,150,i*10,0,Math.PI*2,true);
		context.stroke(); //不填充而只畫邊框
	   }
複製代碼



  1. 用canvas繪製三角形
  • //空心三角形
canvas-三角形1.png
context.beginPath();  //開始繪製路徑
	context.moveTo(100,100); //起點座標設爲(100,100)
	context.lineTo(150,150); //下一點的座標設爲(150,150)
	context.lineTo(50,150); //下一點的座標設爲(50,150)
	context.closePath();//鏈接起點與終點
	context.stroke(); //繪畫線條
複製代碼

  • //實心三角形
canvas-三角形2.png
context.fillStyle = "red"; //設置填充顏色
	context.moveTo(150,50); //設置起點爲(150,50)
	context.lineTo(250,250);//下一點的座標設爲(150,150)
	context.lineTo(50,250);//下一點的座標設爲(50,150)
	context.fill(); //填充顏色,由於會整個圖像填充,因此能夠有closePath(),也能夠沒有
複製代碼

  • //清除畫布[或某部分]
canvas-三角形3.png
context.fillStyle = "red";
	context.moveTo(150,50);
	context.lineTo(250,250);
	context.lineTo(50,250);
	context.closePath();
	context.fill();
	
	var clearBtn = document.getElementById("clearCanvas");
	clearBtn.onclick=function(){
	context.clearRect(0,0,150,300); //清除某一部分畫布圖案
	//context.clearRect(起點x,起點y,畫布寬,畫布高);若寬高和整個畫布大小同樣即清除整個畫布
	};
複製代碼

  1. 繪製二次方貝塞爾曲線(quadraticCurveTo)
canvas-貝塞爾1.png
context.strokeStyle = "black"; //設置線條顏色
context.beginPath(); //開始繪製
context.moveTo(0,200); //定義開始點,從(0,200)開始繪製
//context.quadraticCurveTo(控制點x,控制點y,結束點x,結束點y),
//控制點爲與其與開始座標和結束座標連線的兩直線的交點 context.quadratciCurveTo(150,100,300,200);
context.stroke(); //繪製線條
context.globalCompositeOperation = "source-over";
//globalCompositeOperation 屬性通常用於圖形組合,設置如何將一個源(新)圖像繪製到目標(已有)的圖像上。 
//源圖像 = 您打算放置到畫布上的繪圖。目標圖像 = 您已經放置在畫布上的繪圖。
//源圖像:↓(二次貝塞爾曲線是根據直線部分畫出來的)
context.strokeStyle = "red";
context.beginPath();
context.moveTo(150,100);
context.lineTo(0,200);
context.moveTo(150,100);
context.lineTo(300,200);
context.stroke();	
複製代碼

  1. 繪製三次方貝塞爾曲線(bezierCurveTo
    參考理解:https://blog.csdn.net/cdnight/article/details/48468653
canvas-貝塞爾2.png
context.strokeStyle = "black";
context.beginPath();  //開始繪製
context.moveTo(0,200); //從(0,200)開始繪製
context.bezierCurveTo(25,50,75,50,300,200);
//context.bezierCurveTo(控制點1座標x,控制點1座標y,控制點2座標x,控制點2座標2,終點座標x,終點座標y)
context.bezierCurveTo(25,50,75,50,300,200);
context.stroke();
context.globalCompositeOperation = "source-over";

context.strokeStyle = "red";
context.beginPath();
//控制點1到開始點的直線
context.moveTo(25,50);
context.lineTo(0,200);
//控制點1到控制點2(三次貝塞爾曲線就是根據這條線畫出來的)
context.moveTo(25,50);
context.lineTo(75,50);
//控制點2到結束點直線
context.moveTo(75,50);
context.lineTo(300,200);
context.stroke();
複製代碼

  1. 畫布的圖像能夠按照當前狀態以堆stack的方式保存下來和按照上一次狀態恢復
    A. save::用來保存Canvas的狀態。save以後,能夠調用Canvas的平移、放縮、旋轉、錯切、裁剪等操做.

    B. restore:用來恢復Canvas以前保存的狀態。防止save後對Canvas執行的操做對後續的繪製有影響.
    注意:save表示保存save函數以前的狀態,restore表示獲取save保存的狀態java

    例子:canvas

//矩形一,填充色爲橙色,邊框爲紅色
	context.fillStyle = "orange";
	context.strokeStyle = "red";
	context.fillRect(20,20,100,100);
	context.strokeRect(20,20,100,100);
	context.fill();
	context.stroke();
	//保持當前canvas狀態
	context.save();
	
	//繪製矩形二,填充色爲黃色,邊框色爲粉紅色
	context.fillStyle="yellow";
	context.strokeStyle="pink";
	context.fillRect(150,20,100,100);
	context.strokeRect(150,20,100,100);
	context.fill();
	context.stroke();
	
	//恢復上一個矩形的狀態來進行繪畫
	// context.restore();
	context.fillRect(20,150,100,100);
	context.strokeRect(20,150,100,100);
複製代碼

無context.restore()時的畫面↓:保存的是最後一次繪畫樣式api

canvas-save1.png

有context.restore()時的畫面↓:保存的是context.save()的繪畫樣式瀏覽器

canvas-save2.png



8. 移動座標空間,繪製漸變傘效果
畫布默認左上角爲座標原點,向右爲x軸正向,向下爲y軸正向。座標空間的單位爲像素,在繪製圖像時,可使用translate來移動座標空間,使座標空間原點移動到指定位置。bash

例子:函數

canvas-umbrella.png
var canvasMethod = {
	drawTop:function(context,fillColor){
		context.fillStyle = fillColor;
		context.strokeStyle = fillColor;
		context.beginPath();
		//從座標0,0開始,畫一個半徑爲30像素的正半上方圓
		context.arc(0,0,30,0,Math.PI,true); 
		context.closePath();
		context.fill();
		context.save();//保存畫布當前狀態,移動位置,fillStyle,strokeStyle爲fillColor
	},

	drawStick:function(context){
		context.fillRect(-1.5,0,1,40);//繪製一個矩形,但這個矩形實際上是向左偏移1.5像素,寬爲1高爲40的一條直線,根據save的樣式進行填充
		context.beginPath();
		context.strokeStyle = "blue";
		context.arc(-5,40,4,Math.PI,Math.PI*2,true);//圓心爲(-5,40),半徑爲4,順從從PI到2PI的方向,畫的下半圓,即終點在(-1,40)
		context.restore();//採用save中的畫布樣式,即fillStyle,strokeStyle爲fillColor
		context.stroke();//根據save的樣式進行描邊
	},

	printUmbrella:function(){
		var context = document.getElementById("canvas1").getContext("2d");
		context.translate(80,80);//第一次移動座標原點到(80,80)
		//繪製十把傘
		for (var i = 0; i < 10; i++) {
			context.save();//保存畫布上一次狀態,移動位置,fillStyle,strokeStyle默認爲黑
			context.translate(60*i,0);//不斷改變座標原點,每次向右移60像素(圓的直徑)
			this.drawTop(context,"rgb("+(30*i)+","+(255-30*i)+",255)");//繪製半圓並改變填充色彩
			this.drawStick(context);//繪製雨傘柄
			context.restore();//採用畫布save的設置,移動位置,fillStyle,strokeStyle默認爲黑
	    }
	}
};

window.onload = function(){
	canvasMethod.printUmbrella();
}
複製代碼



9. 旋轉座標空間

利用rotate()方法指定一個角度,改變了畫布座標和Web瀏覽器中的Canvas元素的像素之間的映射,使得任意後續繪圖在畫布中都顯示爲旋轉的。但它並無旋轉Canvas元素自己。 只有一個參數,爲旋轉的角度。
接着上一個雨傘例子,改變canvasMethod.printUmbrella()方法。

canvas-umbrella2.png
printUmbrella:function(){
	var context = document.getElementById("canvas1").getContext("2d");
	context.translate(150,150);//第一次移動座標原點到(150,150)
	
	//繪製8把傘
	for (var i = 0; i < 8; i++) {
		context.save();//保存畫布上一次的移動狀態
		context.rotate(Math.PI*0.25*i); //2PI/8=0.25PI,每次旋轉0.25PI 
		context.translate(0,-100);//不斷改變座標原點,每次向上移100像素
		this.drawTop(context,"rgb("+(30*i)+","+(255-30*i)+",255)");//繪製半圓並改變填充色彩
		this.drawStick(context);//繪製雨傘柄
		context.restore();//採用畫布save的設置

	}
}
複製代碼



10. 縮放圖形

畫布經過scale()去改變canvas上下文對象(context)中橫縱方向的像素數目來改變圖形的大小。

接收兩個參數分別是x軸方向縮放倍數和y軸方向縮放倍數,都必須爲正數,若要比原來大則>1,比原來小則<1。
例如,傳遞一個值 2.0 和 0.5 將會致使繪圖路徑寬度變爲原來的兩倍,而高度變爲原來的 1/2。

例子:

canvas-scale1.png
function scaleCircle(context){
	context.translate(250,20);
	for (var i = 0; i < 80; i++) {
		context.save(); //保存上一次畫布的設置
		context.translate(30,30);//每次迭代新的原點都移動到上一次原座標的(30,30)
		context.scale(0.95,0.95);//每次迭代橫縱因子都縮小到原來的0.9倍
		context.rotate(Math.PI/12)//旋轉
		context.beginPath();//開始進行繪製
		// context.fillStyle = "red";
		// context.globalAlpha="0.4";//設置顏色透明度
		context.fillStyle= "rgba(155, 187, 89, 0.7)";
		context.arc(0,0,50,0,Math.PI*2,true);//繪製圓
		context.closePath();
		context.fill();
	}
}

window.onload = function(){
	scaleCircle(context);
}
複製代碼



11. 矩陣變換

引用了理解網站內容:http://jo2.org/html5-canvas-transform/

canvas上下文對象(context)每次產生一個圖像都會建立一個對應的矩陣對象,可直接對canvas變形矩陣做修改,可經過矩陣變換,使圖形產生移動、旋轉、切片、鏡像反射的效果。

那麼問題來了:圖形都有矩陣,那一個圖形的默認矩陣是什麼樣子的? 答案是:(1,0,0,1,0,0).

①爲何不全爲0?其中:一個圖形在沒有縮放,旋轉,位移什麼的時候,他也會有一個屬性會是1,就是縮放!由於在沒有縮放的狀況下,圖形的縮放實際上是原大小的1倍.因此,這個默認矩陣裏面纔會有兩個1. 因此參數位置1上的1,是表示x軸上的縮放,參數位置4上的1是表示y軸上的縮放!
即:縮放能夠根據:context.transform(scaleX,0,0,scaleY,0,0);來設置效果。

觸類旁通:
②根據圖形默認矩陣,知矩陣中的最後兩位參數就是表示位移距離的數字(在沒有位移的狀況下爲0)。 即:移動能夠根據:context.transform(scaleX,0,0,scaleY,transX,transY);來設置效果。

③那麼剩下的兩個數字(參數位置2,參數位置3)是否是表示旋轉呢? 不是,他們是表示斜切。什麼是斜切?把一個矩形的任一條邊用力一拉,變成平行四邊形,這就是斜切。 例子:

未進行斜切以前
ctx.arc(200,50,50,0,Math.PI*2) 
.fillRect(200,100,50,50)
.stroke()
複製代碼

斜切以後
ctx.transform(1,Math.tan(Math.PI/180*30),0,1,0,0)//矩形X軸產生了斜切效果
.arc(200,50,w/2,0,Math.PI*2)
.fillRect(200,100,50,50)
.stroke()
複製代碼

代碼中咱們能夠看到使用了一個tan函數,若是要用斜切,好比想斜切30度,那麼就必須用tan把30度包起來,x/y軸都是如此.

能夠理解爲圖形矩陣爲ctx.transform(scaleX,skewX,skewY,scaleY,transX,transY);
新座標x' = (scaleX)x + (skewY)y + transX
新座標y' = (skewX)x + (scaleY)y + transY

④那怎麼用transform實現圖形轉換呢?
旋轉的效果要斜切配合縮放實現的。
好比,其餘的都不變,只把圖形旋轉30度,代碼:

var deg = Math.PI/180;
ctx.transform(Math.cos(30*deg),Math.sin(30*deg),-Math.sin(30*deg),Math.cos(30*deg),0,0)
.arc(200,50,50,0,Math.PI*2)
.fillRect(200,100,50,50)
.stroke()
複製代碼

其中:

cos(30*deg),
sin(30*deg),
-sin(30*deg),
cos(30*deg)
複製代碼

在使用transform方法實現旋轉時,旋轉N度時,N*deg不變,只要記住對應位置的對應三角函數cos,sin,-sin,cos就行。
原博主傳授的記憶方法:CS-SC=初三-上牀,不要忘記負號.

注意:canvas也提供setTransform方法直接把矩陣設爲你傳給他的值,會清空前面全部的transform形成的效果。

一個簡單的應用例子:

canvas-transform2.png
context.translate(200,20);
for (var i = 0; i < 80; i++) {
	context.save();
	context.transform(0.95,0,0,0.95,30,30); //縮至0.95倍,移動至(30,30)
	context.rotate(Math.PI/12);
	context.beginPath();
	context.fillStyle = "red";
	context.globalAlpha="0.4";//設置顏色透明度	
	//其中能夠利用globalAlpha()爲設置透明度,也能夠利用fillStyle=rgva()設置透明度
	context.arc(0,0,50,0,Math.PI*2,true);
	// context.closePath();
	context.fill();		
}

context.setTransform(1,0,0,1,10,10); //清空以前的transform樣式,設置新的圖形位置
context.fillStyle = "yellow";
context.fillRect(0,0,50,50);
context.fill();
複製代碼



12. 圖形組合
默認狀況下,兩個圖形有重疊部分時,另一個圖形會將另外一個圖形覆蓋掉。
能夠經過globalCompositeOperation屬性設置。

懶得敲之屬性展現系列:

canvas-globalCompositeOperation1.png canvas-globalCompositeOperation2.png canvas-globalCompositeOperation3.png canvas-globalCompositeOperation4.png canvas-globalCompositeOperation5.png
  1. 裁切路徑
    使用clip(),:一旦剪切了某個區域,則全部以後的繪圖都會被限制在被剪切的區域內(不能訪問畫布上的其餘區域).
    或者能夠理解爲,在使用clip()以後,只看到clip以前信息,而clip以後的只能顯示在clip所選定的區域中的圖形部分,而其餘會被隱藏起來。

    參考理解網址:https://www.w3cplus.com/canvas/clip.html

  2. 應用不一樣的線型
    利用lineWidth、lineGap、lineJoin、miterLimit設置不一樣線形樣式。
    lineWidth:線粗細,默認爲1
    lineGap:線端點樣式,默認爲butt,還有round,square可選
    lineJoin:線段鏈接的樣式,默認爲round(圓形),還有bevel(斜角), miter(垂直矩形)可選
    miterLimit:線段相交交叉點的粗細,越大lineJoin所選的樣式越明顯

  3. 繪製線性漸變
    通常用到createLinearGradient()建立線性的漸變對象, 再用addColorStop對線性漸變對象分段添加不一樣顏色達到漸變效果.

例子:

canvas-linear1.png
// createLinearGradient(漸變起始點x,漸變起始點y,漸變結束點x,漸變結束點y)
var shadow = context.createLinearGradient(0,0,200,0); //也能夠理解爲漸變的方向的座標
shadow.addColorStop(0,'#ff0000');
shadow.addColorStop(1/7,'#ff9900');
shadow.addColorStop(2/7,'#ffff00');
shadow.addColorStop(3/7,'#00ff00');
shadow.addColorStop(4/7,'#00ffff');
shadow.addColorStop(5/7,'#0000ff');
shadow.addColorStop(6/7,'#ff00ff');
shadow.addColorStop(1,"#ff0000");
context.fillStyle =shadow;
context.strokeStyle = shadow;
context.fillRect(10,10,200,200);
複製代碼



16. 繪製徑向漸變
利用createRadialGradient()建立徑向漸變對象, 再用addColorStop對徑向漸變對象發射狀添加不一樣顏色達到徑向漸變效果.
例子:

canvas-radial1.png
// createRadialGradient(漸變開始圓座標x0.漸變開始圓座標y0,開始圓半徑r0,漸變結束圓座標x1,漸變結束圓座標y1,結束圓半徑r1)
var shadow = context.createRadialGradient(85,85,3,100,100,100);
shadow.addColorStop(0,"white");
shadow.addColorStop(1,"orange");
context.fillStyle= shadow;
context.fillRect(10,10,200,200);
複製代碼



17. 繪製圖案

A.context.createPattern(image,"repeat|repeat-x|repeat-y|no-repeat")
方法在指定的方向內重複指定的元素.
和設置圖片背景有點相似,先new Image()對象,再將img對象傳進createPattern(img,type),再將其賦予給fillStyle,便可達到填充圖片的效果。
例子:

canvas-pic1.png
var img = new Image(); //建立新的Image對象
img.src = "https://www.easyicon.net/api/resizeApi.php?id=1209623&size=128";  //設置圖像路徑
img.onload = function(){  //加載圖像
    //建立圖案
    var pattern = context.createPattern(img,'repeat');
    context.fillStyle = pattern;
    context.fillRect(0,0,380,190);
	}
複製代碼

B.drawImage()方法
①在畫布上定位圖像:context.drawImage(img,x,y);
②畫布上定位圖像,並規定圖像的寬度和高度:context.drawImage(img,x,y,width,height);
③剪切圖像,並在畫布上定位被剪切的部分:context.drawImage(img,開始剪切座標位置x,開始剪切座標位置y,被剪切圖像寬度swidth,被剪切圖像高度sheight,圖片位置x,圖片位置y,顯示圖片寬度width,顯示圖片高度height);

var img = new Image(); //建立新的Image對象
img.src = "https://www.easyicon.net/api/resizeApi.php?id=1209623&size=128";  //設置圖像路徑
img.onload = function(){  //加載圖像
    //建立圖案
    context.drawImage(img,0,0);
    context.font = "nomal 100px SimHei";
    context.shadowOffsetX = 3;
    context.shadowOffsetY = 3;
    context.shadowBlur = 3;
    context.shadowColor = "pink";
    context.createPattern(img,'repeat');
    context.fillStyle = "white";
    context.fillText("wowww",50,165);
	}
複製代碼



18. 建立陰影

例子:

canvas-shadow2.png
//設置陰影
context.shadowOffsetX =3; //x軸方向的陰影偏移量,負數爲向右偏移量
context.shadowOffsetY =3; //y軸方向的陰影偏移量,負數爲向上偏移量
context.shadowBlur = 2;//陰影模糊強度
context.shadowColor = "pink";

//繪製矩形
context.fillStyle = "orange";
context.fillRect(20,20,300,80);

//繪製文本
context.font = "nomal 45px SimHei"; //設置文本字體樣式
context.fillStyle = "white"; //設置文本顏色,填充顏色
context.fillText("HTML5/CSS3" ,30,64)//設置文本內容和文本位置
複製代碼

注意:在設置了陰影后,文字和矩形都會有陰影。

  1. 繪製填充/輪廓文字

A.context.fillText(文字內容,位置x,位置y[,最大寬度]),若文字內容長度超過最大寬度,文字會自動被壓縮

//繪製填充文本
context.font = "nomal 45px SimHei"; //設置文本字體樣式
context.fillStyle = "white"; //設置文本填充顏色
context.fillText("HTML5/CSS3" ,30,64)//設置文本內容和文本位置
複製代碼

B.context.strokeText(文字內容,位置x,位置y[,最大寬度]),若文字內容長度超過最大寬度,文字會自動被壓縮
//繪製輪廓文本
context.font = "nomal 45px SimHei"; //設置文本字體樣式
context.strokeStyle = "white"; //設置文本輪廓顏色
var text = "HTML5/CSS3";
context.strokeText(text, ,30,64)//設置文本內容和文本位置
複製代碼

其中:能夠經過context.measureText(text)來獲取對應text的寬度.

小白第一次在掘金寫學習總結,從本身理解的角度記錄筆記,可能對某些方法理解存在錯誤,歡迎指出!持續學習更新中....

相關文章
相關標籤/搜索