致懂得努力的我們
夫君子之行,靜以修身研叫,儉以養(yǎng)德锤窑。非淡泊無以明志,非寧靜無以致遠(yuǎn)嚷炉。夫?qū)W須靜也渊啰,才須學(xué)也,非學(xué)無以廣才申屹,非志無以成學(xué)绘证。
淫慢則不能勵精,險躁則不能治性独柑。年與時馳迈窟,意與日去,遂成枯落忌栅,多不接世车酣,悲守窮廬,將復(fù)何及索绪!
2018.12.12晚上 帶大家一起實現(xiàn)你畫我猜的畫板
主要內(nèi)容
- Canvas api講解
- 繪畫
- 橡皮擦
- 圖片生成
- 本地保存
- 畫筆切換
公開課時間:
12月12日 晚上 20:00~21:30
在線地址:
https://ke.qq.com/course/58689
教室地址:
北京昌平區(qū)回龍觀東大街地鐵A口出湖员,向西走100米(緊鄰?fù)侍茫┒?01教室
Canvas簡述
Canvas 是HTML5新增的元素,讓我們通過JavaScript腳本來繪制圖像, 可以用JavaScript在上面繪制各種圖表瑞驱、動畫等娘摔。
基于Canvas的一些庫:
chartjs(圖表)
https://www.chartjs.org/EaselJS
http://www.createjs.cc/easeljs/
Canvas基本用法
創(chuàng)建一個畫布
<canvas id="canvas" width="300" height="300">
<p>你的瀏覽器不支持Canvas</p>
</canvas>
如果你的瀏覽器不支持canvas標(biāo)簽,則標(biāo)簽內(nèi)的文字會被顯示出來
canvas跟img元素很相像唤反,唯一不同的是它沒有src和alt屬性凳寺,canvas標(biāo)簽(除了選擇器)只有width和height兩個屬性鸭津,canvas 如果不設(shè)置寬高,默認(rèn) 300*150肠缨。
獲取渲染上下文
var canvas = document.querySelector('#canvas')
// 獲取2D畫布的渲染上下文
var ctx = canvas.getContext('2d')
context.getContext() 獲取渲染上下文逆趋,該對象提供了用于在畫布上繪圖的方法和屬性
提示:在未來,如果 canvas 標(biāo)簽擴展到支持 3D 繪圖晒奕,getContext() 方法可能允許傳遞一個 "3d" 字符串參數(shù)闻书。
console.log(ctx) // 2D渲染上下文對象
從畫一條直線開始
JS
// 通過canvas元素設(shè)置寬高
canvas.width = 400
canvas.height = 400
// 設(shè)置線條寬度
ctx.lineWidth = 10
// 設(shè)置畫筆開始繪制坐標(biāo)(落筆點)
ctx.moveTo(100, 100)
// 連接點
ctx.lineTo(300, 300)
// 設(shè)置繪制顏色
ctx.strokeStyle = 'red'
// 根據(jù)moveTo和lineTo定制的路徑 進行繪制
ctx.stroke()
頁面效果
繪制路徑
canvas繪圖是基于路徑的,肉眼看不到脑慧,先進行路徑繪制 然后再通過 fill(填充)或 stroke(描邊)等方法進行填充或繪制魄眉。
涉及api講解
lineWidth
設(shè)置當(dāng)前繪制線條的寬度。默認(rèn)值:1像素moveTo(x, y)
相當(dāng)于畫筆落筆點 開始一條路徑 相對于畫布左上角 x軸坐標(biāo) y軸坐標(biāo)lineTo(x, y)
指定連接點坐標(biāo)闷袒,自動和上一個坐標(biāo)點進行連接 繪制路徑 相對于畫布左上角 x軸坐標(biāo) y軸坐標(biāo)strokeStyle
設(shè)置通過stroke 繪制描邊的顏色坑律。默認(rèn)值:#000stroke
根據(jù)moveTo和lineTo定制的路徑 進行繪制描邊
繪制幾何圖形
繪制三角形
HTML
<canvas id="canvas" width="600" height="600"></canvas>
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
// 設(shè)置繪制線條寬度
ctx.lineWidth = 10
// 設(shè)置繪制線條顏色
ctx.strokeStyle = 'red'
// 設(shè)置填充顏色
ctx.fillStyle = 'pink'
// 開始一條全新的繪制路徑
ctx.beginPath()
// 制定路徑
ctx.moveTo(300, 50)
ctx.lineTo(550, 500)
ctx.lineTo(50, 500)
// 閉合路徑
ctx.closePath()
// 進行填充
ctx.fill()
// 進行繪制
ctx.stroke()
頁面效果
涉及api講解
fillStyle
設(shè)置填充色 默認(rèn)值:#000fill
根據(jù)fillStyle 對當(dāng)前路徑進行填充beginPath
開始一條全新的繪制路徑closePath
閉合當(dāng)前路徑,創(chuàng)建從當(dāng)前點到開始點的路徑
路徑相關(guān)方法講解
1.beginPath
開始一個全新繪制的路徑
假如我要繪制兩條顏色不同的平行線條
HTML
<canvas id="canvas" width="600" height="600"></canvas>
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
ctx.moveTo(100, 100)
ctx.lineTo(500, 100)
ctx.strokeStyle = 'yellow'
ctx.stroke()
ctx.moveTo(100, 200)
ctx.lineTo(500, 200)
ctx.strokeStyle = 'red'
ctx.stroke()
ctx.moveTo(100, 300)
ctx.lineTo(500, 300)
ctx.strokeStyle = 'blue'
ctx.stroke()
不加beginPath情況下囊骤,后面stroke 會從最初路徑開始坐標(biāo)重新繪制一遍 導(dǎo)致之前路徑描邊顏色發(fā)生疊加
在每一次moveTo之前 加上beginPath方法 開始一個全新路徑
JS
// 通常習(xí)慣在第一次的時候也加上beginPath 讓代碼看上去一致
ctx.beginPath()
ctx.moveTo(100, 100)
ctx.lineTo(500, 100)
ctx.strokeStyle = 'yellow'
ctx.stroke()
ctx.beginPath()
ctx.moveTo(100, 200)
ctx.lineTo(500, 200)
ctx.strokeStyle = 'red'
ctx.stroke()
ctx.beginPath()
ctx.moveTo(100, 300)
ctx.lineTo(500, 300)
ctx.strokeStyle = 'blue'
ctx.stroke()
添加beginPath后
效果如下:
2.closePath
假如我們繪制一個幾何圖形如上脾歇,closePath會創(chuàng)建從當(dāng)前結(jié)束點到開始點的路徑 形成閉合路徑
JS
ctx.lineWidth = 10
ctx.strokeStyle = 'red'
ctx.fillStyle = 'pink'
ctx.beginPath()
ctx.moveTo(300, 50)
ctx.lineTo(550, 500)
ctx.lineTo(50, 500)
ctx.fill()
ctx.stroke()
不加closePath時 是這樣
添加上closePath
JS
ctx.lineWidth = 10
ctx.strokeStyle = 'red'
ctx.fillStyle = 'pink'
ctx.beginPath()
ctx.moveTo(300, 50)
ctx.lineTo(550, 500)
ctx.lineTo(50, 500)
// 閉合路徑
ctx.closePath()
ctx.fill()
ctx.stroke()
添加closePath
效果如下:
closePath例子:
JS
ctx.lineWidth = 10
ctx.strokeStyle = 'red'
ctx.beginPath()
ctx.moveTo(300, 100)
ctx.lineTo(500, 500)
ctx.lineTo(300, 500)
ctx.closePath()
ctx.lineTo(100, 500)
ctx.stroke()
效果如下:
繪制矩形
rect(x, y, width, height)
創(chuàng)建一個矩形,需要通過stroke() 進行繪制
JS
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')
ctx.strokeStyle = 'red'
ctx.beginPath()
ctx.rect(100, 100, 300, 300)
ctx.stroke()
效果如下:
strokeRect(x, y, width, height)
根據(jù)strokeStyle指定顏色進行矩形描邊淘捡,繪制無填充色的矩形。
同 rect+stroke 一樣效果
JS
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')
ctx.beginPath()
ctx.lineWidth = 10
ctx.strokeStyle = 'red'
ctx.rect(100, 100, 300, 300)
ctx.stroke()
效果如下:
fillRect(x, y, width, height)
繪制具有填充色的矩形
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
ctx.beginPath()
ctx.fillStyle = 'blue'
ctx.fillRect(100, 100, 300, 300)
效果如下:
完整繪制一個矩形
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
ctx.lineWidth = 10
ctx.fillStyle = 'blue'
ctx.strokeStyle = 'red'
// 方式一
ctx.fillRect(100, 100, 200, 200)
ctx.strokeRect(100, 100, 200, 200)
// 方式二
ctx.rect(320, 100, 200, 200)
ctx.fill()
ctx.stroke()
繪制帶陰影矩形
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
// 陰影模糊度
ctx.shadowBlur = 20
// 陰影顏色
ctx.shadowColor = 'black'
// 繪制帶藍(lán)色填充色的矩形
ctx.fillStyle = 'blue'
ctx.fillRect(100, 100, 200, 200)
線條相關(guān)屬性
lineCap
設(shè)置線條兩端線帽的樣式 context.lineCap=“butt|round|square”;
注意:"round" 和 "square" 值會使線條略微變長池摧。
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
ctx.lineWidth = 20
ctx.beginPath()
ctx.moveTo(100, 100)
ctx.lineTo(500, 100)
// 默認(rèn)值
ctx.lineCap = 'butt'
ctx.stroke()
ctx.beginPath()
ctx.moveTo(100, 200)
ctx.lineTo(500, 200)
// 兩末端圓形線帽
ctx.lineCap = 'round'
ctx.stroke()
ctx.beginPath()
ctx.moveTo(100, 300)
ctx.lineTo(500, 300)
// 兩末端方形線帽
ctx.lineCap = 'square'
ctx.stroke()
效果如下:
繪制圓形
arc
JavaScript 語法:
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
參數(shù)
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
ctx.lineWidth = 10
ctx.beginPath()
ctx.arc(300, 300, 100, 0, Math.PI * 2, false)
ctx.strokeStyle = 'blue'
ctx.fillStyle = 'red'
ctx.fill()
ctx.stroke()
效果如下:
開始角與結(jié)束角:
繪制半圓
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
ctx.lineWidth = 10
ctx.beginPath()
// 逆時針繪制
ctx.arc(300, 300, 100, 0.5 * Math.PI, 1.5 * Math.PI, true)
ctx.strokeStyle = 'green'
ctx.fillStyle = 'red'
ctx.fill()
ctx.stroke()
效果如下:
繪制五角星
JS
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
// 計算x軸坐標(biāo)值
// X = Math.cos(弧度) * 半徑 + 圓心x軸坐標(biāo)
var cx = function(i, r, x, d) {
return Math.cos((d + i * 72) / 180 * Math.PI) * r + x
}
// 計算y軸坐標(biāo)值
// Y = Math.sin(弧度) * 半徑 + 圓心y軸坐標(biāo)
var sy = function (i, r, y, d) {
return -Math.sin((d + i * 72) / 180 * Math.PI) * r + y
}
/**
* @desc 繪制五角星
* @param {Object} ctx 2d渲染上下文
* @param {Number} r 內(nèi)圓半徑
* @param {Number} R 外圓半徑
* @param {Number} x 圓心x軸位置
* @param {Number} y 圓心y軸位置
* @param {Color} fillColor 填充色
* @param {Color} strokeColor 描邊色
*
*/
function drawStart(ctx, r, R, x, y, fillColor, strokeColor) {
ctx.fillStyle = fillColor
ctx.strokeStyle = strokeColor
ctx.beginPath()
// 繪制五個角
for (var i = 0; i < 5; i++) {
// 繪制外圓路徑
ctx.lineTo( cx(i, R, x, 18), sy(i, R, y, 18))
// 繪制內(nèi)圓路徑
ctx.lineTo( cx(i, r, x, 54), sy(i, r, y, 54))
}
ctx.closePath()
ctx.fill()
ctx.stroke()
}
drawStart(ctx, 100, 200, 300, 300, 'red', 'white')
效果如下:
五角星數(shù)學(xué)知識補下
// 求弧度
// 為L = n(圓心角度數(shù))× π × r(半徑)/180(角度制)
// 對邊與斜邊的比叫做正弦(sine)焦除,記作sin
// 鄰邊與斜邊的比叫做余弦(cosine),記作cos
// 對邊與鄰邊的比叫做正切(tangent)作彤,記作tan
// JS Math.sin() 與 Math.cos() 用法
// Math.sin(x) x 的正玄值膘魄。返回值在 -1.0 到 1.0 之間
// Math.cos(x) x 的余弦值。返回的是 -1.0 到 1.0 之間的數(shù)
// 這兩個函數(shù)中的X 都是指的“弧度”而非“角度”竭讳,
// 弧度的計算公式為:2 * PI / 360 * 角度
// 30° 角度 的弧度 = 2 * PI / 360 * 30
// 如何得到圓上每個點的坐標(biāo)创葡?
// 在圓的坐標(biāo)系中 半徑r為斜邊 x軸為鄰邊 y軸為對邊
// 正弦 = y / r
// 余弦 = x / r
// 解決思路:根據(jù)三角形的正弦、余弦來得值
// 假設(shè)一個圓的圓心坐標(biāo)是(a, b)绢慢,半徑為r
// X = 圓心x軸坐標(biāo) + 弧度的余弦值 * 半徑
// 則圓上每個點的X坐標(biāo)= a + Math.cos(2 * Math.PI / 360) * r
// Y = 圓心y軸坐標(biāo) + 弧度的正弦值 * 半徑
// Y坐標(biāo) = b + Math.cos(2 * Math.PI / 360) * r
// 計算x軸坐標(biāo)值
// X = Math.cos(弧度) * 半徑 + 圓心x軸坐標(biāo)
var cx = function(i, r, x, d) {
return Math.cos((d + i * 72) / 180 * Math.PI) * r + x
}
// 計算y軸坐標(biāo)值
// Y = Math.sin(弧度) * 半徑 + 圓心y軸坐標(biāo)
var sy = function (i, r, y, d) {
return -Math.sin((d + i * 72) / 180 * Math.PI) * r + y
}
ctx.lineTo(X, Y)
該文章配套源碼地址
https://github.com/Lwenli1224/canvas_base