canvas學習(一):線條,圖像變換和狀態保存
一:繪制一條線段:
var canvas = document.getElementById('canvas') var ctx = canvas.getContext('2d') //狀態設置 ctx.moveTo(0,300) ctx.lineTo(400,300) ctx.lineWidth = 20 ctx.strokeStyle = '#ddd' ctx.stroke() //執行繪制
二:繪制三條不同顏色的線段:
var canvas = document.getElementById('canvas') var ctx = canvas.getContext('2d') ctx.lineWidth = 20 //狀態設置 ctx.beginPath() ctx.moveTo(0,200) ctx.lineTo(400,300) ctx.strokeStyle = '#ddd' ctx.stroke() //執行繪制 ctx.beginPath() ctx.moveTo(100,300) ctx.lineTo(500,300) ctx.strokeStyle = '#333' ctx.stroke() //執行繪制 ctx.beginPath() ctx.moveTo(200,400) ctx.lineTo(600,300) ctx.strokeStyle = '#red' ctx.stroke() //執行繪制
beginPath()表示進行一次新的路徑繪制。
三:多邊形的繪制和closePath
1:封閉箭頭
var canvas = document.getElementById('canvas') var ctx = canvas.getContext('2d') //狀態設置 ctx.moveTo(20,300) ctx.lineTo(400,300) ctx.lineTo(400,200) ctx.lineTo(700,350) ctx.lineTo(400,500) ctx.lineTo(400,400) ctx.lineTo(20,400) ctx.lineTo(20,300) ctx.lineWidth = 20 ctx.strokeStyle = '#ddd' ctx.stroke() //執行繪制
注意:當我們使用上述方法時,線段在封閉時會出現一點點缺口。所以我們需要baginPath和closePath結合使用:
//狀態設置 ctx.beginPath() ctx.moveTo(20,300) ctx.lineTo(400,300) ctx.lineTo(400,200) ctx.lineTo(700,350) ctx.lineTo(400,500) ctx.lineTo(400,400) ctx.lineTo(20,400) //ctx.lineTo(20,300) //這一段可以省略。closePath會自動連接 ctx.closePath() ctx.lineWidth = 20 ctx.strokeStyle = '#ddd' ctx.stroke() //執行繪制
2:填充箭頭:在上述代碼后面添加
ctx.fillStyle="red" ctx.fill()
注意:從這張圖我們可以發現,邊框的寬度變細了。那是因為填充色在邊框色后面執行了,會覆蓋掉邊框的部分顏色。所以我們要記住:
在繪制一個需要填充的描邊圖案時,需要先填充,后描邊
ctx.fillStyle="red" ctx.fill() //填充 ctx.strokeStyle = '#ddd' ctx.stroke() //描邊
因為canvas是基於狀態繪制的,所以我們可以將設置狀態的代碼放一起,將繪制的代碼放一起:
ctx.beginPath() ctx.moveTo(20,300) ctx.lineTo(400,300) ctx.lineTo(400,200) ctx.lineTo(700,350) ctx.lineTo(400,500) ctx.lineTo(400,400) ctx.lineTo(20,400) ctx.lineTo(20,300) ctx.closePath() //狀態設置 ctx.lineWidth = 20 ctx.fillStyle="red" ctx.strokeStyle = '#ddd' //執行繪制 ctx.fill() ctx.stroke()
3:定義一個繪制填充描邊矩形的函數:
function draw(ele,startX,startY,width,height,lineW,fillColor,strokeColor) { var canvas = document.getElementById(ele) ctx = canvas.getContext('2d') ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(startX+width,startY); ctx.lineTo(startX+width,startY+height); ctx.lineTo(startX,startY+height); ctx.closePath(); ctx.lineWidth = lineW; ctx.fillStyle = fillColor ? fillColor: 'black' //默認顏色 ctx.strokeStyle = strokeColor ? strokeColor: '#ddd' //默認顏色 ctx.fill(); ctx.stroke(); } draw("myCanvas", 100, 100, 200, 300, 20)
四:矩形,覆蓋和透明色
1:繪制矩形的方法:rect()
2:繪制填充矩形的方法:fillRect()
3:繪制描邊矩形的方法:strokeRect()
4:設置顏色值:
顏色名,rgb, rgba,hsl, hsla,漸變色等
例如使用漸變色:
var g = ctx.createLinearGradient(0,0,180,0); //創建漸變對象 漸變開始點和漸變結束點 g.addColorStop(0, '#A9D25B'); //添加顏色點 g.addColorStop(1, '#FA5A2D'); //添加顏色點 ctx.strokeStyle = g; //使用漸變對象
五:線段的其他屬性
1:lineCap:設置線段兩端的形狀 ( butt[default],round【圓頭】,square【方頭】)
注意:只能用於線段的開頭出和結尾處
2:lineJoin:設置線段和線段相交時的形態 ( miter[default],bevel【斜切】,round【圓頭】)
3:miterLimit:需要一個非常尖銳的角時:
ctx.lineJoin = "miter" ctx.miterLimit = 10 //這個數字10為默認值
六:畫一個星星
canvas的坐標軸,X軸向右,Y軸向下!
var canvas = document.getElementById("canvas") var ctx = canvas.getContext('2d') function drawStar(ctx,R,r,x,y,rot) { ctx.beginPath(); for (var i = 0; i <=5; i++) { ctx.lineTo( Math.cos((18+i*72 - rot)/180*Math.PI) * R +x, -Math.sin((18+i*72 - rot)/180*Math.PI) * R +y ) ctx.lineTo( Math.cos((54+i*72 - rot)/180*Math.PI) * r +x, -Math.sin((54+i*72 - rot)/180*Math.PI)* r +y ) } ctx.closePath(); ctx.lineWidth = 10; ctx.stroke() } drawStar(ctx,300,150,400,400,20)
七:畫一片星空
var canvas = document.getElementById("canvas") var ctx = canvas.getContext('2d') ctx.fillStyle = "black" ctx.fillRect(0,0,canvas.width,canvas.height) function drawStar(ctx,R,r,x,y,rot) { ctx.beginPath(); for (var i = 0; i <=5; i++) { ctx.lineTo( Math.cos((18+i*72 - rot)/180*Math.PI) * R +x, -Math.sin((18+i*72 - rot)/180*Math.PI) * R +y ) ctx.lineTo( Math.cos((54+i*72 - rot)/180*Math.PI) * r +x, -Math.sin((54+i*72 - rot)/180*Math.PI)* r +y ) } ctx.closePath(); ctx.lineWidth = 3; ctx.lineJoin = "round" ctx.fillStyle="#fb3" ctx.strokeStyle="#fd5" ctx.fill() ctx.stroke() } for(var i=0;i<=100;i++){ var r = Math.random() *10 +10; //var x = Math.random()*canvas.width //var y = Math.random()*canvas.height var x=Math.abs(Math.random()*canvas.width- 2*r)+r; var y=Math.abs(Math.random()*canvas.height- 2*r)+r; var a = Math.random()*360 drawStar(ctx,r,r/2,x,y,a) }
八:圖像變換和狀態保存:
translate() 方法:移動畫布到相應位置
rotate() 方法:旋轉當前的繪圖
scale() 方法:縮放當前繪圖,更大或更小 (副作用:對位置,邊框大小等都會進行改變)
注意:我們在多次使用圖像變化的方法時,后續的使用會在之前使用的基礎上。例如:
ctx.fillStyle = "red" ctx.translate(100,100) // 先執行操作 ctx.fillRect(0,0,400,400) // 后執行繪制 ctx.fillStyle = "green" ctx.translate(300,300) ctx.fillRect(0,0,400,400)
此時第二個點的左邊會基於第一個點移動,所以變成了 400,,40 。此時我們需要用到狀態保存save和restore:
ctx.save() ctx.fillStyle = "red" ctx.translate(100,100) ctx.fillRect(0,0,400,400) ctx.restore() ctx.save() ctx.fillStyle = "green" ctx.translate(300,300) ctx.fillRect(0,0,400,400) ctx.restore()
八:深入理解圖形變換:
利用transform()替換 translate(),rotate(),scale():
注意:當我們在多次使用transform()時,每次的transform()都是基於上次效果之上的。所以我們可以使用setTransform()來回到特定的效果:
ctx.save() ctx.transform(1,0,0,1,50,100) ctx.transform(2,0,0,1.5,50,100) ctx.setTransform(1,0,0,1,50,100) //回到某個狀態 ctx.restore()