嗯,那個,我是來試水的,跟你們這些大神不能比,所以就為小小白們總結一下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() // 全部填充
複製程式碼
這樣做,我們就可以得到下面這個圖
再來個空心的像這樣的
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)
複製程式碼
矩形的故事先說到這裡,下面我們來說說圓形那個傢伙
- 一個球的故事
跟矩形的套路差不多 ,我們常用來畫圓的是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()
複製程式碼
然後差不多就是這個樣子了
第三話 貝塞爾的約會
在說約會的故事前,先來認識一下牽線人 線段
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第一個研究了這種向量繪製曲線的方法,並給出了詳細的計算公式,因此按照這樣的公式繪製出來的曲線就用他的姓氏來命名,稱為貝塞爾曲線。來見識一下貝塞爾如何?下面是五階貝塞爾曲線的繪製過程
如果覺得太複雜,那我們先來看二階的,是不是好很多
繪製貝塞爾曲線(貝濟埃、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
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為中心,向前向後畫曲線,然後就這樣了,當然如果想要畫更復雜的圖,可以在好好研究一下
- 還有一點值得注意,精確畫圖時,我們要考慮一下線條的畫素會不會對你的圖有影響?
比如說,我們想要一個1畫素的,但是結果卻不太像1畫素的
這是因為計算機不允許出現小於1px的圖形,所以他做了一個折中的事:把這兩個畫素都繪製了。所以,如此一來,本來1px的線條,就成了看起來2px寬的線。也就是說這個1畫素為了能生存下去,就向左向右跨了0.5畫素,也就成了2畫素
為了解決這個問題,聰明的人們還是想到了辦法的,那就是給需要的地方加上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);
複製程式碼
- 嗯,我是陰影
context.shadowOffsetX :陰影的橫向位移量(預設值為0) context.shadowOffsetY :陰影的縱向位移量(預設值為0) context.shadowColor :陰影的顏色 context.shadowBlur :陰影的模糊範圍(值越大越模糊)
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:繪製時要使用的顏色
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:繪製時要使用的顏色
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);複製程式碼
然後就這樣了
位移瞭解一下? 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();
}
複製程式碼
縮放也瞭解一下吧 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();
複製程式碼
第六話 有情人終成眷屬
我們來簡單結合一下圖形做一個好看的效果,像這樣的
怎麼樣是不是還可以,那就上程式碼
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()
}
}
複製程式碼
最後經過不懈的努力,他們就變成了這個樣紙,程式碼找不到了,反正就是拼在一起就好了^_^