成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Canvas 的基本原理

philadelphia / 1752人閱讀

摘要:關(guān)于這兩個(gè)的細(xì)節(jié)直接參考文檔像素操作基于像素的可以實(shí)現(xiàn)針對(duì)單個(gè)像素的操作,這也是畫布底層的,通過調(diào)用方法將返回一個(gè)對(duì)象,該對(duì)象表示畫布中原始的像素信息,通過調(diào)用方法也可以創(chuàng)建一個(gè)空的對(duì)象,最后方法將處理后的像素輸出到畫布中。

過個(gè)年一下荒廢了個(gè)把月。 最近剛接觸canvas,將一些概念點(diǎn)簡單歸納下,canvas是基于像素的圖像API,與svg的最大的區(qū)別在于canvas需要重繪(canvas移除圖片時(shí)需要重新繪制,而SVG可以通過編輯元素節(jié)點(diǎn)來編輯圖片),并且基于基于像素繪制(svg顧名思義是矢量),更詳細(xì)的對(duì)比mark在此:?SVG 與 HTML5 的 canvas 各有什么優(yōu)點(diǎn) 而且我個(gè)人認(rèn)為雖然canvas的API也很復(fù)雜,但是svg更復(fù)雜,囧rz。以下是我將我接觸canvas過程中認(rèn)為需要厘清的概念點(diǎn)歸納如下。

基礎(chǔ)結(jié)構(gòu)

canvas元素本身沒有任何外觀,它就是一塊空白畫板,提供給JS的一套API,最早由Safari引入,IE9之前可以使用一些類庫在IE中模擬canvas,大部分的API都不在canvas元素自身定義,canvas元素自身屬性與常規(guī)的HTML元素并沒有多大區(qū)別, 它的繪圖API都定義在一個(gè)CanvasRenderingContext2D對(duì)象上(這里簡單翻譯成上下文對(duì)象),該對(duì)象通過getContext()方法獲得,代碼示例:



坐標(biāo)系demo






無任何坐標(biāo)系變化的圖像繪制:

translate()方法將坐標(biāo)原定移動(dòng)到(20,20)后得到當(dāng)前坐標(biāo)系后的繪制

了解這點(diǎn)后setTransform()也很容易,該方法影響的是默認(rèn)坐標(biāo)系,也就是說它并非將原點(diǎn)移來移去,而是重置當(dāng)前坐標(biāo)系,定義一個(gè)新的默認(rèn)坐標(biāo)系,什么叫影響默認(rèn)坐標(biāo)系,比如說前面的translate()所移動(dòng)的坐標(biāo)原點(diǎn)(0,0)還是初始的默認(rèn)坐標(biāo)系,而現(xiàn)在setTransform()所影響的就是這個(gè)原點(diǎn)(0,0)的坐標(biāo)系,還是之前的demo,當(dāng)加入ctx.setTransform(1,0.5,-0.5,1,30,10)這條語句后,圖像繪制將變成:

這是因?yàn)?b>setTransform()將默認(rèn)坐標(biāo)系重新定義了,于是translate()基于新的默認(rèn)坐標(biāo)系來得到當(dāng)前坐標(biāo)系。理解了這兩個(gè)概念也就掌握了canvas中坐標(biāo)系的變換。

setTransform()transform()方法

setTransform()這個(gè)API略復(fù)雜, 它所接受的參數(shù)與transform()(使用transform()可直接得到一個(gè)變換結(jié)構(gòu),可代替rotate()等方法,并且更為靈活)一樣為6個(gè)參數(shù),setTransform(a,b,c,d,e,f) 而坐標(biāo)系變化的原理就是通過與這6個(gè)參數(shù)進(jìn)行以下運(yùn)算后得出的:

x" = ax + cy +e
y" = bx + dy +f

這種坐標(biāo)系變換也被稱為仿射變換(affine transform),關(guān)于該變換的栗子可參考這兩篇博客:
?Html5 Canvas 變換矩陣與坐標(biāo)變形之間的關(guān)系

路徑

路徑是繪制所有圖形的基礎(chǔ),不同于SVG中path使用屬性M,L,A等控制的XML文檔,canvas調(diào)用上下文對(duì)象的方法來完成路徑的繪制,調(diào)用beginPath()開始一段新路徑,每段路經(jīng)又有子路徑,正是依靠這些子路徑使得圖形成形。調(diào)用beginPath()后調(diào)用MoveTo()開始一段子路徑。繪制完成后使用closePath()閉合路徑,從而形成一個(gè)閉合區(qū)域,這時(shí)候就可以使用fill()等方法填充該區(qū)域了。每次開始一段新路徑的繪制必須再次調(diào)用beginPath(),否則新繪制的路徑將作為之前路徑的子路徑繼續(xù)繪制。

類似于lineTo()是最簡單的直線段路徑方法, canvas還提供了bezierCurveTo()quadraticCurveTo()這些復(fù)雜的曲線路徑方法,非常復(fù)雜,所以估計(jì)一般這種操作還是先找輪子解決。

另外需要注意的是,當(dāng)一條路徑的兩條子路徑不相交的時(shí)候(比如繪制一個(gè)鏤空的圖形),畫布將采用“非零繞數(shù)原則”判斷某點(diǎn)是在路徑內(nèi)還是路徑外, 這樣以便于填充的時(shí)候區(qū)別哪些區(qū)域是需要填充的。

有關(guān)非零繞數(shù)原則的原理可以參考這里:mark? 非零環(huán)繞數(shù)規(guī)則和奇-偶規(guī)則

canvas的圖像狀態(tài)

canvas的屬性與方法與我們面向?qū)ο笾械膶傩苑椒ú]有太大區(qū)別,只是這里涉及到了一個(gè)圖像狀態(tài)的概念。在canvas中,無法通過getContext()方法獲得多個(gè)上下文(context)對(duì)象,而圖像屬性都是基于canvas的上下文對(duì)象,也就是說無法同時(shí)擁有兩個(gè)屬性。形象地比喻就是圖像屬性就像畫筆, 粗細(xì),大小,顏色。由于同一時(shí)間只能有一個(gè)上下文對(duì)象所以只能同一時(shí)間使用一支畫筆。這時(shí)候當(dāng)需要其它的圖像屬性(另一支畫筆)的時(shí)候就只能通過保存當(dāng)前圖像狀態(tài),然后新建一個(gè)圖像狀態(tài)來切換。

這時(shí)候就需要借助save()restore()來切換圖像狀態(tài),每次save()都將保存當(dāng)前圖像狀態(tài),圖像狀態(tài)包括當(dāng)前的圖像屬性,當(dāng)前坐標(biāo)系,裁剪區(qū)域等信息。比如以下demo以兩種顏色畫線:

直接在demo中修改代碼觀察圖像狀態(tài)demo
JS代碼:

var canvas = document.getElementById("square")

var ctx = canvas.getContext("2d")

ctx.beginPath()
ctx.strokeStyle = "red"
ctx.moveTo(0,0)
ctx.lineTo(100,20)
ctx.stroke()
ctx.save()//保存當(dāng)前圖像狀態(tài)(畫筆)

ctx.beginPath()
ctx.strokeStyle = "blue"
ctx.moveTo(0,0)
ctx.lineTo(100,40)
ctx.stroke()
ctx.restore()//恢復(fù)到最近保存圖像狀態(tài)(畫筆)

ctx.beginPath()
ctx.moveTo(0,0)
ctx.lineTo(100,60)
ctx.stroke()

輸出如下:

這些圖像屬性包括:

fillStyle

font

globalAlpha

globalCompositeOperation

lineCap

lineJoin

lineWidth

miterLimit

textAlign

textBaseline

shadowBlur

shadowColor

shadowOffsetX

shadowOffsetY

strokeStyle

canvas背景

一般的純色背景填充可以使用fillStyle屬性,但是當(dāng)涉及更復(fù)雜的圖片或者漸變色填充就需要CanvasPatternCanvasGradient對(duì)象了,可以通過creatPattern()方法得到CanvasPattern,這里需要注意的是該API不僅可以代入一般的圖片,也可以使用canvas元素,比如畫面外一個(gè)不可見的canvas元素用于插入。
關(guān)于這兩個(gè)API的細(xì)節(jié)直接參考文檔:

?CanvasPattern
?CanvasGradient

像素操作

基于像素的canvas可以實(shí)現(xiàn)針對(duì)單個(gè)像素的操作,這也是畫布底層的API,通過調(diào)用getImageData()方法將返回一個(gè)ImageData對(duì)象,該對(duì)象表示畫布中原始的RGBA像素信息,通過調(diào)用creatImageData()方法也可以創(chuàng)建一個(gè)空的ImageData對(duì)象,最后putImageData()方法將處理后的像素輸出到畫布中。

微軟有篇不錯(cuò)的教程(使用 Canvas 將彩色照片變成黑白照片)解釋像素操作,其中的操作是將彩色照片轉(zhuǎn)成灰白,使用的原理是將RGB三個(gè)分量提取出來,經(jīng)過計(jì)算后(關(guān)鍵計(jì)算語句如下)重新賦值為灰度變量。

myGray = parseInt((myRed + myGreen + myBlue) / 3);

          // Assign average to red, green, and blue.
          myImage.data[i] = myGray;
          myImage.data[i + 1] = myGray;
          myImage.data[i + 2] = myGray;

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78709.html

相關(guān)文章

  • 基于Canvas動(dòng)畫基本原理與數(shù)理分析

    摘要:注以下所有代碼托管到動(dòng)畫的數(shù)理分析有了前面的基礎(chǔ)知識(shí),現(xiàn)在我們就會(huì)想如果我們能夠在每秒幀,內(nèi)渲染張圖像,并且每一張圖像的內(nèi)容發(fā)生微調(diào),那么在秒鐘整個(gè)畫面就會(huì)產(chǎn)生動(dòng)畫效果了。 什么是動(dòng)畫? 就像思考哲學(xué)問題無法回避思維和存在的關(guān)系一樣,制作動(dòng)畫同樣無法逃避的問題是動(dòng)畫的原理是什么?這里提一句題外話,任何原理的東西通常難以讓你短期拾掇成果,但在隱約的未來會(huì)起到難以置信的效果,不信就看接下來...

    genedna 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<