canvas API ,通俗的canvas基礎知識(六)

這篇是canvas API系列的首尾之做,這篇之後,全部的canvas的屬性和方法就將完了,哦,不對,應該是大部分經常使用的,還有部分不經常使用的屬性和方法,由於種種緣由,就不介紹了,後期的重點就是多寫一點canvas的實踐小實例了,恩,我以爲這纔是最實用的,俗話說一例抵千言啊,廢話很少說,咱們來看看剩下的一些屬性和方法吧!css

一、createPatterncanvas

createPattern(image,"repeat|repeat-x|repeat-y|no-repeat")  在指定的方向上重複指定的元素數組

參數: image指實用的圖片,畫布或者是視頻對象 第二個參數表示重複的方式app

看這後面的參數,很容易想到css中的background-repeat,第一個參數我得說一下,這裏跟background不同,不是引用的圖片地址,而是一個圖片對象,這裏特別注意,咱們分別看一下這些重複方式的表現:this

var aImg = new Image();
aImg.src = '4.jpg';
aImg.onload = function(){
    draw(this);
}
function draw(obj){
    //這裏爲了演示方便,把其餘的先註釋
    //var bg = ctx.createPattern(obj,"repeat");
    //var bg = ctx.createPattern(obj,"repeat-x");
    //var bg = ctx.createPattern(obj,"repeat-y");
    var bg = ctx.createPattern(obj,"no-repeat");
    ctx.fillStyle = bg;
    ctx.fillRect(0,0,400,400);
}

      

恩,跟css的background-repeat的效果是同樣的,那就好理解了,可是canvas是沒有background-position的,恩,這個效果就是這樣,沒什麼好講的!spa

具體效果看這裏 —— canvas 背景重複翻譯

二、gloableCompositeOperation3d

gloableCompositeOperation()  設置或返回新圖像如何繪製到已有的圖像上code

參數:視頻

source-over  默認,在目標圖像上顯示源圖像。

source-atop   在目標圖像頂部顯示源圖像。源圖像位於目標圖像以外的部分是不可見的。

source-in   在目標圖像中顯示源圖像。只有目標圖像內的源圖像部分會顯示,目標圖像是透明的。

source-out   在目標圖像以外顯示源圖像。只會顯示目標圖像以外源圖像部分,目標圖像是透明的。

destination-over   在源圖像上方顯示目標圖像。

destination-atop   在源圖像頂部顯示目標圖像。源圖像以外的目標圖像部分不會被顯示。

destination-in   在源圖像中顯示目標圖像。只有源圖像內的目標圖像部分會被顯示,源圖像是透明的。

destination-out   在源圖像外顯示目標圖像。只有源圖像外的目標圖像部分會被顯示,源圖像是透明的。

lighter   顯示源圖像 + 目標圖像,即相交部分圖形前後填充來增長亮度

copy    顯示源圖像。忽略目標圖像,即只顯示源圖像

xor   使用異或操做對源圖像與目標圖像進行組合,即相交部分爲透明

不經常使用的:

multiply  源圖像的像素乘以目標圖像的像素

screen   

overlay    

darken  加深,相交部分圖形前後填充來下降亮度

lighten  加亮,相交部分圖形前後填充來增長亮度

color-dodge  將底層調到頂層,即將目標圖像調到源圖像上方

color-burn   將底層調到頂層,而後反轉

hard-light   將底層調到頂層,而後 multiply效果與screen疊加

soft-light

difference

exclusion

hue

saturation

color

luminosity

 

因爲英文很差,部分的經常使用的參數的意思不太好解釋,爲了避免誤導你們,我就不翻譯了,若是有英文比較好的,看看這裏 gloableCompositeOperation參數解釋 ,要是能比較清楚的翻譯的話,但願你能把翻譯的意思告訴我,不勝感謝,英語是硬傷啊!不事後面的運行結果我會給到你們參考!

 

參數不少,咱們先看看經常使用的,前面八個很好理解,就是一個反的,首先咱們須要理解,什麼是目標圖形?什麼是源圖形?

目標圖像 = 您已經放置在畫布上的繪圖;源圖像 = 您打算放置到畫布上的繪圖。這是官方的解釋,若是你對這個解釋不理解,咱們能夠這麼理解,就是先畫的圖像是目標圖形,後畫的圖像是源圖像,例如:

//目標圖像
ctx.fillStyle="red";
ctx.fillRect(20,20,75,50);
ctx.globalCompositeOperation="source-over";
//源圖像
ctx.fillStyle="blue";
ctx.fillRect(50,50,75,50);

固然這個gloableCompositeOperation的位置不是固定的,能夠放到目標圖像前面,也能夠放到目標圖像後面,可是不能放到源圖像後面(大家懂的),參數意思如很差理解,看下圖,看看是什麼表現:

var arr = ['source-over','source-atop','source-in','source-out','destination-over','destination-atop','destination-in','destination-out','lighter','copy','xor','multiply','screen','overlay','darken','lighten','color-dodge','color-burn','hard-light','soft-light','difference','exclusion','hue','saturation','color','luminosity'];
        for(var i=0;i<arr.length;i++){
            document.write("<div id='p_" + i + "' style='float:left;'>" + arr[i] + ":<br>");
            var canvas = document.createElement("canvas");
            canvas.width = 120;
            canvas.height = 100;
            canvas.style.border = "1px solid #000";
            canvas.style.marginRight = '10px';
            document.getElementById("p_" + i).appendChild(canvas);
            var ctx = canvas.getContext("2d");
            ctx.fillStyle="red";
            ctx.fillRect(10,10,50,50);
            ctx.globalCompositeOperation=arr[i];
            ctx.beginPath();
            ctx.fillStyle="green";
            ctx.fillRect(30,30,50,50);
            ctx.fill();
            document.write("</div>");
                
        }

紅與綠

紅與藍

具體效果你也能夠看這裏 —— canvas圖形組合模式

裏面的代碼我故意把canvas的代碼留在上面,方便大家查看,不知道你看到這些參數有什麼感想,個人第一感受就是有些熟悉比clip好用,也讓我第一時間想到了這一個效果:

ctx.fillStyle="red";
ctx.arc(150,150,100,0,360*Math.PI/180,false);
ctx.fill();
ctx.globalCompositeOperation="xor";
ctx.beginPath();
ctx.arc(150,150,80,0,360*Math.PI/180,false);
ctx.fill();

若是配合前面的扇形方法,很容易作一個圓形進度條什麼的,固然,還有不少屬性能夠有大的做用,好比說裁切一個圖形,發揮的發達的大腦吧,這裏我就不演示了

 

三、setLineDash

setLineDash(arr)  在畫布上畫一條虛線

參數:arr 表示的是一個數組集合,裏面的參數能夠有多個,這裏面的參數頗有意思,舉個栗子說明:

ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.setLineDash([10,20]);
ctx.stroke();

   

對比代碼看圖,若是有2個參數,則第一個參數表示虛線的線寬,第二個參數表示虛線的線與線的距離,後面一直循環

若是是3個參數呢?

ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.setLineDash([10,20,30]);
ctx.stroke();

  

此時會這樣,第一條線長爲10,而後間距爲20,第2條線長爲30,而後間距爲10,第3條線長20,而後間距爲30,處處爲一個循環,後面重複

那麼4個參數就好理解了,

ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.setLineDash([10,20,30,40]);
ctx.stroke();

 

規律和上面的同樣,只是循環的長度要長一些,更多參數的規則也是這樣的,那麼一個參數是否有效呢

ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.setLineDash([10]);
ctx.stroke();

 

顯然是有效的,此時線寬爲10,間距爲10,這就是華麗的分割線的作法

它還有一個兄弟用法,這個是設置虛線,那麼就會有一個獲取虛線

getLineDash()  獲取當前虛線的樣式

它沒有參數,它獲得的結果就是設置虛線的線寬數組arr,咱們看一下怎麼用:

ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.setLineDash([10]);
var txt = ctx.getLineDash();
ctx.stroke();
ctx.fillStyle = 'red';
ctx.font = "30px Arial";
ctx.fillText(txt,180,140);

ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(400, 100);
ctx.setLineDash([10,20]);
var txt = ctx.getLineDash();
ctx.stroke();
ctx.fillStyle = 'red';
ctx.font = "30px Arial";
ctx.fillText(txt,180,140);

從這兩組圖能夠看出,當只有一個參數數,會默認爲2個同樣的參數

 

四、isPointInPath

isPointInPath(x,y)  指定點是否在路徑區域中,若是在則返回true,不在則返回false

參數: x,y表示指定的座標點

