canvas學(xué)習(xí)筆記

  • 最基本的使用
    • 創(chuàng)建一個(gè)畫布
      1. 所有的操作都在畫布的context上面
      2. canvas是基于狀態(tài)而不是基于對(duì)象的,比如說(shuō)顏色都是賦值給context,并不是一條線
    • canvas 標(biāo)簽
    <canvas id="myCanvas" height="200" width="100"></canvas>
    
  • 使用javascript來(lái)繪制圖像
    • 基本步驟:
    var c = document.getElementById("myCanvas");//前提是有這個(gè)canvas元素
    var ctx = c.getContext("2d")//創(chuàng)建getContext("2d")對(duì)象
    //下面就可以繪圖了。在ctx對(duì)象上
    
    • getContext(),獲得渲染上下文和他的繪畫功能途茫,只有一個(gè)參數(shù)-上下文的格式
    • 繪制矩形
    fillRect(x,y,width,height)//繪制一個(gè)填充的矩形
    strokeRect(x,y,width,height)//繪制一個(gè)矩形的邊框(也就是一個(gè)帶邊框的矩形啦)
    clearRect(w,y,width,height)//清除指定矩形區(qū)域,讓清楚部分完全透明
    
    • 繪制路徑
    ctx.beginPath()//必須要先新建一條路徑,如果沒(méi)有beginPath()那么,會(huì)從延續(xù)之前的路徑哆键,所謂的延續(xù)表現(xiàn)出來(lái)就是“連著”---從上次結(jié)束的地方開始,如果要想獨(dú)立畫瘦锹,那最好的習(xí)慣就是每次開始前begin籍嘹,結(jié)束后close
    closePath()//閉合路徑之后圖形繪制命令又重新指向到上下文中,在繪制封閉多邊形的時(shí)候闪盔,建議成對(duì)使用
    stroke()//通過(guò)線條來(lái)繪制圖形輪廓
    fill()//通過(guò)填充路徑的內(nèi)容區(qū)域生成實(shí)心的圖形
    
    • 移動(dòng)筆觸
    moveTo(x,y)//相當(dāng)于從哪里開始畫圖的意思
    
    lineTo(x,y)//繪制一條從當(dāng)前位置到指定x,y的直線(這里的x,y是終點(diǎn)),指定線段的終點(diǎn)
    
    • 曲線
      • quadraticCurveTo(cpx,cpy,x,y),二次貝賽爾曲線路徑的方法辱士,接受兩個(gè)點(diǎn)為參數(shù)泪掀,第一個(gè)點(diǎn)是控制點(diǎn),第二個(gè)是終點(diǎn)颂碘,起點(diǎn)在就是當(dāng)前moveTo的點(diǎn)异赫,這樣可以畫一個(gè)基于起點(diǎn)到終點(diǎn),受控于控制點(diǎn)的一個(gè)曲線凭涂,通俗一點(diǎn)的理解就是控制點(diǎn)就像一只手把一條線拽起來(lái)一樣祝辣,注意,并不是把一條直線拽起來(lái)切油,如果是拽直線蝙斜,那就成折線了,而不是曲線澎胡。并且曲線永遠(yuǎn)不會(huì)觸碰到控制點(diǎn)孕荠,而會(huì)在中途偏離控制點(diǎn)。
      • bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)
      • arcTo(cp1x,cp1y,cp2x,cp2y,radius)
    • 圓弧
    arc(x,y,radius,startAngle,endAngle,anticlockwise)//畫一個(gè)以(x,y)為圓心攻谁,radius為半徑稚伍,從startAngle開始到endAngle結(jié)束,按照anticlockwise給定的方向(默認(rèn)為順時(shí)針)來(lái)生成戚宦,需要注意的是startAngle和endAngle的單位是弧度个曙,不是度數(shù),角度與弧度的js表達(dá)式:radians=(Math.PI/180)*degress.
    
    • 色彩
      fillStyle = color設(shè)置圖形的填充顏色受楼,strokeStyle = color設(shè)置線條的顏色

    • 透明度 globalAlpha = transparencyValue,取值范圍0-1

    ctx.globalAlpha = 0.2
    
  • line Styles
lineWidth //設(shè)置線條寬度垦搬,默認(rèn)為1.0
lineCap   //設(shè)置線條末端樣式?什么鬼艳汽,其實(shí)就是線條的帽子猴贰,值有butt/round/square,默認(rèn)值為butt
lineJoin  //設(shè)置線條與線條之間相交處的樣式,值有round/bevel/miter,默認(rèn)是miter
miterLimit//當(dāng)lineJoin屬性設(shè)置為miter的時(shí)候河狐,該屬性可用于控制兩條相交線外側(cè)交點(diǎn)與內(nèi)側(cè)交點(diǎn)的距離米绕,必須是一個(gè)大于零的有限的數(shù)字,默認(rèn)值為10.
getLineDash()//返回一個(gè)包含當(dāng)前虛線樣式馋艺,長(zhǎng)度為非負(fù)偶數(shù)的數(shù)組
setLineDash()//設(shè)置當(dāng)前虛線樣式
lineDashOffset//設(shè)置虛線樣式的起始偏移量

lineCap三個(gè)屬性見(jiàn)下圖


linecap
linecap

lineJoin三個(gè)屬性見(jiàn)下圖


lineJoin
lineJoin
  • 使用虛線
ctx.setLineDash([4,2])//接受一個(gè)數(shù)組作為參數(shù)栅干,來(lái)指定線段與間隙的交替
ctx.lineDashOffset = 0//設(shè)置起始偏移量
  • 漸變
createLinearGradient(x1,y1,x2,y2)//指定漸變的起點(diǎn)和終點(diǎn)
createRadialGradient(x1,y1,r1,x2,y2,r2)//確定兩個(gè)圓
gradient.addColorStop(offset,color)//上色,offset取值范圍是0-1,表示漸變中開始用于結(jié)束之間的位置捐祠,color就是在offset位置顯示的顏色值
用法舉例 
var lineargradient = ctx.createLinearGradient(0,0,150,150);
lineargradient.addColorStop(0,'black')碱鳞;//定義漸變的顏色
ctx.fillStyle = lineargadient;//把漸變顏色給fillstyle或者strokestyle都行
ctx.fillRect(0,0,200,200)//這樣就創(chuàng)建出一個(gè)漸變的矩形
  • 圖案樣式
createPattern(image,type)//image可以是一個(gè)image對(duì)象的引用或者另外一個(gè)canvas對(duì)象,type必須是repeat/repeat-x/repeat-y/no-repeat之一
舉例:
var img = new Image()//第一次見(jiàn)
img.src = 'someImage.png';
img.onloda = function(){
 var ptn = ctx.createPattern(img,'repeat');
 ctx.fillStyle = ptn;
 ctx.fillRect(0,0,150,150)
}
  • 陰影
shadowOffsetX //設(shè)定陰影在x軸上延伸距離雏赦,默認(rèn)為0
shadowBlur //設(shè)定陰影的模糊程度劫笙,默認(rèn)為0
shadowColor //設(shè)定陰影的顏色,默認(rèn)是全透明的黑色
  • 繪制文本
fillText(text,x,y [,maxWidth])//在指定的位置填充指定文本星岗,最大寬度可選
strokeText(text,x,y [,maxWidth])//在指定的位置繪制文本邊框(也就是空心的文字啦)填大,最大寬度可選
舉例:
ctx.font = "48px serif";
ctx.fillText('Hello world',10,50)
  • 文本的樣式
font //設(shè)置字體大小和字體名稱
textAlign //文本對(duì)齊選項(xiàng),值start/end/left/right/center俏橘,默認(rèn)start
textBaseline //基線對(duì)齊選項(xiàng)允华。值top/hanging/middle/alphabetic,ideographic,bottom,默認(rèn)alphabetic
direction //文本方向,值ltr/rtl/inherit,默認(rèn)inherit
  • 測(cè)量文本
    measureText()返回一個(gè)textMetrics對(duì)象的寬度寥掐,所在像素靴寂,體現(xiàn)文本特性的屬性
