進入JS30的第八天,今天我們要透過HTML的<canvas>
元素,在頁面上創造出一塊畫布,並讓我們在上面畫出彩色的線條。
在範例當中,當我們在畫面上按下滑鼠拖曳,就會沿著鼠標軌跡出現一條線,而這條線又會隨著過程有粗細及顏色的變化。
實作連結-1
實作連結-2
<canvas>
元素,可以在HTML中創造一個類似畫布的區域,再利用程式腳本在上面繪出圖形。
height
:單位為pixel,表示此元素座標的空間高度,預設為150px。width
:單位為pixel,表示此元素座標的空間寬度,預設為300px。要修改<canvas>
元素大小的話,需要直接使用在元素中加入屬性,如果在CSS屬性中強制修改的話,<canvas>
的網格大小將被縮放來符合元素尺寸。
//方法一
<canvas id="canvas" width="300" height="300">
//方法二
let canvas = document.querySelector('canvas);
canvas.width = 300;
canvas.height = 300;
getContext()
:<canvas>
元素所創造的區域一開始為空白,透過此方法可以取得渲染環境來產生或操作顯示內容,而畫布上可以有一或多個渲染環境,此方法中的值則代表渲染環境的類型(2D or 3D)。context.fillRect(x,y,width,height);
x:矩形左上角的起始點X軸座標,往右為正。
y:矩形左上角的起始點Y軸座標,往下為正。
width:寬。
height:高。
矩形範例:
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
//設定填滿圖形用的顏色
ctx.fillStyle='blue';
ctx.fillRect(25, 50, 120, 150);
//beginPath()方法:產生一條路徑,或重置目前的路徑。
context.beginPath();
//moveTo():該線的起點座標。
context.moveTo(X-Start, Y-Start);
//lineTo():該線的終點座標。
context.lineTo(X-End, Y-End);
//線條寬度
context.lineWidth = number;
//端點樣式
context.lineCap = 'butt'<切平> or 'round'<圓形> or 'square'<方形>;
//交叉點樣式
context.lineJoin = 'bevel'<斜角> or 'round'<圓形> or 'miter'<尖角>;
//線條顏色
context.strokeStyle = color;
//繪製路徑
context.stroke();
線範例:
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(75,75);
ctx.lineTo(225, 75);
ctx.lineTo(75, 225);
ctx.lineTo(225, 225);
ctx.lineWidth = 20;
ctx.lineCap = 'round';
ctx.lineJoin = 'miter';
ctx.strokeStyle = 'green';
ctx.stroke();
context.beginPath();
context.arc(x,y,r,sAngle,eAngle);
x:圓心X軸座標,往右為正。
y:圓心Y軸座標,往下為正。
r:圓的半徑。
sAngle:起始角度。
eAngle:結束角度。
圓形範例:
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(150, 150, 100, 0, 2*Math.PI);
ctx.fillStyle='rgba(0, 0, 0, 0.5)';
//填滿圖形
ctx.fill();
ctx.lineWidth= 4;
ctx.strokeStyle='blue';
//畫出曲線
ctx.stroke();
context.strokeText(text,x,y);
context.fileText(text,x,y);
text:要呈現的字。
x:字串左上起始點X軸座標。
y:字串左上起始點Y軸座標。
字體範例:
// stroke font
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
ctx.beginPath();
//字體大小及字型
ctx.font = '50px Arial';
ctx.strokeStyle = 'red';
ctx.strokeText('Hello World', 25, 75);
// fill font
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.font = '50px Arial';
ctx.fillStyle = 'blue';
ctx.fillText('Hello World', 25, 225);
//線性漸層
context.createLinearGradient(x0,y0,x1,y1);
x0:漸層起點的X軸座標。
y0:漸層起點的y軸座標。
x1:漸層終點的X軸座標。
y1:漸層終點的y軸座標。
//圓形漸層
context.createRadialGradient(x0,y0,r0,x1,y1,r1);
x0:漸層起點圓心的X軸座標。
y0:漸層起點圓心的y軸座標。
r0:漸層起點圓心的半徑大小。
x1:漸層終點圓心的X軸座標。
y1:漸層終點圓心的y軸座標。
r1:漸層終點圓心的半徑大小。
//新增顏色
gradient.addColorStop(stop,color);
stop:代表漸層起點到終點間的位置。該值從0(起點)到1(終點)。
color:代表漸層在該位置上的顏色。
線性漸層範例:
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
let grd = ctx.createLinearGradient(50,50, 150, 50);
grd.addColorStop(0, 'red');
grd.addColorStop(0.5, 'orange');
grd.addColorStop(1, 'yellow');
ctx.fillStyle=grd;
ctx.fillRect(50, 50, 150, 150);
圓形漸層範例:
let canvas = document.getElementById('mycanvas');
let ctx = canvas.getContext('2d');
let grd = ctx.createRadialGradient(150, 150, 0, 150, 150, 120);
grd.addColorStop(0, 'blue');
grd.addColorStop(0.25, 'green');
grd.addColorStop(0.5, 'yellow');
grd.addColorStop(0.75, 'orange');
grd.addColorStop(1, 'red');
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(150 ,150, 120, 0, 2*Math.PI);
ctx.fill();
要完成今天的課題,我們需要依序完成以下的步驟:
<canvas>
元素創造畫布區域。首先我們要創造畫布區域,目標是整個頁面,因此先透過CSS屬性,將body
的margin
及padding
歸零。然後建立一個<canvas>
元素,並利用前面所學的innerHeight
以及innerWidth
將其寬跟高指定為整個頁面。
html,body {
margin: 0;
padding: 0;
}
var canvas = document.querySelector('#draw');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
完成畫布的設定之後,再來要監聽事件。當我們按下滑鼠按鍵之後,隨著滑鼠的移動會繪製出線條,當放開按鍵的時候,又失去繪圖的功能。因此我們要監聽的事件包含mousedown
、mouseup
以及mousemove
。而當mousedown
事件觸發的時候,我們要加上監聽mousemove
這個事件,而當放開滑鼠按鍵的時候,我們要解除監聽mousemove
這個事件:
canvas.addEventListener('mousedown', checkClick);
canvas.addEventListener('mouseup', removeClick);
//按下滑鼠的時候
function checkClick(event) {
//取得滑鼠按下時的位置
lastX = event.offsetX;
lastY = event.offsetY;
canvas.addEventListener('mousemove', createCircle);
};
function removeClick(event) {
canvas.removeEventListener('mousemove', createCircle);
};
從上面的canvas
介紹,我們已經知道如何畫出一條線,透過將按下滑鼠的位置作為原點,移動之後滑鼠的位置為終點,可以畫出第一條線,而滑鼠下一次移動的線條終點又以上一次的終點為起點持續畫出新的線條,如此一來就能完成初步的畫線。
function createLine(event) {
//取得滑鼠移動後的位置座標
var newX = event.offsetX;
var newY = event.offsetY;
var getContext = canvas.getContext('2d');
getContext.beginPath();
//指定剛開始滑鼠按下的位置作為線的起點
getContext.moveTo(lastX, lastY);
//指定滑鼠移動之後的位置作為線的終點
getContext.lineTo(newX, newY);
getContext.lineCap = 'round';
getContext.lineJoin = 'round';
getContext.stroke();
//原本線條的終點作為下一條線的起點
lastX = event.offsetX;
lastY = event.offsetY;
};
最後我們要透過getContext.strokeStyle
以及getContext.lineWidth
這兩種方法來改變我們線條的顏色以及粗細。
hsl(hue, saturation, lightness);
Hue:色相。以紅色為0度(360度);黃色為60度;綠色為120度;青色為180度;藍色為240度;最後又回到紅色,形成一個色相環。
Saturation:飽和度。
Lightness:亮度。
我們要讓.strokeStyle
指定為hsl()
,並讓其中hue
的值在函數執行的同時隨著增加,如此一來就能使線條的顏色持續變化。
將以上兩個條件加入我們code,完成之後就能完成今天的課題囉:
//指定初始的色相為0度角的紅色
var hue = 0;
//增加或縮減的判斷條件
var increase = true;
//指定初始的線寬為1px
var radius = 1;
function createLine(event) {
var newX = event.offsetX;
var newY = event.offsetY;
var getContext = canvas.getContext('2d');
getContext.beginPath();
getContext.moveTo(lastX, lastY);
getContext.lineTo(newX, newY);
//將繪出的線寬指定為變數'radius'
getContext.lineWidth = radius;
getContext.lineCap = 'round';
getContext.lineJoin = 'round';
//將繪出的線顏色指定為hsl
getContext.strokeStyle = `hsl(${hue}, 100%, 50%)`;
getContext.stroke();
lastX = event.offsetX;
lastY = event.offsetY;
//隨著函式執行色相角度增加而改變顏色
hue++;
//當radius >= 100 或 radius <1 判斷值改為相反
if(radius >= 100 || radius <1) {
increase = !increase;
};
//布林值為True的時候radius持續增加
if(increase) {
radius++;
//布林值為False的時候radius持續減少
} else {
radius--;
}
};
今天雖然只有學到<canvas>
元素,但裡頭包含了許多有趣的屬性,還有如何在上面繪製出各種圖形,而這邊也嘗試利用圓型取代線做出類似滴水感覺,有興趣的讀者可以從實作二的連結玩玩看。感謝您的閱讀。