Canvas是常見的前端技術,可是因爲API衆多,使用複雜,且對程序員的數學功底、空間想象能力乃至審美都有必定要求,因此真正擅長canvas的前端並很少,但並不表明你們就學很差canvas。我在此將經常使用的canvas使用場景羅列出來但願能幫助到你們。html
Canvas的建立很簡單,只須要一個<canvas>
標籤足以,而內部複雜的實現都交給瀏覽器搞定。前端
html:程序員
<canvas id="canvas"></canvas>
全部的繪製動做都須要在canvas上下文(context)中進行,所以咱們須要先建立一個上下文。web
js:canvas
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d');
除了2d
,上下文還能夠設置爲:webgl, webgl2, bitmaprenderer瀏覽器
js:網絡
canvas.width = 600; canvas.height = 600;
若要滿屏顯示能夠:ide
canvas.width = window.innerWidth; canvas.height = window.innerHeight;
fillRect
)繪製實心矩形最簡單的是用 fillRect(x, y, width, height)
方法,參數中 x, y
表示矩形左上角的座標;width
、height
分別表示矩形的寬、高。使用方法以下:學習
js:字體
// 設置填充顏色 ctx.fillStyle = 'skyblue'; // 繪製實心矩形 ctx.fillRect(20, 20, 150, 100);
效果:
strokeRect
)與繪製實心矩形相似的是使用 strokeRect(x, y, width, height)
方法繪製空心矩形。參數與 fillText
方法一致。
js:
// 設置線寬 ctx.lineWidth = 5; // 設置繪製顏色 ctx.strokeStyle = 'chocolate'; // 繪製空心矩形 ctx.strokeRect(20, 20, 150, 100);
效果:
clearRect
)當要重繪canvas中的內容時(好比動畫),咱們須要先使用 clearRect(x, y, width, height)
清空canvas。
js:
ctx.fillStyle = 'skyblue'; ctx.fillRect(20, 20, 150, 100); // 清除畫布中的矩形區域 ctx.clearRect(25, 25, 140, 90);
效果:
繪製文字也是canvas的基本功能,實心文字可使用 fillText(text, x, y [, maxWidth])
方法,參數中 text
表示繪製的文字;x, y
爲文字起點的座標;maxWidth
爲可選參數,表示文字的最大寬度,若是文字超過該最大寬度那麼瀏覽器將會經過調整字間距、字體或者壓縮文字來適應最大寬度。
js:
// 設置繪製顏色 ctx.fillStyle = 'purple'; // 設置字體 ctx.font = '30px Arial'; // 繪製實心顏色 ctx.fillText('Hello World', 220, 50);
效果:
相似的,空心文字可使用 strokeText(text, x, y [, maxWidth])
繪製,參數與 fillText
方法一致:
js:
// 設置線寬 ctx.lineWidth = 3; // 設置文字顏色 ctx.strokeStyle = 'orange'; // 設置字體 ctx.font = '50px Arial'; // 繪製空心文字 ctx.strokeText('Hello World', 180, 50);
效果:
顧名思義,經過Path咱們能夠定義一段段路徑(或直線、或曲線)來組合出咱們想要的圖形。
使用Path也能夠繪製矩形,和 fillRect
、strokeRect
同樣的效果,可是多一個步驟。使用 rect(x, y, width, height)
方法能夠向當前路徑添加一個矩形,該方法只會改變路徑但不會直接渲染出矩形,因此還須要執行 fill()
或 stroke()
方法:
js:
ctx.rect(200, 20, 200, 100); ctx.fillStyle = 'deeppink'; ctx.fill();
效果:
或者,空心矩形:
ctx.rect(200, 20, 200, 100); ctx.lineWidth = 3; ctx.strokeStyle = 'deeppink'; ctx.stroke();
效果:
用路徑能夠繪製各類自定義的圖形,好比三角形:
js:
// 開始繪製路徑 ctx.beginPath(); // 移動至起點 ctx.moveTo(200, 20); // 繪製線段 ctx.lineTo(300, 20); ctx.lineTo(250, 150); ctx.lineTo(200, 20); // 繪製路徑 ctx.stroke();
效果:
或者在繪製最後一邊的時候可使用ctx.closePath()
,使路徑閉合。
咱們也能夠將閉合的路徑填充顏色,以實現實心三角形的繪製:
js:
ctx.beginPath(); ctx.moveTo(200, 20); ctx.lineTo(300, 20); ctx.lineTo(250, 150); // 閉合路徑 ctx.closePath(); // 設置填充顏色 ctx.fillStyle = 'coral'; // 填充路徑 ctx.fill();
效果:
Canvas中沒有專門繪製圓的方法,而是使用更加通用的方法arc(x, y, radius, startAngle, endAngle [, anticlockwise])
繪製弧線,參數中 x, y
爲圓心座標;radius
爲圓的半徑; startAngle
爲弧的初始角度;endAngle
爲弧的結束角度;anticlockwise
表示是否以逆時針方向繪製路徑。例如繪製圓,能夠寫成:
js:
ctx.beginPath(); ctx.arc(300, 300, 60, 0, Math.PI * 2, true); ctx.stroke();
效果:
Canvas也支持繪製二次方曲線,使用 quadraticCurveTo(cpx, cpy, x, y)
方法,參數爲兩個點的座標,其中 cpx, cpy
爲控制點的座標;x, y
爲結束點的座標。使用方法以下:
js:
ctx.beginPath(); ctx.moveTo(150, 400); ctx.quadraticCurveTo(300, 0, 450, 400); ctx.stroke();
效果:
相似的,canvas還支持繪製常見的貝塞爾曲線,使用 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
,參數中 cp1x, cp1y
爲第一控制點的座標;cp2x, cp2y
爲第二控制點的座標;x, y
爲結束點的座標。一個簡單的貝塞爾曲線能夠表示以下:
js:
ctx.beginPath(); ctx.moveTo(100, 400); ctx.bezierCurveTo(200, 200, 400, 400, 500, 200); ctx.stroke();
效果:
咱們也能夠將圖片繪製到canvas上面,使用 drawImage()
方法。drawImage()
方法有三個重載:
drawImage(image, dx, dy); drawImage(image, dx, dy, dWidth, dHeight); drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
各參數的含義爲:
image: 被繪製到canvas上面的圖片源,支持多種類型:CSSImageValue, HTMLImageElement, SVGImageElement, HTMLVideoElement, HTMLCanvasElement, ImageBitmap, OffscreenCanvas
dx: 在canvas上水平方向繪製的起點
dy: 在canvas上垂直方向繪製的起點
dWidth: 在canvas上繪製圖片的寬度
dHeight: 在canvas上繪製圖片的高度
sx: 原始圖片上水平方向裁剪的起點
sy: 原始圖片上垂直方向裁剪的起點
sWidth: 原始圖片上水平方向裁剪的寬度
sHeight: 原始圖片上垂直方向裁剪的高度
前兩個重載比較好理解,就是在canvas上繪製出完整的源圖片,而且能夠經過設置寬高控制圖片的縮放。第三個重載即在canvas上繪製出源圖片的一部分,能夠形象表示爲:
圖片源以 HTMLImageElement
爲例,在canvas上繪製圖片能夠這麼實現:
html:
<img id="source" style="display: none;" src="https://unsplash.it/500/300?image=1074" alt="source">
js:
const image = document.getElementById('source'); image.addEventListener('load', e => { ctx.drawImage(image, 50, 150, 500, 300); });
效果:
使用canvas配合 requestAnimationFrame 能夠很方便的實現一些動畫效果,好比實現一個圓從左往右移動的動畫:
js:
/** * 定義圓 */ const circle = { x: 30, // 水平方向的座標 y: 300, // 垂直方向的座標 size: 30, // 圓的半徑 dx: 5, // 水平座標的變化值 dy: 4 // 垂直座標的變化值 } /** * 繪製圓 */ function drawCirle() { ctx.beginPath(); ctx.arc(circle.x, circle.y, 30, 0, Math.PI * 2); ctx.fillStyle = 'purple'; ctx.fill(); } /** * 更新canvas實現動畫效果 */ function update() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawCirle(); circle.x += circle.dx; requestAnimationFrame(update); } update();
效果:
咱們也能夠給小球加上碰撞檢測,讓它在canvas裏面來回彈:
js:
function update() { ... if (circle.x + circle.size > canvas.width || circle.x - circle.size < 0) { circle.dx *= -1; } requestAnimationFrame(update); }
效果:
或者咱們能夠實現用鍵盤控制圓的移動:
js:
/** * 定義圓 */ const circle = { x: 300, // 水平方向的座標 y: 300, // 垂直方向的座標 size: 30, // 圓的半徑 dx: 0, // 水平座標的變化值 dy: 0, // 垂直座標的變化值 speed: 10 // 移動速度 } /** * 繪製圓 */ function drawCirle() { ctx.beginPath(); ctx.arc(circle.x, circle.y, 30, 0, Math.PI * 2); ctx.fillStyle = 'purple'; ctx.fill(); } /** * 更新canvas實現動畫效果 */ function update() { ctx.clearRect(0, 0, canvas.width, canvas.height); circle.x += circle.dx; circle.y += circle.dy; // 邊界碰撞檢測 const leftMost = circle.size; const rightMost = canvas.width - circle.size; const topMost = circle.size; const bottomMost = canvas.height - circle.size; if (circle.x < leftMost) { circle.x = leftMost; } if (circle.x > rightMost) { circle.x = rightMost; } if (circle.y < topMost) { circle.y = topMost; } if (circle.y > bottomMost) { circle.y = bottomMost; } // 繪製圓 drawCirle(); requestAnimationFrame(update); } /** * 開始移動 */ function move(e) { const { key } = e; if (key === 'ArrowUp' || key === 'Up') { circle.dy = -circle.speed; } else if (key === 'ArrowDown' || key === 'Down') { circle.dy = circle.speed; } else if (key === 'ArrowLeft' || key === 'Left') { circle.dx = -circle.speed; } else if (key === 'ArrowRight' || key === 'Right') { circle.dx = circle.speed; } } /** * 中止移動 */ function stop(e) { if ( e.key == 'Right' || e.key == 'ArrowRight' || e.key == 'Left' || e.key == 'ArrowLeft' || e.key == 'Up' || e.key == 'ArrowUp' || e.key == 'Down' || e.key == 'ArrowDown' ) { circle.dx = 0; circle.dy = 0; } } document.addEventListener('keydown', move); document.addEventListener('keyup', stop); update();
效果:
因爲canvas很是的強大,可是API較爲複雜,因此業界出現了不少基於canvas的庫,讓你們使用canvas更加簡單,下面列出一些供你們選擇:
關於canvas就給你們介紹到這裏,但願有朝一日你們都能用canvas畫出心中最美的風景!