
文章出處
寫在前面
閑來無事的時候會來一場一個人說走就走的旅行或者宅家里系統性的看些技術方面的書,最近在看《html5與css3權威指南》,這本書挺適合初學前端的人,雖然對于我來說只是溫習相關的知識,但好歹來說開卷有益,只要是一本好書,即使知識很淺也值得一看。
(我會在相關代碼注釋中揭示canvas對象相關方法各參數的含義)寫的不好的地方還望大家見諒canvas概述
canvas標簽非常的簡潔,常用的就width和height兩個屬性
大多數 canvas 繪圖 API 都沒有定義在 <canvas> 元素本身上,而是定義在通過畫布的 getContext() 方法獲得的一個“繪圖環境”對象上
var tCanvas = document.getElementById("canvasOne");
var ct = tCanvas.getContext("2d");
//因此可以通過該方法來檢測瀏覽器是否支持canvas:
function canvasSupport() {
//檢測是否支持canvas
return !!document.createElement("canvas").getContext;
}繪制矩形
界面html如下所示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body onload="draw('canvas');">
<canvas id="canvas" width="400" height="300"></canvas>
<script src="script.js"></script>
</body>
</html>
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');//取得上下文對象
context.fillStyle = '#EEEEFF';//填充樣式
context.fillRect(0, 0, 400, 300);//填充矩形
context.fillStyle = 'red';
context.strokeStyle = 'blue';//圖形邊框的樣式
context.lineWidth = 1;//設置圖形邊框的寬度
context.fillRect(50, 50, 100, 100);//填充矩形
context.strokeRect(50, 50, 100, 100);//繪制矩形邊框
}效果圖如下所示:
使用路徑繪制圓形
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
for (var i = 0; i < 10; i++) {
context.beginPath();//開始創建路徑
//創建圓形路徑
context.arc(i * 25,//繪制圓形的起點橫坐標
i * 25,//繪制圓形的起點縱坐標
i * 10,//圓形半徑
0,//開始角度
Math.PI * 2,//結束角度
true/*是否按順時針方向進行繪制*/);
context.closePath();//關閉路徑
context.fillStyle = 'rgba(255,0,0,0.25)';//設置繪制樣式
context.fill();//進行圖形繪制
}
} 效果圖如下所示:
未關閉路徑繪制圓形
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
for (var i = 0; i < 10; i++) {
context.arc(i * 25, i * 25, i * 10, 0, Math.PI * 2, true);
context.fillStyle = 'rgba(255,0,0,0.25)';
context.fill();
}
} 效果圖如下所示:
使用moveTo和LineTo方法繪制復雜線條
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
context.fillRect(0, 0, 400, 300);
var dx = 150,
dy = 150,
s = 100,
x = Math.sin(0),
y = Math.cos(0),
dig = Math.PI / 15 * 11;
context.beginPath();//需要使用moveTo將光標移動到所指定的直線起點
context.fillStyle = 'rgb(100,255,100)';
context.strokeStyle = 'rbg(0,0,100)';
for (var i = 0; i < 30; i++) {
x = Math.sin(i * dig);
y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);//繪制一條直線 (在直線起點和直線終點繪制)
}
context.closePath();
context.fill();
context.stroke();
} 效果圖如下所示:
使用bezierCurveTo繪制貝濟埃曲線
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#EEEEFF';
var dx = 150,
dy = 150,
s = 100,
x = Math.sin(0),
y = Math.cos(0),
dig = Math.PI / 15 * 11;
context.beginPath();
context.globalCompositeOperation = 'red';
context.fillStyle = 'rgb(100,255,100)';
context.moveTo(dx, dy);//將光標移動到指定坐標點
for (var i = 0; i < 30; i++) {
x = Math.sin(i * dig);
y = Math.cos(i * dig);
//繪制貝濟埃曲線 將當前坐標點到指定坐標點中間的貝濟埃曲線追加到路徑中
context.bezierCurveTo(dx + x * s,//第一個控制點的橫坐標
dy + y * s - 100,//第一個控制點的縱坐標
dx + x * s + 100,//第二個控制點的橫坐標
dy + y * s,//第二個控制點的縱坐標
dx + x * s,//貝濟埃曲線的終點橫坐標
dy + y * s);//貝濟埃曲線的終點縱坐標
}
context.closePath();
context.fill();
context.stroke();
} 效果圖如下所示:
繪制線性漸變
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
//創建線性漸變
var g1 = context.createLinearGradient(0,//漸變起始地點的橫坐標
0,//漸變起始地點的縱坐標
0,////漸變結束地點的橫坐標
300);//漸變結束地點的縱坐標
//追加漸變的顏色
g1.addColorStop(0,//設定顏色離開漸變起始點的偏移量 該參數的值是一個范圍在0到1之間的浮點數 漸變起始點的偏移量為0 漸變結束點的偏移量為1
'rgb(255,255,0)');//顏色值
//因為是漸變 所以至少使用兩次addColorStop
g1.addColorStop(1, 'rgb(0,255,255)');
context.fillStyle = g1;
context.fillRect(0, 0, 400, 300);
var g2 = context.createLinearGradient(0, 0, 300, 0);
g2.addColorStop(0, 'rgba(0,0,255,0.5)');
g2.addColorStop(1, 'rgba(255,0,0,0.5)');
for (var i = 0; i < 10; i++) {
context.beginPath();
context.fillStyle = g2;//設置為漸變LinearGradient對象
context.arc(i * 25, i * 25, i * 10, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}
} 效果圖如下所示:
繪制徑向漸變
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
//繪制徑向漸變
var g1 = context.createRadialGradient(400,//漸變開始圓的圓心橫坐標
0,//漸變開始圓的圓心縱坐標
0,//漸變開始圓的半徑
400,//漸變結束圓的圓心橫坐標
0,//漸變結束圓的圓心縱坐標
400);//漸變結束圓的半徑
g1.addColorStop(0.1, 'rgb(255,255,0)');
g1.addColorStop(0.3, 'rgb(255,0,255)');
g1.addColorStop(1, 'rgb(0,255,255)');
context.fillStyle = g1;
context.fillRect(0, 0, 400, 300);
var g2 = context.createRadialGradient(250, 250, 0, 250, 250, 250, 300);
g2.addColorStop(0.1, 'rgba(255,0,0,0.5)');
g2.addColorStop(0.7, 'rgba(255,255,0,0.5)');
g2.addColorStop(1, 'rgba(0,0,255,0.5)');
for (var i = 0; i < 10; i++) {
context.beginPath();
context.fillStyle = g2;
context.arc(i * 25, i * 25, i * 10, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}
} 效果圖如下所示:
利用坐標變換來繪制類似撲克牌的變形圖形
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#eef';
context.fillRect(0, 0, 400, 300);
//移動坐標軸原點
context.translate(200,//將坐標軸原點向左移動多少個單位
50); //將坐標軸原點向下移動多少個單位
context.fillStyle = 'rgba(255,0,0,0.25)';
for (var i = 0; i < 50; i++) {
context.translate(25, 25);
//將圖形放大
context.scale(0.95,//水平方向的放大倍數
0.95);//垂直方向的放大倍數
context.rotate(Math.PI / 10);//將圖形進行旋轉
context.fillRect(0, 0, 100, 50);
}
} 效果圖如下所示:
利用坐標變換與路徑結合使用來繪制星形圖形
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#eef';
context.fillRect(0, 0, 400, 300);
context.translate(200, 50);
for (var i = 0; i < 50; i++) {
context.translate(25, 25);
context.scale(0.95, 0.95);
context.rotate(Math.PI / 10);
create5Star(context);
context.fill();
}
}
function create5Star(context) {
var dx = 100,
dy = 0,
s = 50;
context.beginPath();
context.fillStyle = 'rgba(255,0,0,0.5)';
var x = Math.sin(0),
y = Math.cos(0),
dig = Math.PI / 5 * 4;
for (var i = 0; i < 5; i++) {
x = Math.sin(i * dig);
y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);
}
context.closePath();
} 效果圖如下所示:
利用矩陣變換來繪制彩虹
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
//定義顏色
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'navy', 'purple'];
context.lineWidth = 10;//定義線寬
context.transform(1, 0, 0, 1, 100, 0);//矩陣轉換
for (var i = 0; i < colors.length; i++) {//循環繪制圓弧
context.transform(1, 0, 0, 1, 0, 10);//定義每次向下移動10個像素的變換矩陣
context.strokeStyle = colors[i];//設定顏色
context.beginPath();
context.arc(50, 100, 100, 0, Math.PI, true);//繪制圓弧
context.stroke();
}
} 效果圖如下所示:
使用setTransform方法繪制變形圖形
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
//繪制紅色長方形
context.strokeStyle = 'red';
context.strokeRect(30, 10, 60, 20);
//繪制順時針旋轉45度的藍色長方形
var rad = 45 * Math.PI / 180;
context.setTransform(Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), 0, 0);//定義順時針旋轉45的變換矩陣
context.strokeStyle = 'blue';
context.strokeRect(30, 10, 60, 20);//繪制圖形
//繪制放大2.5倍后的綠色長方形
context.setTransform(2.5, 0, 0, 2.5, 0, 0);//定義放大2.5倍的變換矩陣
context.strokeStyle = 'green';
context.strokeRect(30, 10, 60, 20);//繪制圖形
//將坐標原點向左移動40像素,向下移動80像素后繪制灰色長方形
context.setTransform(1, 0, 0, 1, 40, 80);//定義將坐標原點向右移動40像素,向下移動80像素的矩陣
context.strokeStyle = 'gray';
context.strokeRect(30, 10, 60, 20);//繪制圖形
} 效果圖如下所示:
圖形結合的不同選項講解
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
var oprtns = [
'source-atop',//只繪制新圖形中與原有圖形重疊的部分與未被重疊覆蓋的原有圖形,新圖形的其它部分變成透明
'source-in',//只顯示新圖形中與原有圖形相重疊的部分,新圖形與原有圖形的其它部分均變成透明
'source-out',//只顯示原圖形與新圖形不重疊的部分,新圖形與原有圖形的其它部分均變成透明
'source-over',//新圖形覆蓋在原有圖形之上
'destination-atop',//只繪制原有圖形中被新圖形重疊覆蓋的部分與新圖形的其它部分,原有圖形中的其它部分變成透明 ,不繪制新圖形中與原有圖形相重疊的部分
'destination-in',//只顯示原有圖形中與新圖形相重疊的部分,新圖形與原有圖形的其它部分均變成透明
'destination-out',//只顯示原有圖形中與新圖形不重疊的部分,新圖形與原有圖形的其它部分均變成透明
'destination-over',//在原有圖形之下繪制圖形
'lighter',//原有圖形與新圖形均繪制,重疊部分做加色處理
'copy',//只繪制新圖形,原有圖形中未與新圖形重疊的部分變成透明
'xor'];//只繪制新圖形中與原有圖形不重疊的部分,重疊部分變成透明
i = 7;//在原有圖形之下繪制圖形 (這里大家可以自己去試下其它選項 方便自己深入理解)
context.fillStyle = 'blue';
context.fillRect(10, 10, 60, 60);
context.globalCompositeOperation = oprtns[i];
context.beginPath();
context.fillStyle = 'red';
context.arc(60, 60, 30, 0, Math.PI * 2, false);
context.fill();
} 效果圖如下所示:
給圖形繪制陰影
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#eef';
context.fillRect(0, 0, 400, 300);
context.shadowOffsetX = 10;//陰影的橫向位移量
context.shadowOffsetY = 10;//陰影的縱向位移量
context.shadowColor = 'rgba(100,100,100,0.5)';//陰影的顏色
context.shadowBlur = 7.5;//陰影的模糊范圍
context.translate(0, 50);
for (var i = 0; i < 3; i++) {
context.translate(50, 50);
create5Star(context);
context.fill();
}
}
function create5Star(context) {
var dx = 100,
dy = 0,
s = 50,
x = Math.sin(0),
y = Math.cos(0),
dig = Math.PI / 5 * 4;
context.beginPath();
context.fillStyle = 'rgba(255,0,0,0.5)';
for (var i = 0; i < 5; i++) {
x = Math.sin(i * dig);
y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);
}
context.closePath();
} 效果圖如下所示:
繪制圖像
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#eef';
context.fillRect(0, 0, 400, 300);
var image = new Image();
image.src = 'img/ctrip.gif';
image.onload = function () {
for (var i = 0; i < 7; i++) {
context.drawImage(image,//img元素
0 + i * 50,//繪制時的圖像的寬度
0 + i * 25,//繪制時的圖像的高度
100,//繪制該圖像在畫布中的x坐標
100);//繪制該圖像在畫布中的y坐標
}
}
} 效果圖如下所示:
繪制圖像時放大局部圖像
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#eef';
context.fillRect(0, 0, 400, 300);
var image = new Image();
image.src = 'img/ctrip.gif';//設置圖像路徑
image.onload = function () {//繪制圖像的函數
var i = 0;
//繪制原始圖像
context.drawImage(image,//img元素
0,//繪制時的圖像的寬度
0,//繪制時的圖像的高度
100,//繪制該圖像在畫布中的x坐標
100);//繪制該圖像在畫布中的y坐標
//繪制將局部區域進行放大后的圖像
context.drawImage(image,//img元素
0,//源圖像被復制區域在畫布中的起始畫布中的起始橫坐標
0,//源圖像被復制區域在畫布中的起始畫布中的起始縱坐標
50,//被復制區域的寬度
80,//被復制區域的高度
110,//復制后的目標圖像在畫布中的起始橫坐標
0,//復制后的目標圖像在畫布中的起始縱坐標
100,//復制后的目標圖像的寬度
100);//復制后的目標圖像的高度
}
} 效果圖如下所示:
圖像平鋪
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
var image = new Image();
image.src = 'img/ctrip.gif';//設置圖像路徑
image.onload = function () {
var scale = 5,
n1 = image.width / scale,
n2 = image.height / scale,
n3 = canvas.width / n1,
n4 = canvas.height / n2;
for (var i = 0; i < n3; i++) {
for (var j = 0; j < n4; j++) {
context.drawImage(image, i * n1, j * n2, n1, n2);
}
}
}
} 效果圖如下所示:
利用createPattern方法平鋪圖像
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
var image = new Image();
image.src = 'img/ctrip.gif';//設置圖像路徑
image.onload = function () {
//no-repeat 不平鋪
//repeat-x 橫方向平鋪
//repeat-y 縱方向平鋪
//repeat 全方向平鋪
var ptrn = context.createPattern(image, 'repeat');//創建填充樣式,全方向平鋪
context.fillStyle = ptrn;//指定填充樣式
context.fillRect(0, 0, 400, 300);//填充畫布
}
} 效果圖如下所示:
圖像裁剪
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
var gr = context.createLinearGradient(0, 400, 300, 0);
gr.addColorStop(0, 'rgb(255,255,0)');
gr.addColorStop(1, 'rgb(0,255,255)');
context.fillStyle = gr;
context.fillRect(0, 0, 400, 300);
var image = new Image();
image.src = 'img/ctripLogo.png';//設置圖像路徑
image.onload = function () {
var n = 0,
dx = 100,
dy = 0,
s = 150,
x = Math.sin(0),
y = Math.cos(0),
dig = Math.PI / 5 * 4;
context.beginPath();
context.translate(100, 150);
for (var i = 0; i < 5; i++) {
x = Math.sin(i * dig);
y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);//創建一個五角星的路徑
}
context.clip();//設置裁剪圖像
context.drawImage(image, -50, -150, 300, 300);
}
} 效果圖如下所示:
將圖像進行反顯操作
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
var image = new Image();
image.src = 'img/ctrip.gif';//設置圖像路徑
image.onload = function () {
context.drawImage(image, 0, 0);
//獲得圖像中的像素
var imageData = context.getImageData(0,//起點橫坐標
0,//起點縱坐標
image.width,//獲取區域的寬度
image.height);//獲取區域的高度
for (var i = 0,n=imageData.data.length; i < n; i+=4) {
imageData.data[i + 0] = 255 - imageData.data[i + 0];//red
imageData.data[i + 1] = 255 - imageData.data[i + 2];//red
imageData.data[i + 2] = 255 - imageData.data[i + 1];//red
}
//將像素的數據重新放置到圖像中
context.putImageData(imageData,//像素數組
0,//重繪圖像的起點橫坐標
0);//重繪圖像的起點縱坐標
}
} 效果圖如下所示:
繪制文字
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = '#00f';
context.font = 'italic 30px sans-serif';//設置文字字體
context.textBaseline = 'top';//設置文字垂直對齊方式
context.fillText('示例文字', 0, 0);
context.font = 'bold 30px sans-serif';
context.strokeText('示例文字', 0, 50);
} 效果圖如下所示:
測量文字寬度
JavaScript如下所示:
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.font = 'italic 20px sans-serif';
var txt = '字符串的寬度為';//定義繪制文字
var tml = context.measureText(txt);//獲得文字寬度
context.fillText(txt, 10, 30);//繪制文字
context.fillText(tml.width, tml.width + 10, 30);
context.font = 'bold 30px sans-serif';//改變字體
var tm2 = context.measureText(txt);//重新獲得文字寬度
context.fillText(txt, 10, 70);//重新繪制文字
context.fillText(tm2.width, tm2.width + 10, 70);
}效果圖如下所示: