首頁  >  文章  >  web前端  >  突破canvas語法限制 讓他支援鍊式語法_html5教學技巧

突破canvas語法限制 讓他支援鍊式語法_html5教學技巧

WBOY
WBOY原創
2016-05-16 15:50:341303瀏覽

先來看一段正常的canvas畫圖語法:

複製程式碼
程式碼如下:


程式碼如下:



程式碼如下:



程式碼如下:ctx.arc(centerX,centerY,radius,0,PI*2,true);
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowBlur = "10" ;
ctx.fill();
ctx.beginPath();
ctx.shadowColor = 'rgba(0,0,0,0)';
ctx.moveTo(centerX-radius, centerY);
ctx.lineTo(centerX-radius,centerY - 50);
ctx.lineTo(centerX radius,centerY - 50);
ctx.lineTo(centerX radius,centerY); // ctx.lineTo(centerX-radius,centerY);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'rgba(255,0,0,1)' ;
ctx.arc(centerX,centerY-50,radius,0,PI*2,true);
ctx.fill();
我對canvas原生語法不爽的有兩點:1是每句前面都有寫ctx(即canvas的context2d物件),2是每個函數或屬性都要佔一行,浪費空間。 我對jQuery的鍊式語法很欣賞,例如:


複製程式碼


複製程式碼
程式碼
$('#div1').show(300).html(p).delay(3000).slideUp(300).remove();


所以,我也想用這種文法來進行canvas繪圖:





複製程式碼

程式碼如下:
程式碼如下:
程式碼如下:



程式碼如下:


ctx.moveTo(500,0).lineTo(500,500).strokeStyle('#f00').stroke();


有個辦法就是模擬一個context2d物件支援所有的原生context2d方法,但又支援鍊式。

不過,程式碼不能太多,多了就沒人喜歡用了。

下面就是完整的程式碼段,這個「類別」我取名為XtendCanvas(又是以X開頭的喲):





複製程式碼


程式碼如下:


// 讓canvas支援鍊式語法,來自十年燈
~function () {var pro = ['save ','restore', 'scale', 'rotate', 'translate', 'transform', 'createLinearGradient', 'createRadialGradient', 'getLineDash', 'clearRect', 'fillRect', 'beginPath', 'closePath', 'moveTo', 'lineTo', 'quadraticCurveTo', 'bezierCurveTo', 'arcTo', 'rect', 'arc', 'fill', 'stroke', 'clip', 'isPointInPath', 'measureText', 'clearShadow ', 'fillText', 'strokeText', 'strokeRect', 'drawImage', 'drawImageFromRect', 'putImageData', 'createPattern', 'createImageData', 'getImageData', 'lineWidth','strokeStyle','glod 'fillStyle','font','shadowOffsetX','shadowOffsetY','shadowBlur','shadowColor','lineCap','lineJoin','miterLimit'];
function XtendCanvas (canvas) {
<.> var ctx = canvas.getContext('2d'),
fn = function(){},
fnP = fn.prototype; for(var j = 0,p=pro[0] ;p;p=pro[j ]) { fn.prototype[p] = function (p) { return function () { var args = Array.prototype.slice.call(arguments) ;
// console.log(args);
if(typeof ctx[p] == 'function') {
ctx[p].apply(ctx,args);
} else {
ctx[p] = args '';
}
return fnP;
}; }(p); } return new fn; }; window.XtendCanvas = XtendCanvas;}();使用方法很簡單,給他傳一個canvas對象,他就會返回一個類似context2d的對象,你可以像普通的context2d一樣使用,但不同的是,他支援鍊式語法了:複製程式碼程式碼如下:var cvs = document.getElementById('cvs');var ctx = XtendCanvas(cvs);ctx.moveTo(500,0).lineTo0(500,ctx.moveTo(500,0).lineTo0) .strokeStyle('#f00').stroke();
這樣一來你就可以把所有操作都放在一句話裡,你也可以隨時中斷,做其他的事,然後繼續。

這段程式碼並不是對canvas的增強,只是單純的讓他支援鍊式語法了。但勝在程式碼少,可以嵌入任何JS函式庫中,在此我希望能得到你的一個「推薦」

程式碼中肯定有值得改進的地方,大家可以自行完善。但——吃水不忘挖井人,希望大家記得我,最重要的是思路,對吧?下面就是想法:
大家可以看到,程式碼中最長的部分,是那個保存方法名稱的陣列pro,核心程式碼反而很短。為什麼我要蓋這麼一個陣列呢?

本來我也想直接從CanvasRenderingContext2D繼承所有原生方法,但每個瀏覽器下面遍歷這個CanvasRenderingContext2D,結果都不一致。如果我把他們直接繼承,那麼當你想用chrome中的方法套在firefox裡執行,就會報錯。

所以我只是把CanvasRenderingContext2D中的通用的,無異議的方法與屬性名提取了出來,沒辦法,只有建一個固定的數組——大家可以自行決定往裡面添加你的方法。

方法與屬性提取出來了,接著就是把原生的方法加在我的新物件上。我建了一個叫fn的空函數,放置我的方法。

由於數組中的這些元素既有函數,也有屬性,所以我在循環中判斷了他是否是一個函數,如果是函數,就帶參數執行;不是函數——那麼就肯定是屬性了,就把參數賦給這個屬性。

這樣大家在碰到設定canvas屬性的時候,就不用中斷鏈了,直接把屬性值當參數傳進去就行了,比如:

複製程式碼
程式碼如下:

ctx.strokeStyle('#f00')

最後,關鍵的關鍵,就是返回fn,這招是從jQuery學來的,是支援鍊式語法的關鍵。

這段中用到了匿名函數,閉包,原型,以及我以前文章講過的奇怪的for循環。

說起來好像挺簡單的,不過我實在是想了很久,希望對大家有用。

在寫程式碼的過程中,我發現chrome的做法很不錯,他有一串以set開頭的函數,如setStrokeColor,setLineCap等函數,給他們傳參數,就可以取代對應的strokeStyle和lineCap等屬性,也就是說,他的canvas裡面就全是函數而沒有屬性了那樣的話我就不用判斷是函數還是屬性了。但firefox裡面沒有這些,所以我還是只能用前面的想法。

我也把那一串set函數給放出來吧

複製代碼
代碼如下:

var bak = ['setTransform','setAlpha', 'setCompositeOperation', 'setLineWidth', 'setLineCap', 'setLineJoin', 'setMiterLimit', 'setMiterLimit' ','setShadow','setStrokeColor','setFillColor'];

他們的用處一看就懂。你也可以選擇一些加入前面程式碼的pro數組中。

最後,我很奇怪我的程式碼怎麼會沒有高亮了。 。 。如果你都看到最後了,那麼還是給個推薦吧,讓我也虛榮一把
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn