關注公衆號「執鳶者」,回覆「資料」獲取500G資料(各「兵種」均有),還有專業交流羣等你一塊兒來瀟灑。(哈哈)經過本文你將瞭解canvas簡介及其比較經常使用的方法,並利用canvas實現一個小豬頭。html
Canvas(畫布)是在HTML5中新增的標籤用於在網頁實時生成圖像,能夠操做圖像內容,是一個能夠用JavaScript操做的位圖(bitmap)。
canvas的座標系統以下圖所示,其具備以下特色:
canvas這個神奇的東西有不少領域能夠獲得應用,下面咱們一塊兒嘮一嘮。
經過第一章對canvas有了初步的認識,本章就按照一我的繪製一幅畫的思路進行演化,逐步瞭解canvas的基本功能,從而更好的使用它實現一些酷炫的效果。
當要繪製一幅畫時首先要肯定座標系,只有選擇好了座標系以後纔好動筆,在canvas中默認座標系在左上角(X軸正方向向右、Y軸正方向向下),但是有的時候須要變換座標系才能更方便的實現所需的效果,此時須要變換座標系,canvas提供瞭如下幾種變換座標系的方式:
function main() { const canvas = document.getElementById('canvasId'); const ctx = canvas.getContext('2d'); ctx.lineWidth = 4; // 默認 ctx.save(); ctx.strokeStyle = '#F00'; drawCoordiante(ctx); ctx.restore(); // 平移 ctx.save(); ctx.translate(150, 150); ctx.strokeStyle = '#0F0'; drawCoordiante(ctx); ctx.restore(); // 旋轉 ctx.save(); ctx.translate(300, 300); ctx.rotate(-Math.PI / 2); ctx.strokeStyle = '#00F'; drawCoordiante(ctx); ctx.restore(); // 縮放 ctx.save(); ctx.translate(400, 400); ctx.rotate(-Math.PI / 2); ctx.scale(0.5, 0.5); ctx.strokeStyle = '#000'; drawCoordiante(ctx); ctx.restore(); } function drawCoordiante(ctx) { ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(120, 0); ctx.moveTo(0, 0); ctx.lineTo(0, 80); ctx.closePath(); ctx.stroke(); } main();
座標系選擇好了以後,就要開始動筆創做大做了,那麼canvas到底容許繪製哪些內容呢?
function drawLine(ctx, startX, startY, endX, endY) { ctx.moveTo(startX, startY); ctx.lineTo(endX, endY); ctx.stroke(); }
function drawCircle(ctx, x, y, R, startAngle, endAngle) { ctx.arc(x, y, R, startAngle, endAngle); ctx.stroke(); }
// 貝濟埃曲線 function drawBezierCurve(ctx, cpX1, cpY1, cpX, cpY2, endX, endY) { ctx.bezierCurveTo(cpX1, cpY1, cpX, cpY2, endX, endY); ctx.stroke(); } // 二次曲線 function drawQuadraticCurve(ctx, cpX, cpY, endX, endY) { ctx.quadraticCurveTo(cpX, cpY, endX, endY); ctx.stroke(); }
// 填充矩形 function drawFillRect(ctx, x, y, width, height) { ctx.fillRect(x, y, width, height); } // 邊框矩形 function drawStrokeRect(ctx, x, y, width, height) { ctx.strokeRect( x, y, width, height); }
// 填充字符串 function drawFillText(ctx, text, x, y) { ctx.fillText(text, x, y); } // 邊框字符串 function drawStrokeText(ctx, text, x, y) { ctx.strokeText(text, x, y); }
// 利用路徑繪製 function drawFigureByPath(ctx) { ctx.beginPath(); ctx.moveTo(100, 400); ctx.lineTo(200, 450); ctx.lineTo(150, 480); ctx.closePath(); ctx.fill(); }
function main() { const canvas = document.getElementById('canvasId'); const ctx = canvas.getContext('2d'); ctx.lineWidth = 2; ctx.strokeStyle = '#F00'; ctx.fillStyle = '#F00'; ctx.font = 'normal 50px 宋體'; drawLine(ctx, 50, 10, 150, 10); ctx.moveTo(150, 100); drawCircle(ctx, 100, 100, 50, 0, Math.PI); ctx.moveTo(300, 100); drawCircle(ctx, 250, 100, 50, 0, Math.PI * 2); ctx.moveTo(350, 150); drawBezierCurve(ctx, 200, 200, 450, 250, 300, 300); ctx.moveTo(50, 250); drawQuadraticCurve(ctx, 50, 400, 80, 400); drawFillRect(ctx, 100, 300, 100, 50); drawStrokeRect(ctx, 300, 300, 100, 50); drawFillText(ctx, 'I', 100, 400); drawStrokeText(ctx, 'I', 300, 400); drawFigureByPath(ctx); }
利用canvas繪製圖形時勢必要上點顏料,經過設置fillStyle屬性便可設置對應的顏料,對於顏料值主要有如下四種:純顏色、線性漸變顏色、徑向漸變顏色、位圖。
function useColorFill(ctx) { ctx.save(); ctx.fillStyle = '#F00'; ctx.fillRect(10, 10, 100, 100); ctx.restore(); }
function useLinearGradientFill(ctx) { ctx.save(); const lg = ctx.createLinearGradient(110, 10, 210, 10); lg.addColorStop(0.2, '#F00'); lg.addColorStop(0.5, '#0F0'); lg.addColorStop(0.9, '#00F'); ctx.fillStyle = lg; ctx.fillRect(120, 10, 100, 100); ctx.restore(); }
function useRadialGradientFill(ctx) { ctx.save(); const lg = ctx.createRadialGradient(260, 60, 10, 260, 60, 60); lg.addColorStop(0.2, '#F00'); lg.addColorStop(0.5, '#0F0'); lg.addColorStop(0.9, '#00F'); ctx.fillStyle = lg; ctx.fillRect(230, 10, 100, 100); ctx.restore(); }
function useImageFill(ctx) { ctx.save(); const image = new Image(); image.src = 'https://dss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=442547030,98631113&fm=58'; image.onload = function () { // 建立位圖填充 const imgPattern = ctx.createPattern(image, 'repeat'); ctx.fillStyle = imgPattern; ctx.fillRect(340, 10, 100, 100); ctx.restore(); } }
用一隻畫筆在畫某個美女時,突然來了靈感須要畫另外一個帥哥,這個時候又不想放棄這個美女,則就須要將當前畫美女的顏料、座標等狀態進行暫存,等到畫完帥哥後恢復狀態進行美女的繪製。在canvas中能夠經過save()和restore()方法實現,調用save()方法後將這一時刻的設置放到一個暫存棧中,而後能夠放心的修改上下文,在須要繪製以前的上下文時,能夠調用restore()方法。
![]()
// 從左往右是依次繪製(中間爲用新的樣式填充,最後一個是恢復到原來樣式填充) function main() { const canvas = document.getElementById('canvasId'); const ctx = canvas.getContext('2d'); ctx.fillStyle = '#F00'; ctx.fillRect(10, 10, 100, 100); ctx.save(); ctx.fillStyle = '#0F0'; ctx.fillRect(150, 10, 100, 100); ctx.restore(); ctx.fillRect(290, 10, 100, 100); }
有的時候須要引入外部圖片,而後對外部圖片進行像素級別的處理,最後進行保存。
function main() { const canvas = document.getElementById('canvasId'); const ctx = canvas.getContext('2d'); const image = document.getElementById('image'); // 繪製圖像 ctx.drawImage(image, 0, 0); // 獲取圖像數據 const imageData = ctx.getImageData(0, 0, image.width, image.height); const data = imageData.data; for (let i = 0, len = data.length; i < len; i += 4) { const red = data[i]; const green = data[i + 1]; const blue = data[i + 2]; const average = Math.floor((red + green + blue) / 3); data[i] = average; data[i + 1] = average; data[i + 2] = average; } imageData.data = data; ctx.putImageData(imageData, 0, 0); document.getElementById('result').src = canvas.toDataURL('image/png'); }
學習了這麼多,就利用canvas繪製一個豬頭吧,畢竟每一個程序員身邊確定有一個陪伴本身的小胖豬,嘿嘿。
![]()
function main() { const canvas = document.getElementById('canvasId'); const ctx = canvas.getContext('2d'); ctx.lineWidth = 4; ctx.strokeStyle = '#000'; ctx.fillStyle = '#ffd8e1'; ctx.translate(260, 20); drawPigEar(ctx); ctx.save(); ctx.rotate(Math.PI / 2); drawPigEar(ctx); ctx.restore(); drawPigFace(ctx); ctx.save(); ctx.translate(-100, -100); drawPigEye(ctx); ctx.restore(); ctx.save(); ctx.translate(100, -100); drawPigEye(ctx); ctx.restore(); ctx.save(); ctx.translate(0, 60); drawPigNose(ctx); ctx.restore(); } function drawPigEar(ctx) { ctx.save(); ctx.beginPath(); ctx.arc(-250, 0, 250, 0, -Math.PI / 2, true); ctx.arc(0, -250, 250, -Math.PI, Math.PI / 2, true); ctx.closePath(); ctx.fill(); ctx.stroke(); ctx.restore(); } function drawPigFace(ctx) { ctx.save(); ctx.beginPath(); ctx.arc(0, 0, 250, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); ctx.closePath(); ctx.restore(); } function drawPigEye(ctx) { ctx.save(); ctx.fillStyle = '#000'; ctx.beginPath(); ctx.arc(0, 0, 20, 0, Math.PI * 2); ctx.closePath(); ctx.fill(); ctx.restore(); } function drawPigNose(ctx) { ctx.save(); ctx.fillStyle = '#fca7aa'; ctx.beginPath(); ctx.ellipse(0, 0, 150, 100, 0, 0, Math.PI * 2); ctx.closePath(); ctx.fill(); ctx.stroke(); ctx.save(); ctx.translate(-60, 0); drawPigNostrils(ctx); ctx.restore(); ctx.save(); ctx.translate(60, 0); drawPigNostrils(ctx); ctx.restore(); ctx.restore(); } function drawPigNostrils(ctx) { ctx.save(); ctx.fillStyle = '#b55151'; ctx.beginPath(); ctx.ellipse(0, 0, 40, 60, 0, 0, Math.PI * 2); ctx.closePath(); ctx.fill(); ctx.stroke(); ctx.restore(); } main();
1.若是以爲這篇文章還不錯,來個分享、點贊吧,讓更多的人也看到前端
2.關注公衆號執鳶者,領取學習資料(前端「多兵種」資料),按期爲你推送原創深度好文html5