1. 程式人生 > >canvas學習(一):線條,圖像變換和狀態保存

canvas學習(一):線條,圖像變換和狀態保存

itl height tar 默認 class limit 方法 星空 stop

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,strokeWidth,strokeColor,fillColor) {
	var canvas = document.getElementById(ele)
	var 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 = strokeWidth
	ctx.fillStyle= fillColor
     ctx.strokeStyle = strokeColor

	//執行繪制
	ctx.fill()
	ctx.stroke() 
}
		
draw("canvas",50,50,200,300,20,"#ddd","#333")

  

四:矩形,覆蓋和透明色

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()

  

canvas學習(一):線條,圖像變換和狀態保存