溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何突破canvas語(yǔ)法限制讓他支持鏈?zhǔn)秸Z(yǔ)法

發(fā)布時(shí)間:2021-10-14 14:25:18 來(lái)源:億速云 閱讀:128 作者:小新 欄目:web開(kāi)發(fā)

這篇文章給大家分享的是有關(guān)如何突破canvas語(yǔ)法限制讓他支持鏈?zhǔn)秸Z(yǔ)法的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

先來(lái)看一段正常的canvas畫圖語(yǔ)法:

代碼如下:


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();


我對(duì)canvas原生語(yǔ)法不爽的有兩點(diǎn):1是每句前面都有寫ctx(即canvas的context2d對(duì)象),2是每個(gè)函數(shù)或?qū)傩远家家恍?,浪費(fèi)空間。

我對(duì)jQuery的鏈?zhǔn)秸Z(yǔ)法很欣賞,比如:

代碼如下:


$('#div1').show(300).html(p).delay(3000).slideUp(300).remove();


所以,我也想用這種語(yǔ)法來(lái)進(jìn)行canvas繪圖:

代碼如下:


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


有個(gè)辦法就是模擬一個(gè)context2d對(duì)象,這個(gè)對(duì)象支持所有的原生context2d方法,但又支持鏈?zhǔn)健?

不過(guò),代碼不能太多,多了就沒(méi)人喜歡用了。

下面就是完整的代碼段,這個(gè)“類”我取名為XtendCanvas(又是以X開(kāi)頭的喲):

代碼如下:


// 讓canvas支持鏈?zhǔn)秸Z(yǔ)法,來(lái)自十年燈
~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','globalAlpha','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;
}();


使用方法很簡(jiǎn)單,給他傳一個(gè)canvas對(duì)象,他就會(huì)返回一個(gè)類似context2d的對(duì)象,你可以像普通的context2d一樣使用,但不同的是,他支持鏈?zhǔn)秸Z(yǔ)法了:

代碼如下:


var cvs = document.getElementById('cvs');
var ctx = XtendCanvas(cvs);
ctx.moveTo(500,0).lineTo(500,500).strokeStyle('#f00').stroke();


這樣一來(lái)你就可以把所有操作都放在一句話里,你也可以隨時(shí)中斷,做其他的事,然后繼續(xù)。

這段代碼并不是對(duì)canvas的增強(qiáng),只是單純的讓他支持鏈?zhǔn)秸Z(yǔ)法了。但勝在代碼少,可以嵌入到任何JS庫(kù)中,在此我希望能得到你的一個(gè)“推薦”

代碼中肯定有值得改進(jìn)的地方,大家可以自行完善。但——吃水不忘挖井人,希望大家記得我,最重要的是思路,對(duì)吧?下面就是思路:
大家可以看到,代碼中最長(zhǎng)的部分,是那個(gè)保存方法名的數(shù)組pro,核心代碼反而很短。為什么我要建這么一個(gè)數(shù)組呢?

本來(lái)我也想直接從CanvasRenderingContext2D繼承所有原生方法,但每個(gè)瀏覽器下面遍歷這個(gè)CanvasRenderingContext2D,結(jié)果都不一致。如果我把他們直接繼承,那么當(dāng)你想用chrome中的方法套在firefox里執(zhí)行,就會(huì)報(bào)錯(cuò)。

所以我只是把CanvasRenderingContext2D中的通用的,無(wú)異議的方法與屬性名提取了出來(lái),沒(méi)辦法,只有建一個(gè)固定的數(shù)組——大家可以自行決定往里面添加你的方法。

方法與屬性提取出來(lái)了,接著就是把原生的方法加在我的新對(duì)象上。我建了一個(gè)叫fn的空函數(shù),放置我的方法。

由于數(shù)組中的這些元素既有函數(shù),也有屬性,所以我在循環(huán)中判斷了他是否是一個(gè)函數(shù),如果是函數(shù),就帶參數(shù)執(zhí)行;不是函數(shù)——那么就肯定是屬性了,就把參數(shù)賦給這個(gè)屬性。

這樣大家在碰到設(shè)置canvas屬性的時(shí)候,就不用中斷鏈了,直接把屬性值當(dāng)參數(shù)傳進(jìn)去就行了,比如:

代碼如下:


ctx.strokeStyle('#f00')


最后,關(guān)鍵的關(guān)鍵,就是返回fn,這招是從jQuery學(xué)來(lái)的,是支持鏈?zhǔn)秸Z(yǔ)法的關(guān)鍵。

這段中用到了匿名函數(shù),閉包,原型,以及我以前文章講過(guò)的奇怪的for循環(huán)。

說(shuō)起來(lái)好像挺簡(jiǎn)單的,不過(guò)我實(shí)在是想了很久,希望對(duì)大家有用。

在寫代碼的過(guò)程中,我發(fā)現(xiàn)chrome的做法很不錯(cuò),他有一串以set開(kāi)頭的函數(shù),如setStrokeColor,setLineCap等函數(shù),給他們傳參數(shù),就可以替代對(duì)應(yīng)的strokeStyle和lineCap等屬性,也就是說(shuō),他的canvas里面就全是函數(shù)而沒(méi)有屬性了那樣的話我就不用判斷是函數(shù)還是是屬性了。但firefox里面沒(méi)有這些,所以我還是只能用前面的思路。

我也把那一串set函數(shù)給放出來(lái)吧

代碼如下:


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


他們的用處一看就懂。你也可以選擇一些加入前面代碼的pro數(shù)組中。

感謝各位的閱讀!關(guān)于“如何突破canvas語(yǔ)法限制讓他支持鏈?zhǔn)秸Z(yǔ)法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI