歡迎交流,互聯(lián)網(wǎng)產(chǎn)品開發(fā)解決方案CoreThink&OpenCMF:
http://www.corethink.cn
Canvas的應(yīng)用(一)
canvas是Html5中的一個新功能,它可以實現(xiàn)在一個矩形區(qū)域內(nèi)繪制一些簡單圖形的功能,最近很是熱衷于用它去實現(xiàn)一些交互動畫,要說如何應(yīng)用它,一言以蔽之,化繁為簡吧。不考慮時間的維度,在我們眼前定格的每一幀畫面,縱使再精美,也無外乎點(diǎn)線面的結(jié)合,所以能繪制基本的點(diǎn)、線、面也足以實現(xiàn)很多;要是考慮上時間這個維度,結(jié)合視覺暫留原理,就算沒有繪畫基礎(chǔ),也能實現(xiàn)簡單的動畫交互。
一、lineTo()的應(yīng)用——簽名
1.原理
原理其實很簡單,就是用極限的思想去看待鼠標(biāo)或者手指劃出的所有線條,當(dāng)線條無限短,我們就可以將它視為直線,短到什么程度呢,短到由兩個像素構(gòu)成,或水平或垂直或?qū)蔷€,所有的可能也無外乎如此,所以僅僅是lineTo()就能夠?qū)崿F(xiàn)簽名了,所以監(jiān)控鼠標(biāo)的mousemove事件,并獲取當(dāng)前事件對象坐標(biāo)即可。
canvas.addEventListener('mousemove',function(e) {
var x = e.clientX - this.offsetLeft;
var y = e.clientY - this.offsetTop;
Point.push([x,y]);
var len = Point.length;
if(flag) {
ct.beginPath();
ct.moveTo(Point[len-1][0],Point[len-1][1]);
ct.lineTo(Point[len-2][0],Point[len-2][1]);
ct.closePath();
ct.stroke();
}
});
將經(jīng)過的的所有點(diǎn)放在一個數(shù)組中,在當(dāng)前點(diǎn)和上一個點(diǎn)之間繪制路徑,簽名的基本功能就能夠?qū)崿F(xiàn)。
2.在手機(jī)上的實現(xiàn)
需要說明的一點(diǎn)是,在手機(jī)上event對象會有所不同,touches屬性是一個數(shù)組,會獨(dú)立記錄每個觸控點(diǎn)的信息,當(dāng)event.touches.length為1的時候,說明是一個觸控點(diǎn),event.touches.length為2的時候就是多點(diǎn)觸控,簽名自然是單點(diǎn)觸控,所以要獲取當(dāng)前坐標(biāo)就要從touches[0]取得。
canvas.addEventListener('touchmove',function(e) {
event.preventDefault();
if(e.touches.length == 1) {
var x = e.touches[0].clientX - this.offsetLeft;
var y = e.touches[0].clientY - this.offsetTop;
Point.push([x,y]);
var len = Point.length;
if(flag) {
ct.beginPath();
ct.moveTo(Point[len-1][0],Point[len-1][1]);
ct.lineTo(Point[len-2][0],Point[len-2][1]);
ct.closePath();
ct.stroke();
}
}
},false);
3.其他說明
如果僅僅是監(jiān)控move事件,那么在pc端只要鼠標(biāo)滑過就會繪制路徑,所以得設(shè)置一個開始繪制路徑的開關(guān),即將mousedown事件所謂開始繪制的標(biāo)志,mouseup則繪制結(jié)束。 當(dāng)簽名完成之后,調(diào)用canvas的toDataURL()可以獲取畫布內(nèi)的繪制信息,并以圖片的形式保存下來。
當(dāng)然這里其實存在一些遺留問題,如何對簽名進(jìn)行識別,如果需要識別,那是否應(yīng)該先對簽名做一些平滑處理,這一系列問題留待后續(xù)解決。
二、bezierCurveTo()的應(yīng)用1.貝塞爾曲線
關(guān)于貝塞爾曲線具體是什么,這里不做贅述,隨便一搜,各種百科說的很詳細(xì)。這邊主要要說的是貝塞爾曲線如何在canvas中加以應(yīng)用。這邊主要用到的是二次貝塞爾公式,即bezierCurveTo()的應(yīng)用,它有6個參數(shù),前兩個是起始點(diǎn)的坐標(biāo),中間兩個是控制點(diǎn)的坐標(biāo),最后兩個是終點(diǎn)的坐標(biāo),知道起點(diǎn)終點(diǎn)和一個控制點(diǎn),就能繪制我們想要的曲線了。
2.應(yīng)用
仔細(xì)觀察一些網(wǎng)站,很多地方都用到了直線變曲線、仿波浪形狀,或者一些不規(guī)則圖形,能夠?qū)崿F(xiàn)它們就是貝塞爾曲線的功勞,其中很著名的就是qq的消除氣泡。
effect:function(){
},
var canvas = this.canvas,
offset = this.offset,
ct = canvas.getContext("2d"),
ui = this.ui,
x1 = ui.originalPosition.left,
y1 = ui.originalPosition.top,
x = ui.offset.left,
y = ui.offset.top;
var base = Math.sqrt((x1-x)^2+(y1-y)^2),
sin = Math.abs(x1-x)/base,
cos = Math.abs(y1-y)/base;
ct.clearRect(0,0,400,200);
ct.beginPath();
ct.arc(x1,y1,10,0,2*Math.PI,false);
ct.fill();
ct.beginPath();
ct.moveTo(x1+cos,y1-sin);
ct.lineTo(x1-cos,y1+sin);
ct.bezierCurveTo(x1-cos,y1+sin,(x1+x)/2,(y1+y)/2,x-cos,y+sin);
ct.lineTo(x+cos,y-sin);
ct.bezierCurveTo(x+cos,y-sin,(x1+x)/2,(y1+y)/2,x1+cos,y1-sin);
ct.fill();
ct.beginPath();
ct.arc(x,y,10,0,2*Math.PI,false);
ct.fill();
這里貼出部分關(guān)鍵的代碼,就是拖拽那個氣泡出現(xiàn)的拉伸效果,如同拉扯一個有彈性的東西,被拉的越長就會越細(xì),在bezierCurveTo()通過設(shè)置合理的控制點(diǎn)就能很好的實現(xiàn)這個效果。其他更多的應(yīng)用,等有空把代碼寫出來再繼續(xù)咯。
CoreThink_張玥2016.7.4凌晨