舉個栗子:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        
        ctx.beginPath();
        ctx.fillStyle = 'red';
        ctx.rect(50,50,100,100);
        ctx.fill();

        canvas.onclick = function(ev){
            var ev = ev || event;    
            ctx.clearRect(200,0,200,200);
            var l = ev.clientX - canvas.offsetLeft; 
            var t = ev.clientY - canvas.offsetTop;
            if(ctx.isPointInPath(l,t)){
                ctx.font = "40px Arial";
                ctx.fillText((l+','+t),200,120);
            }
        }

看看這個gif圖,當點擊紅色區域時,我將座標打印出來,若是點擊的地方不在紅色區域,則不顯示座標,具體效果看這裏 —— canvas判斷是否在路徑區域

這裏有一點須要注意,就是在繪製矩形時,不能用fillRect或strokeRect,爲何呢?由於這裏判斷是是否在指定的路徑中,而fillRect或strokeRect此時已經不是路徑了,而是變成了填充過的圖形,因此這裏必須先用Rect()定義一下路徑,再填充,這樣才能回去到指定圖形的路徑,此點須知!

還有一個方法:

isPointInStroke(x,y)  指定點是否在路徑中,若是在則返回true,不在則返回false

此方法跟上面的方法很類似,不一樣點在於,isPointInPath是在一個區域中,不論是用fill仍是stroke,可是isPointInStroke只能用stroke填充,且指定的區域是在線框上,看下面的例子:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        
        ctx.beginPath();
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 5;
        ctx.rect(50,50,100,100);
        ctx.stroke();
        canvas.onclick = function(ev){
            var ev = ev || event;    
            ctx.clearRect(200,0,200,200);
            var l = ev.clientX - canvas.offsetLeft; 
            var t = ev.clientY - canvas.offsetTop;
            if(ctx.isPointInStroke(l,t)){
                ctx.font = "40px Arial";
                ctx.fillText((l+','+t),200,120);
            }
        }

從這個gif中能夠看出端倪來,只有點到線框纔會觸發,具體效果看這裏 —— canvas 判斷是否在線框中

這2個方法的基本用法就是這樣,可是會有一個問題,就是目前只有一個圖形在上面,若是有2個圖形在上面,並且分別的方法不同,好比說,一個是區域路徑,一個是線框路徑,分別點擊他們,彈出不一樣的值,咱們看行不行:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        
        ctx.beginPath();
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 5;
        ctx.rect(50,50,100,100);
        ctx.stroke();
        ctx.closePath();
        ctx.beginPath();
        ctx.fillStyle = 'green';
        ctx.rect(200,50,100,100);
        ctx.fill();
        ctx.closePath();
        
        canvas.onclick = function(ev){
            var ev = ev || event;    
            var l = ev.clientX - canvas.offsetLeft; 
            var t = ev.clientY - canvas.offsetTop;
            if(ctx.isPointInStroke(l,t)){
                console.log('線框路徑');
            }
        }
        canvas.onclick = function(ev){
            var ev = ev || event;    
            var l = ev.clientX - canvas.offsetLeft; 
            var t = ev.clientY - canvas.offsetTop;
            if(ctx.isPointInPath(l,t)){
                console.log('區域路徑');
            }
        }

看看console裏面的提示,當點擊區域路徑的時候,觸發了操做,可是點擊線框路徑時,不管我怎麼點擊,都無濟於事,這是爲何呢?把2圖形的執行順序顛倒一下,發現效果也相反了,說明誰最後繪製就執行誰,其實這也是能夠理解的,由於此時的ctx指的是當前的路徑,它不能分當前路徑一,路徑二什麼的,若是要實現多個圖形執行不一樣的事件,又改如何作呢?因爲實現方法有點複雜,就在這裏留一個思考題?大家先思考一下,該怎麼弄?我會到後期單獨寫一篇文章,專門來講這個的解決方案,供你們參考!

恩,處處全部該講的canvas API就所有講完了,看了這一系列的文章,不知道你是否對canvas有了那麼一點點的感受,是否canvas已經不那麼神祕了,若是你嘴上不說,內心以爲,恩,好像有點感受了,那個人目的就達到了,要是你還能寫一些效果,那恭喜你,距離大神你有近了一步,若是有時間,有能力,我但願能多寫一下有點深度的canvas實例給你們參考,希望能對你們有幫助!

就這樣吧,感謝你們的關注,謝謝!

相關文章
相關標籤/搜索