要不要一起了解一下Canvas?

星冉發表於2018-04-28

      嗯,那個,我是來試水的,跟你們這些大神不能比,所以就為小小白們總結一下Canvas的基礎,還望各位多多指教……

第一話   與canvas的初次邂逅

姓名:Canvas
自我介紹:一個預設為寬300,高150的空白畫布,可以使用指令碼來繪製圖形的HTML元素,可以繪製圖表、製作圖片構圖或者製作簡單的動畫

哦,對了,Canvas說他只是一個容器,本身沒有繪製能力,所以他在等一個意中人拿到一個畫布,使之具有繪製各種圖形的能力,他的意中人應該可以做到以下幾點:

 1、 有一個舒適的地方(頁面),一般我們最常用html檔案

 2、 裡面要有標籤,作為h5新標籤,不太支援較老版本的瀏覽器,因此稍稍判斷以下還是可以的,或者說如果你用的瀏覽器版本比較新 ,那可以不用寫‘你的瀏覽器不支援canvas’這句話了,同時我們在標籤上規定id、寬高,這裡的寬高如果拿到外面去設定就會導致canvas變形,所以乖乖仔這裡設,至於其他樣式設定就拿到外面去吧

<canvas id="canvas" width="400" height="500">
你的瀏覽器不支援canvas!
</canvas>
複製程式碼

 3、 獲取到這個畫布,每個canvas節點都有一個對應的context物件(上下文物件),Canvas API定義在這個context物件上面,所以需要獲取這個物件,方法是使用getContext方法。即Canvas.getContext(contextID),引數 contextID 指定了您想要在畫布上繪製的型別。當前唯一的合法值是 "2d",它指定了二維繪圖,並且導致這個方法返回一個環境物件,該物件匯出一個二維繪圖 API。在未來,如果 <canvas> 標籤擴充套件到支援 3D 繪圖,getContext() 方法可能允許傳遞一個 "3d" 字串引數。

var canvas=document.getElementById('canvas')
//獲得畫布
var context=canvas.getContext('2d')
複製程式碼

第二話   他的意中人

  • 跟矩形有關的那點事
在此之前,我們先做一下準備工作:fillReact(座標x,座標y,寬,高):一般用於繪製實心的矩形,與fillStyle() 填充顏色搭配使用;strokeReact(座標x,座標y,寬,高) : 一般繪製空心的矩形,與strokeStyle() 設定邊框顏色搭配使用;
context.benginPath(): 開始路徑;context.closePath() : 結束路徑,值得注意的是  
1、系統預設在繪製第一個路徑的開始點為beginPath                                                 2、如果畫完前面的路徑沒有重新指定beginPath,那麼畫第其他路徑的時候會將前面最近指定的beginPath後的全部路徑重新繪製                                                                    3、每次呼叫context.fill()的時候會自動把當次繪製的路徑的開始點和結束點相連,接著填充封閉的部分,這時也就不用呼叫closePath()了,但是呼叫strock()不會自動閉合

var canvas=document.getElementById('canvas')
//獲得畫布
var context=canvas.getContext('2d')
context.beginPath();               // 開始路徑
context.fillStyle='yellow'         // 設定要填充的顏色
context.fillRect(100,150,100,100) 
context.fill()                     // 全部填充
複製程式碼

這樣做,我們就可以得到下面這個圖

要不要一起了解一下Canvas?

再來個空心的像這樣的

要不要一起了解一下Canvas?

context.beginPath()
context.strokeStyle="red"
context.strokeRect(150,150,100,100)
context.fill()
複製程式碼

什麼?想要個橡皮擦?沒問題,滿足你

context.clearRect(x,y,width,height)  僅支援矩形

context.clearRect(30,30,50,50)
複製程式碼

要不要一起了解一下Canvas?

矩形的故事先說到這裡,下面我們來說說圓形那個傢伙

  • 一個球的故事
跟矩形的套路差不多 ,我們常用來畫圓的是arc , context.arc(x, y, radius, starAngle,endAngle, anticlockwise)  座標位置不用介紹了,後面就是半徑,開始弧度,結束弧度,順逆時針

//繪製圓形
context.beginPath()
context.arc(250,250,20,0,Math.PI*2,true)
context.closePath()
context.fillStyle='rgba(0,255,0,0.25)'
context.fill()
複製程式碼

然後差不多就是這個樣子了

要不要一起了解一下Canvas?

第三話  貝塞爾的約會

在說約會的故事前,先來認識一下牽線人  線段

 context.moveTo(x,y) context.lineTo(x,y)   
 moveTo(x,y) 移動到某一點,但是它只是代表的作畫的起點 lineTo(x,y) 與上面的對應,代表作畫的終點,每次畫線都從moveTo的點到lineTo的點, 如果沒有moveTo那麼第一次lineTo的效果和moveTo一樣, 每次lineTo後如果沒有moveTo,那麼下次lineTo的開始點為前一次lineTo的結束點
Bézier curve(貝塞爾曲線)是應用於二維圖形應用程式的數學曲線。 曲線定義:起始點、終止點、控制點。通過調整控制點,貝塞爾曲線的形狀會發生變化。 1962年,法國數學家Pierre Bézier第一個研究了這種向量繪製曲線的方法,並給出了詳細的計算公式,因此按照這樣的公式繪製出來的曲線就用他的姓氏來命名,稱為貝塞爾曲線。來見識一下貝塞爾如何?下面是五階貝塞爾曲線的繪製過程

要不要一起了解一下Canvas?

如果覺得太複雜,那我們先來看二階的,是不是好很多

要不要一起了解一下Canvas?

繪製貝塞爾曲線(貝濟埃、bezier) context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) 先來說說個個引數都代表什麼  cp1x:第一個控制點x座標       cp1y:第一個控制點y座標 cp2x:第二個控制點x座標       cp2y:第二個控制點y座標       x:終點x座標    y:終點y座標   如果你想要了解他的演算法,可以參考一下這個

http://www.cnblogs.com/wxydigua/p/4204254.html http://www.cnblogs.com/regina1123/p/6256375.html

要不要一起了解一下Canvas?

ctx.beginPath();
ctx.moveTo(75,25);  // 開個頭
ctx.quadraticCurveTo(25,25,25,62.5);
ctx.quadraticCurveTo(25,100,50,100);
ctx.quadraticCurveTo(50,120,30,125);
ctx.quadraticCurveTo(60,120,65,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();
複製程式碼

結果如下,還可以吧,沒那麼醜,至於那個控制點,個人理解為以moveTo為中心,向前向後畫曲線,然後就這樣了,當然如果想要畫更復雜的圖,可以在好好研究一下

要不要一起了解一下Canvas?

  • 還有一點值得注意,精確畫圖時,我們要考慮一下線條的畫素會不會對你的圖有影響?

比如說,我們想要一個1畫素的,但是結果卻不太像1畫素的

要不要一起了解一下Canvas?

這是因為計算機不允許出現小於1px的圖形,所以他做了一個折中的事:把這兩個畫素都繪製了。所以,如此一來,本來1px的線條,就成了看起來2px寬的線。也就是說這個1畫素為了能生存下去,就向左向右跨了0.5畫素,也就成了2畫素

要不要一起了解一下Canvas?

為了解決這個問題,聰明的人們還是想到了辦法的,那就是給需要的地方加上0.5畫素,雖然有點麻煩,但是親測有效

第四話  初識文(文字)陰(陰影)漸(漸變)

  • 我是文字啊
fillText(text, x, y [, maxWidth]) 在指定的(x,y)位置填充指定的文字,繪製的最大寬度是可選的. 當然如果繪製一個空心的也可以,那就這樣strokeText(text, x, y);

ctx.font = "20px Arial";
ctx.textBaseline = "hanging";
ctx.strokeText("Hello ", 50, 50);
複製程式碼

要不要一起了解一下Canvas?

  • 嗯,我是陰影

   context.shadowOffsetX :陰影的橫向位移量(預設值為0) context.shadowOffsetY :陰影的縱向位移量(預設值為0) context.shadowColor :陰影的顏色 context.shadowBlur :陰影的模糊範圍(值越大越模糊)

要不要一起了解一下Canvas?

ctx.shadowOffsetX = 2; //X軸陰影距離,負上,正下
ctx.shadowOffsetY = 2; //Y軸陰影距離,負左,正右
ctx.shadowBlur = 2; //陰影的模糊程度
ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; //陰影顏色
ctx.font = "30px Times New Roman"; //設定字型和字型大小 
ctx.fillStyle = "Black"; 
ctx.fillText("Sample String", 15, 30); //實體文字
ctx.strokeStyle = 'red'; 
ctx.strokeText('Hello world', 15, 100); //邊框文字
複製程式碼

  • 我,我是漸變……
 線性漸變 createLinearGradient(xStart,yStart,xEnd,yEnd)                                          線性漸變顏色addColorStop(offset,color)                                                                   xstart:漸變開始點x座標                                                                                             ystart:漸變開始點y座標                                                                                           xEnd:漸變結束點x座標                                                                                            yEnd:漸變結束點y座標                                                                                          offset:設定的顏色離漸變結束點的偏移量(0~1)                                                       color:繪製時要使用的顏色

要不要一起了解一下Canvas?

let can=document.getElementById('Canvas')
let ctx=Canvas.getContext('2d')
let bg = ctx.createLinearGradient(0, 0, 0, 200); 
bg.addColorStop(0, 'black'); // 開始顏色
bg.addColorStop(0.6, '#fff’);  //結束顏色
ctx.fillStyle = bg;
ctx.fillRect(10, 10, 100, 100);
複製程式碼

徑向漸變(發散)context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd)           徑向漸變(發散)顏色rg.addColorStop(offset,color)                                           xStart:發散開始圓心x座標                                                                                           yStart:發散開始圓心y座標                                                                             radiusStart:發散開始圓的半徑                                                                                xEnd:發散結束圓心的x座標                                                                                     yEnd:發散結束圓心的y座標                                                                             radiusEnd:發散結束圓的半徑                                                                                 offset:設定的顏色離漸變結束點的偏移量(0~1)                                                         color:繪製時要使用的顏色

要不要一起了解一下Canvas?

var bg1 = ctx.createRadialGradient(100, 100, 0, 100, 100, 50);
bg1.addColorStop(0, '#FF5F98');
bg1.addColorStop(0.75, '#FF0188');
bg1.addColorStop(1, 'rgba(255,1,136,0)');
ctx.fillStyle = bg1; 
ctx.fillRect(0,0,150,150);
複製程式碼

第五話   千變萬化

這裡先了解一下狀態:對於canvas 的狀態就是當前畫面應用的所有樣式和變形的一個快照,操作狀態有兩個方法:save() 和 restore (),前者是用來儲存當前狀態,後者用來恢復剛才儲存的狀態,他們都可以多次呼叫,舉個例子

ctx.fillStyle = 'black'; 
ctx.fillRect(20, 20, 150, 150); 
ctx.save(); //儲存當前狀態 
ctx.fillStyle= '#fff’; 
ctx.fillRect(45, 45, 100, 100); 
ctx.restore(); //恢復到剛才儲存的狀態 
ctx.fillRect(70, 70, 50, 50);複製程式碼

然後就這樣了

要不要一起了解一下Canvas?

位移瞭解一下?   ctx.translate(x, y); //更改canvas的原點 

for(var i = 1; i< 4; i++) { 
ctx.save(); 
//使用save方法儲存狀態,讓每次位移時都針對(0,0)移動。 
ctx.translate(100*i, 0); 
ctx.fillRect(0, 50, 50, 50);
ctx.restore(); 
}
複製程式碼

要不要一起了解一下Canvas?

縮放也瞭解一下吧 ctx.scale(x, y); //基於原點縮放,x、y是兩個軸的縮放倍數

var ctx = document.getElementById('canvas').getContext('2d’); 
ctx.fillStyle = 'red’; 
ctx.scale(0.8, 1.2); 
ctx.beginPath(); 
ctx.arc(75, 75, 60, 0, Math.PI * 2); ctx.fill();
複製程式碼

要不要一起了解一下Canvas?

第六話 有情人終成眷屬

要不要一起了解一下Canvas?

我們來簡單結合一下圖形做一個好看的效果,像這樣的

要不要一起了解一下Canvas?

怎麼樣是不是還可以,那就上程式碼

let can=document.getElementById('can')
let context=can.getContext('2d')
//繪製顏色板
for(let i=0;i<6;i++){
   for(let j=0;j<6;j++){
	context.fillStyle='rgb('+Math.floor(255-42.5*i)+','+Math.floor(255-42.5*j)+',0)'
	context.fillRect(i*25,j*25,25,25)
    }
}
//繪製圓形
for(var i=0;i<10;i++){
   for(var j=0;j<10;j++){
	context.strokeStyle='rgb(0,'+Math.floor(255-42.5*i)+','+Math.floor(255-42.5*j)+')'
	context.beginPath()
	context.arc(12.5+j*25,180+i*25,10,0,Math.PI*2,true)
	context.stroke()
  }
}
複製程式碼

最後經過不懈的努力,他們就變成了這個樣紙,程式碼找不到了,反正就是拼在一起就好了^_^

要不要一起了解一下Canvas?

嗯,總結到此先告一段落,希望對你有幫助……


相關文章