var text = ctx.measureText('foo');
text.width;//就可以輸出寬度了
  • 應(yīng)用圖像

    canvas圖像操作能力很強(qiáng)大

    • 引入圖像
    1,獲得一個(gè)指向HTMLImageElement的對(duì)象或則另一個(gè)canvas的引用作為源召耘,也可以通過(guò)提供一個(gè)url的 讓是來(lái)使用圖片
    2百炬,使用drawImage()函數(shù)將圖片繪制到畫布上
    
    • 獲得需要繪制的圖片
    HTMLImageElement //由Image()構(gòu)造出來(lái),或者任何的<img>元素
    HTMLVideoElement//可以用一個(gè)html的<video>元素作為圖片遠(yuǎn)污它,抓取某一幀作為一個(gè)圖像
    HTMLCanvasElement//使用一個(gè)<canvas>元素作為圖片源
    ImageBitmap//高性能的位圖剖踊,可以從上述的所有源一集其它幾種源中生成
    
    • 繪制圖片

    所謂繪制圖片就是在圖片上畫的意思

    drawImage(image,x,y)//image是image或者canvas對(duì)象,x衫贬,y是在其目標(biāo)canvas里的起始目標(biāo)
    
    • 縮放圖片
    drawImage(image,x,y,width,height)//參數(shù)比上面多了兩個(gè)德澈,控制當(dāng)canvas畫入的時(shí)候應(yīng)該縮放的大小
    
    • 切片

    也就是裁剪圖片,有點(diǎn)意思

    drawImage(image,sx,sy,sWidth,sHeight,dx,dy,dWidth,dHeight)//參數(shù)見(jiàn)下圖,前5個(gè)和上面的一樣
    
    slicing
    slicing
    • 控制圖像的縮放行為
      cx.mozImageSmoothingEnabled = false //火狐
  • 變形

變形操作都是在對(duì)一個(gè)圖像設(shè)置好屬性之后固惯、繪制之前用的

  • 狀態(tài)的保存和恢復(fù)
    save(), 用來(lái)保存canvas狀態(tài)梆造,canvas狀態(tài)保存在一個(gè)棧中,保存一次葬毫,當(dāng)前的狀態(tài)就入棧镇辉,返回上一步的操作,就是restore()供常,恢復(fù)狀態(tài)
  • 移動(dòng)(translating)
translate(offsetx,offsety)//offsetx是左右偏移量摊聋,offsety是上下偏移量,變形前保存狀態(tài)是個(gè)很好的習(xí)慣,translate移動(dòng)的是canvas和他的原點(diǎn)到一個(gè)不同的位置(也就是將canvas的原點(diǎn)進(jìn)行了偏移)
  • 旋轉(zhuǎn)(rotating)
rotate(angle)//angle是以順時(shí)針為方向栈暇、以弧度為單位的值
  • 縮放(scaling)
scale(x,y)//x麻裁,y是橫軸和縱軸的縮放因子,必須為正值源祈,比1小是縮小煎源,比1大是放大,默認(rèn)情況下香缺,canvas 的 1 單位就是 1 個(gè)像素手销。舉例說(shuō)万伤,如果我們?cè)O(shè)置縮放因子是 0.5拒贱,1 個(gè)單位就變成對(duì)應(yīng) 0.5 個(gè)像素跛溉,這樣繪制出來(lái)的形狀就會(huì)是原先的一半触菜。同理,設(shè)置為 2.0 時(shí)兽埃,1 個(gè)單位就對(duì)應(yīng)變成了 2 像素侥钳,繪制的結(jié)果就是圖形放大了 2 倍。
  • 變形(transforms)
transform(m11,m12,m21,m22,dx,dy)//目前沒(méi)懂

移動(dòng)柄错、旋轉(zhuǎn)舷夺、縮放,是疊加的售貌,比如之前已經(jīng)translate(100,100),左右上下偏移一百给猾,此時(shí)位置為a點(diǎn),如果后面沒(méi)有移回來(lái)颂跨,又用了translat(200,200),那么是在a的基礎(chǔ)上繼續(xù)偏移敢伸,所以這個(gè)時(shí)候restore 的作用就來(lái)了,恢復(fù)狀態(tài)毫捣,恢復(fù)在save時(shí)候的狀態(tài)

  • 動(dòng)畫

所謂動(dòng)畫详拙,就是不停的重繪,達(dá)到一種動(dòng)的視覺(jué)效果

  • 基本步驟

    1. 清空canvas
    2. 保存canvas狀態(tài)
    3. 繪制動(dòng)畫圖形
    4. 恢復(fù)canvas狀態(tài)蔓同,然后重繪下一幀
  • window.requestAnimationFrame(callback)

    用來(lái)在頁(yè)面重繪之前饶辙,通知瀏覽器調(diào)用一個(gè)指定的函數(shù),如果想要得到連貫的逐幀動(dòng)畫斑粱,函數(shù)中必須要重新調(diào)用,用法:
    function callback(){ window.requestAnimationFrame(callback);// 放在第一行 //函數(shù)體 }

  • 動(dòng)畫中的公式

    • 三角學(xué)基礎(chǔ)函數(shù)
      1. sine of angle = opposite/hypotenuse
      2. cosine of angle = adjacent/hypotenuse
      3. tangent of angle = opposite/adjacent
    • 角度與弧度互轉(zhuǎn)
      1. radians = degrees * Math.PI / 180
      2. degrees = radians * 180 / Math.PI
    • 創(chuàng)建波
    (function drawFrame(){
        window.requestAnimationFrame(drawFrame);
        angle += speed;
      }())
    
    • 創(chuàng)建圓形
    (function drawFrame(){
        window.requestAnimationFrame(drawFrame);
        xposition = centerX + Math.cos(angle)*radius;
        yposition = centerY + Math.sin(angle)*radius;
        angle += speed;
    }())
    
    • 創(chuàng)建橢圓形
    (function drawFrame(){
        window.requestAnimationFrame(drawFrame);
        xposition = centerX + Math.cos(angle)*xradius;
        yposition = centerY + Math.sin(angle)*yradius;
        angle += speed;
    }())
    
    • 獲取兩點(diǎn)間的距離
    dx = x2 - x1;
    dy = y2 - y1;
    distance = Math.sqrt(dx*dx + dy*dy)
    
  • 保存文件

    • canvas.toDataURL(type,encoderOptions),type是圖片格式(可選)弃揽,默認(rèn)image/png,encoderOptions是圖片質(zhì)量(可選),默認(rèn)范圍為0-1则北,默認(rèn)值0.92
  • 碰撞檢測(cè)

    碰撞檢測(cè)就是判定兩個(gè)物體是否在同一時(shí)間內(nèi)占用同一塊空間

    • 碰撞檢測(cè)的方法:
      1. 從幾何圖形的角度來(lái)檢測(cè)矿微,就是判斷一個(gè)物體是否和另一個(gè)物體有重疊
      2. 也可以檢測(cè)距離,就是判斷兩個(gè)物體是否足夠近到發(fā)生碰撞尚揣。
    • 基于幾何圖形的碰撞檢測(cè)
      • 兩個(gè)物體間的碰撞檢測(cè)
        1. 邊界框算法:(就是把圖形放到一個(gè)矩形里面涌矢,這個(gè)矩形由位置和大小計(jì)算得來(lái))
        utils.intersectx = function (rectA, rectB) {
          return !(rectA.x + rectA.width < rectB.x ||
              rectB.x + rectB.width < rectA.x ||
              rectA.y + rectA.height < rectB.y ||
              rectB.y + rectB.height < rectA.y)}
        
    • 基于距離的的碰撞檢測(cè)

    先確定兩個(gè)物體的最小距離,再計(jì)算當(dāng)前距離快骗,然后進(jìn)行比較

  • 小結(jié)

    • canvas畫布常用接口
      1. canvas.width
      2. canvas.height
      3. canvas.getContext('2d')
    • 所謂狀態(tài)娜庇,就是顏色、邊框方篮、線條寬度等等這些具體的屬性
    • 矩形的繪制
      1. rect(x, y, width, height),繪制一個(gè)矩形名秀,僅僅是路徑,沒(méi)有任何狀態(tài)(也就是沒(méi)有顏色沒(méi)有邊框)
      2. fillRect(x, y, width, height)藕溅,繪制一個(gè)有填充色的矩形
      3. strokeRect(x, y, width, height)匕得,繪制一個(gè)有邊框的矩形
  • TIPS

    • 一個(gè)有填充色并且描邊的圖像,應(yīng)該先填充后描邊(先f(wàn)ill后stroke)巾表,如果反過(guò)來(lái)的話汁掠,邊的一半會(huì)被填充色覆蓋掉
    • 所謂速度略吨、加速度的問(wèn)題:

    物理上v = at,x=v*t; 在canvas上沒(méi)有時(shí)間的概念考阱,因?yàn)槭侵饚秩镜慕希梢韵胂蟪梢粠褪?s,但是時(shí)間有遞加的概念羔砾,而幀并沒(méi)有,所以對(duì)應(yīng)過(guò)來(lái)如果想要取得有“加速度的效果”偶妖,那么x += a,也就是疊加一個(gè)加速度的值姜凄,這樣就像有了加速度一樣;如果對(duì)應(yīng)過(guò)來(lái)想要取得有“速度”的效果趾访,那么就是x += v,也就是位置疊加一個(gè)速度,這樣就像有了速度一樣

    • 角度問(wèn)題:canvas中逆時(shí)針角度為正,順時(shí)針角度為負(fù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末态秧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子扼鞋,更是在濱河造成了極大的恐慌申鱼,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件云头,死亡現(xiàn)場(chǎng)離奇詭異捐友,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)溃槐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門匣砖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人昏滴,你說(shuō)我怎么就攤上這事猴鲫。” “怎么了谣殊?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵拂共,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我姻几,道長(zhǎng)宜狐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任鲜棠,我火速辦了婚禮肌厨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘豁陆。我一直安慰自己柑爸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布盒音。 她就那樣靜靜地躺著表鳍,像睡著了一般馅而。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上譬圣,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天瓮恭,我揣著相機(jī)與錄音,去河邊找鬼厘熟。 笑死屯蹦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绳姨。 我是一名探鬼主播登澜,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼飘庄!你這毒婦竟也來(lái)了脑蠕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤跪削,失蹤者是張志新(化名)和其女友劉穎谴仙,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碾盐,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晃跺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了毫玖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哼审。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖孕豹,靈堂內(nèi)的尸體忽然破棺而出涩盾,到底是詐尸還是另有隱情,我是刑警寧澤励背,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布春霍,位于F島的核電站,受9級(jí)特大地震影響叶眉,放射性物質(zhì)發(fā)生泄漏址儒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一衅疙、第九天 我趴在偏房一處隱蔽的房頂上張望莲趣。 院中可真熱鬧,春花似錦饱溢、人聲如沸喧伞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)潘鲫。三九已至翁逞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溉仑,已是汗流浹背挖函。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浊竟,地道東北人怨喘。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像振定,于是被迫代替她去往敵國(guó)和親哲思。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一吩案、canvas簡(jiǎn)介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標(biāo)簽 Canvas是一個(gè)矩形區(qū)...
    Looog閱讀 3,942評(píng)論 3 40
  • 一:canvas簡(jiǎn)介 1.1什么是canvas帝簇? ①:canvas是HTML5提供的一種新標(biāo)簽 ②:HTML5 ...
    GreenHand1閱讀 4,691評(píng)論 2 32
  • 一徘郭、canvas簡(jiǎn)介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標(biāo)簽 Canvas是一個(gè)矩形區(qū)...
    J_L_L閱讀 1,520評(píng)論 0 4
  • canvas制造2d環(huán)境: var txt = cvs.grtContext(‘2d’); 繪制矩形: fillR...
    WeekOne閱讀 336評(píng)論 0 0
  • 我讀的高中在鎮(zhèn)子的北邊丧肴,絕大部分學(xué)生來(lái)自鎮(zhèn)周邊的鄉(xiāng)村残揉,都住校,只有鎮(zhèn)里的少數(shù)學(xué)生走讀芋浮。 那時(shí)抱环,我暗戀了一個(gè)叫馬琳的...
    劍膽v琴心閱讀 242評(píng)論 0 0